Python Forum
[PyGame] Snake game: how to get an instance for my snake's body multiple times?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] Snake game: how to get an instance for my snake's body multiple times?
#1
i am totaly begginer in programming and i am learning all by myself,sooo ty in andvance for any help. i am trying to make a snake game using pygame.My problem is that when the game starts i have the whole body of the snake and when the snake starts to move it desappears and i have only the head and the 1st block of the body. i know that i dont need all this complex code for such a simple game, but i want to upgrade it as much as i can adding more and more things so i can train myself to learn better a higher lvl of logic for my future projects. in my new game def i use my BODY_LIST to create my instace multiple times but when i am doint the same thing in the class it doesn't work...

In the main.py def new() i have this " for pos in BODY_LIST: self.body = Body(self,pos[0],pos[1]) " and it gives me the whole snake at the beggining.Then in sprites.py in Head class and Body class i have this print(self.pos_list) checkers and it seems that both work fine and i am getting both list printed as i want. Soooo...why in Body class movement() works fine but only for the first block of the body(that means the lost indexof my list)


this is my main:
from sprites import *
from config import *
import sys

class Game:

    def __init__(self):
        pygame.init()

        self.running = True
        self.screen = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
        self.clock = pygame.time.Clock()

    def new(self):
        self.playing = True
        self.all_sprites = pygame.sprite.LayeredUpdates()
        self.blocks = pygame.sprite.LayeredUpdates()
        self.target = pygame.sprite.LayeredUpdates()
        self.ground = pygame.sprite.LayeredUpdates()
        self.head = Head(self,32,24,)
        for pos in BODY_LIST:
         self.body = Body(self,pos[0],pos[1])

    def events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.playing = False
                self.running = False

    def update(self):
        self.all_sprites.update()

    def draw(self):
        self.screen.fill(BLACK)
        self.all_sprites.draw(self.screen)
        self.clock.tick(PLAYER_SPEED)
        pygame.display.update()

    def main(self):
        while self.playing:

            self.events()
            self.update()
            self.draw()
        self.running = False
    def game_over(self):
        pass
    def intro(self):
        pass

g = Game()
#g.intro()
g.new()
while g.running:
    g.main()
    #g.game_over()
pygame.quit()
sys.exit()
this my sprites.py :
from config import *
import math
import random

class Head(pygame.sprite.Sprite):
    def __init__(self,game, x, y):
        self.game = game
        self.groups = self.game.all_sprites
        pygame.sprite.Sprite.__init__(self,self.groups)
        self.clock = pygame.time.Clock()
        # Head
        self.x = x * TILESIZE
        self.y = y * TILESIZE
        self.width = TILESIZE
        self.height = TILESIZE
        self.move= [0,0]
        self.pos_list= POS_LIST

        self.image = pygame.Surface([self.width, self.height])
        self.image.fill(RED)
        self.rect = self.image.get_rect()
        self.rect.x = self.x
        self.rect.y = self.y

    def update(self):
        self.movement()
        self.rect = self.rect.move(self.move)
        if self.game.head.move != [0, 0]:
         self.pos_list.append([int(self.rect.x/10), int(self.rect.y/10)])
         if len(self.pos_list) > SNAKE_SIZE :
          self.pos_list.pop(0)

         print(self.pos_list)

    def movement(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT] and self.move != (TILESIZE, 0) :
            self.move = (-TILESIZE, 0)
        if keys[pygame.K_RIGHT] and self.move != (-TILESIZE, 0):
            self.move = (TILESIZE, 0)
        if keys[pygame.K_UP] and self.move != (0, TILESIZE):
            self.move = (0, -TILESIZE)
        if keys[pygame.K_DOWN] and self.move != (0, -TILESIZE):
            self.move = (0, TILESIZE)

class Body(pygame.sprite.Sprite):
    def __init__(self,game,x,y):
        self.game = game
        self.groups = self.game.all_sprites
        pygame.sprite.Sprite.__init__(self,self.groups)

        self.pos_list =POS_LIST[1:-1]
        self.x = x * TILESIZE
        self.y = y * TILESIZE
        self.width = TILESIZE
        self.height = TILESIZE
        self.move = [0, 0]

        self.image = pygame.Surface([self.width, self.height])
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.rect.x = self.x
        self.rect.y = self.y

    def update(self):

        self.pos_list=POS_LIST[1:-1]
        self.movement()

    def movement(self):
      if self.game.head.move != [0, 0]:
             for pos in self.pos_list:
              self.rect = pos[0]*10,pos[1]*10
             print(self.pos_list)
