[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Odd behaviour of sprites in a list - newbie help please?



On 24.06.2019 17:19, Adam Coombes wrote:
I've created a list of sprites to try and make a basic 'snake' game. The idea is to shuffle each sprite to the position of the next, starting at the end of the tail, and then move the head. As I append new tail pieces, they should 'snake' along. However, when I move the head sprite ( Snake[0] in my list 'Snake'), they all seem to move to the same position. Even when I omit the line that moves them along by commenting out 'Snake[tail] = Snake[tail-1]' in my for loop, it still moves every sprite in the list Snake[] to the same place as Snake[0], which is inexplicable to me as I'm not even moving them then. Can anyone point out my mistake please? This is just a learner project, but it's driving me nuts.

import pygame, sys
from pygame.locals import*
import random
#colours========================================================
BLACK = (0,0,0)
WHITE = (255,255,255)
RED = (255,0,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
PURPLE = (128,0,128)
GREY = (128,128,128)
YELLOW = (255,255,0)
pygame.init()
Height = 1920
Width = 1080
score = 0
basicfont = pygame.font.SysFont(None, 50)
Score = basicfont.render("Score: " + str(score), True, WHITE, GREEN)
ScoreRect = Score.get_rect()
ScoreRect.left =560
ScoreRect.bottom = 130
moveLeft = False
moveRight = False
moveUp = False
moveDown = False
PlayerSpeed = 40
def GameBoard():
    pygame.display.set_caption("Snake_Game")
    Window.fill(GREEN)
    pygame.draw.line(Window, BLACK,(560,140),(1360,140),4)
    pygame.draw.line(Window, BLACK,(560,140),(560,940),4)
    pygame.draw.line(Window, BLACK,(1360,140),(1360,940),4)
    pygame.draw.line(Window, BLACK,(560,940),(1360,940),4)
#GAME===========================================================
mainClock = pygame.time.Clock()
Window = pygame.display.set_mode((Height,Width), 0, 32)
#PLayer=========================================================                    
Snake =[]
Snake.append (pygame.Rect(940,500,40,40))
playerImage = pygame.image.load("Snake.GIF")
Window.blit(playerImage,Snake[0])
#Apple==========================================================
def PlotApple():
    global AppleX
    global AppleY
    global Apple
    AppleX = random.randint(560,1320)
    AppleY = random.randint(140,900)
    Apple = pygame.Rect(AppleX,AppleY,40,40)
PlotApple()
AppleImage = pygame.image.load("Apple.GIF") 
Window.blit(AppleImage,Apple)
pygame.display.update()
#================================================================
while True:
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                pygame.quit()
        #===================================================
        if event.type == KEYDOWN:
            #===============================================
            if event.key == K_LEFT:
                moveRight = False
                moveLeft = True
                moveDown = False
                moveUp = False
            #===============================================
            if event.key == K_RIGHT:
                moveLeft = False
                moveRight = True
                moveDown = False
                moveUp = False
            #===============================================
            if event.key == K_UP:
                moveDown = False
                moveUp = True
                moveLeft = False
                moveRight = False
            #===============================================
            if event.key ==K_DOWN:
                moveUp = False
                moveDown = True
                moveLeft = False
                moveRight = False
            #KEYUP===============================================
            if event.type == KEYUP:
            #===================================================
                if event.key == K_ESCAPE:
                    pygame.quit()
                    sys.exit()
    #MovePlayer===================================================
    mainClock.tick(10)
    GameBoard()
    for tail in range (len(Snake)-1,0,-1):
        print(Snake,tail)
        Snake[tail] = Snake[tail-1]
        Window.blit(playerImage,Snake[tail])
        print(Snake,tail)
    if moveDown:
        Snake[0].top += PlayerSpeed
    if moveUp:
        Snake[0].top -= PlayerSpeed
    if moveLeft:
        Snake[0].left -= PlayerSpeed
    if moveRight:
        Snake[0].right += PlayerSpeed
    if Snake[0].bottom >=940 or Snake[0].top<+140 or Snake[0].left<=560 or Snake[0].right>=1360:
        pygame.quit()
    Score = basicfont.render("Score:" + str(score), True, WHITE, GREEN)
    Window.blit(playerImage,Snake[0])
    Window.blit(AppleImage,Apple)
    Window.blit(Score,ScoreRect)
    if Snake[0].colliderect(Apple):
        score = score +50
        Snake.append (Snake[0])
        PlotApple()
    pygame.display.update()


Hi

flying over your code (without executing it) I think these loop is setup wrongly:


    for tail in range (len(Snake)-1,0,-1):
        print(Snake,tail)
        Snake[tail] = Snake[tail-1]

Because the for loop will generate 'tail' sequence as: 9, 8, 7, 6, 5, 4, 3, 2, 1
But then you do: Snake[tail] = Snake[tail-1]   which is using concrete indices: Snake[9] = Snake[9-1]
...

So this means that if you had a Snake like this ['a', 'b', 'c', 'd'] this loop will transform it to:
['a', 'a', 'b', 'c']
and so on until its all 'a': ['a', 'a', 'a', 'a']
which is what you see (all seem to be at index 0 because only this sprite exists in the list).

...

I wondered and run the code. It seems there are some other issues.

1. I would suggest to draw all elements of the snake not only the head (so you see where they are actually placed and the snake should be growing with each apple eaten).
2. I would think about object references. If a rect1 is put into a list at index 0 and then Snake[1] = Snake[0] is executed the same object is now at index 0 and 1. This means that if Snake[0].x is changed its also changed for Snake[1] (because both are actually the same object). So adding a tail part or moving the last to the front should be carefully done. I would think about moving the last part to the front (don't forget to update the coordinates accordingly because next lines in the code move the head relative to the old position).

I hope I gave you some pointers where to look.

~DR0ID