bgly
bgly

Reputation: 177

Python's list object do not allow index value change

I'm creating my first game using Python and Pygame. It consists on objects falling to the ground and an object controlled by the player catching them. However, It gives me an Exception when the falling object hits the ground:

Traceback (most recent call last):
  File "/home/me/Chest/game.py", line 79, in <module>
    resetShirtPosition()
  File "/home/me/Chest/game.py", line 35, in resetShirtPosition
    shirtPosition[0] = random.randint(0, DISPLAY_WIDTH - shirt_size[0])
TypeError: 'tuple' object does not support item assignment

Seems like it doesn't allow the vector to change by index. Which I find odd because I'm not assigning shirtPosition with a tuple but with a list. Besides that I'm changing the chestPosition the same way and it moves without crashing.

Here is my code:

import pygame, random, os

pygame.init()

DISPLAY_WIDTH, DISPLAY_HEIGHT = 1600, 900

clock   = pygame.time.Clock()
gamedisplay = pygame.display.set_mode((DISPLAY_WIDTH, DISPLAY_HEIGHT))

chest_imag  = pygame.image.load(os.path.join("catcher.png"))
shirt_red   = pygame.image.load(os.path.join("shirt_red.png"))
background  = pygame.image.load(os.path.join("background.png"))
shirt_blue  = pygame.image.load(os.path.join("shirt_blue.png"))
shirt_green = pygame.image.load(os.path.join("shirt_green.png"))

shirt = shirt_blue

chest_size = chest_imag.get_size()
chestPosition = [DISPLAY_WIDTH / 2, DISPLAY_HEIGHT - chest_size[1]]

shirt_blue_size = shirt_blue.get_size()
shirt_size      = shirt_blue_size

shirtPosition = [random.randint(0, DISPLAY_WIDTH - shirt_size[0]), 0]

dX, dY = 0, 20
score = 0
fallWidth = fallHeight = 100
COLLISION_LEVEL_LINE = DISPLAY_HEIGHT - chest_size[1]

onGame = True
collide = False

# **************** Exception happens here *******************
def resetShirtPosition():
    shirtPosition[0] = random.randint(0, DISPLAY_WIDTH - shirt_size[0])
    shirtPosition[1] = 0

def hitCollisionLevelLine():
    return (shirtPosition[1] + shirt_size[1]) >= COLLISION_LEVEL_LINE

def hitGround():
    return (shirtPosition[1] + shirt_size[1]) >= DISPLAY_HEIGHT

def hitHorizontalEdge():
    willTouchLeftEdge = (chest_size[0] + dX) < 0
    willTouchRightEdge = (chest_size[0] + dX) > (DISPLAY_WIDTH  - chest_size[0])
    return willTouchLeftEdge or  willTouchRightEdge

def collides():
    touchFromLeft = shirtPosition[0] > (chestPosition[0] - shirt_size[0])
    touchFromRight = shirtPosition[0] < (chestPosition[0] + chest_size[0])
    return touchFromLeft and touchFromRight

while onGame:
    clock.tick(60)

    # action
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_a:
                dX = -20
            elif event.key == pygame.K_d:
                dX = 20
        elif event.type == pygame.KEYUP:
            dX = 0
        elif event.type == pygame.QUIT:
            onGame = false

    # logic
    if hitCollisionLevelLine():
        hasCollided = collides()
        if hasCollided:
            collide = False
            score = score + 1
            print score
            resetShirtPosition()

    if hitGround():
        resetShirtPosition()

    if hitHorizontalEdge():
        dX = 0

    # update positions and draw
    chestPosition = (chestPosition[0] + dX, chestPosition[1])
    shirtPosition = (shirtPosition[0], shirtPosition[1] + dY)

    gamedisplay.blit(background , (0, 0))
    gamedisplay.blit(shirt_blue, shirtPosition)
    gamedisplay.blit(chest_imag, chestPosition)

    pygame.display.flip()

I've posted all my code because I'd also like if you could hand me some tips to improve it, from code writting to improve-performance tricks. For example, I'm thinking about putting my images in a Dictionary and get them by its key (name). Thank you.

Upvotes: 1

Views: 80

Answers (1)

Kenstars
Kenstars

Reputation: 660

On the following line :

shirtPosition = (shirtPosition[0], shirtPosition[1] + dY)

you have reassigned shirtPosition as a tuple, this is causing your problem. Do convert this into a list object instead and your issue will be resolved.

Upvotes: 3

Related Questions