and this is my config:

WIN_HEIGHT = 480
TILESIZE = 10

RED = (255,0,0)
BLUE = (0,0,255)
BLACK = (0,0,0)
GREEN=(0,255,0)

FPS = 60

PLAYER_LAYER = 1
PLAYER_SPEED = 15
POS_LIST = [[28, 24], [29, 24], [30, 24], [31, 24], [32, 24]]
BODY_LIST = POS_LIST[1:-1]
SNAKE_SIZE=5
Reply
#2
self.body can only reference one Body object, so self.body is only the last Body sprite.
        for pos in BODY_LIST:
         self.body = Body(self,pos[0],pos[1])
If you wanted all the Body sprites you could do something like this:
self.body = [Body(self, x, y) for x, y in  POS_LIST[1:-1]]
But I don't think this matters because you don't ever use self.body, you use self.all_sprites.

The real problem is this code in Body.
    def update(self):
 
        self.pos_list=POS_LIST[1:-1]
        self.movement()
 
    def movement(self):
      if self.game.head.move != [0, 0]:  # Indenting should always be 4 spaces, never 1
             for pos in self.pos_list:
              self.rect = pos[0]*10,pos[1]*10
             print(self.pos_list)
If there are 3 positions in self.pos_list this code moves the same Body sprite 3 times. If you have 3 Body sprites all three are moved 3 times TO THE SAME FINAL POSITION (self.pos_list[-1]). That is why it looks like all but one of the Body sprites have disappeared, they are all sitting on top of each other.

To fix the problem you need to change how Body works. If it is only a single sprite it will have to know what index to use from the position list and it only updates itself. No "for pos in self.pos_list".
Reply
#3
(Jan-25-2022, 05:53 PM)deanhystad Wrote: self.body can only reference one Body object, so self.body is only the last Body sprite.
        for pos in BODY_LIST:
         self.body = Body(self,pos[0],pos[1])
If you wanted all the Body sprites you could do something like this:
self.body = [Body(self, x, y) for x, y in  POS_LIST[1:-1]]
But I don't think this matters because you don't ever use self.body, you use self.all_sprites.

The real problem is this code in Body.
    def update(self):
 
        self.pos_list=POS_LIST[1:-1]
        self.movement()
 
    def movement(self):
      if self.game.head.move != [0, 0]:  # Indenting should always be 4 spaces, never 1
             for pos in self.pos_list:
              self.rect = pos[0]*10,pos[1]*10
             print(self.pos_list)
If there are 3 positions in self.pos_list this code moves the same Body sprite 3 times. If you have 3 Body sprites all three are moved 3 times TO THE SAME FINAL POSITION (self.pos_list[-1]). That is why it looks like all but one of the Body sprites have disappeared, they are all sitting on top of each other.

To fix the problem you need to change how Body works. If it is only a single sprite it will have to know what index to use from the position list and it only updates itself. No "for pos in self.pos_list".

ty mate...
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  how to add segments to the snake body blacklight 1 2,881 Sep-13-2023, 07:33 AM
Last Post: angelabarrios
  help with snake game blacklight 3 2,603 Jul-30-2020, 01:13 AM
Last Post: nilamo
  Adding persistent multiple levels to game michael1789 2 2,409 Nov-16-2019, 01:15 AM
Last Post: michael1789
  Snake Game - obstacle problem Samira 3 5,627 Oct-31-2019, 02:58 PM
Last Post: Samira
  [PyGame] Made my first Python program: Snake. Please help me improve it andrerocha1998 7 6,147 Feb-19-2019, 07:08 PM
Last Post: Windspar
  Creating Snake game in Turtle Shadower 1 8,649 Feb-11-2019, 07:00 PM
Last Post: woooee
  [PyGame] Basic Snake game (using OOP) PyAlex 1 12,546 Sep-10-2018, 09:02 PM
Last Post: Mekire
  [PyGame] Snake not changing directions in Snake Game Bjdamaster 4 4,945 Aug-13-2018, 05:09 AM
Last Post: Bjdamaster
  [PyGame] Snake controls not working jakegold98 5 6,400 Dec-12-2017, 01:45 AM
Last Post: Windspar

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020