0

I'm trying to build the snake game in pygame. I am representing the snake using a two dimensional vector.
I have written this code to move the snake but for some reason it doesn't work. Instead of the snake moving, the snake just gets larger. I want the snake to move and keep the same size it has.

def move_snake(self):
    body_copy = self.body[:-1]
    body_copy.insert(0, body_copy[0] + self.direction)
    self.body = body_copy[:]

self.direction is just another vector and self.body is the two dimensional vector i was talking about.

I don't know if the error is in that move_snake method, so I am also posting here my full code.

import pygame
import sys
import random
from pygame.math import Vector2


pygame.init()
pygame.display.set_caption("Snake")

DARK_GREEN = (126, 166, 114)
STEEL_BLUE = (70, 130, 180)


CELL_SIZE = 40
CELL_NUMBER = 20
WIDTH, HEIGTH = CELL_SIZE * CELL_NUMBER, CELL_SIZE * CELL_NUMBER
FPS = 60
SCREEN = pygame.display.set_mode((WIDTH, HEIGTH))
SCREEN.fill((175, 215, 70))


class Snake:
    def __init__(self):
        self.body = [Vector2(5, 10), Vector2(6, 10), Vector2(7, 10)]
        self.direction = Vector2(1, 0)

    def draw_snake(self):
        for block in self.body:
            x_pos = int(block.x * CELL_SIZE)
            y_pos = int(block.y * CELL_SIZE)
            block_rect = pygame.Rect(x_pos, y_pos, CELL_SIZE, CELL_SIZE)
            pygame.draw.rect(SCREEN, STEEL_BLUE, block_rect)

    def move_snake(self):
        body_copy = self.body[:-1]
        body_copy.insert(0, body_copy[0] + self.direction)
        self.body = body_copy[:]


class Fruit:
    def __init__(self):
        self.x = random.randint(0, CELL_NUMBER - 1)
        self.y = random.randint(0, CELL_NUMBER - 1)

        self.pos = Vector2(self.x, self.y)

    def draw_fruit(self):
        fruit_rect = pygame.Rect(
            int(self.pos.x * CELL_SIZE), int(self.pos.y * CELL_SIZE), CELL_SIZE, CELL_SIZE)
        pygame.draw.rect(SCREEN, DARK_GREEN, fruit_rect)


def main():
    run = True
    clock = pygame.time.Clock()

    while run:
        clock.tick(FPS)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                sys.exit()
            if event.type == SCREEN_UPDATE:
                snake.move_snake()

        fruit.draw_fruit()
        snake.draw_snake()

        pygame.display.update()


fruit = Fruit()
snake = Snake()

SCREEN_UPDATE = pygame.USEREVENT
pygame.time.set_timer(SCREEN_UPDATE, 150)


main()
António Rebelo
  • 186
  • 1
  • 13
  • are you sure the screen gets cleared at some point? I am not familiar with pygame, but unless something that I am not seeing removes the last frame from the screeen, you would just incrementally keep drawing an ever increasing snake – gnight Apr 08 '22 at 22:48
  • @gnight I'm not sure I fully understand what you mean but I thought that ```body_copy = self.body[:-1]``` this removed from the body of the snake the last cell and then the line after that one added another one at the position where it is supposed to go – António Rebelo Apr 08 '22 at 22:50
  • My guess is that your datastructures are sound. The data of the snake behaves as intended, only you are never removing the snake you drew last frame. First frame: one snake. Second frame: snake moved and is drawn on new location but First frame snake is still visible. Try painting the snake with a different color in each `draw_snake` call. If I am right, your snake will have a rainbow tail – gnight Apr 08 '22 at 23:00
  • @gnight that makes sense, however in pygame you update the display of the screen. I am not sure how to change the color of the snake each time it is drawn tho. thank you anyways – António Rebelo Apr 08 '22 at 23:05

1 Answers1

1

You need to have screen.fill(color) (the one argument is the background color of your game) somewhere in your loop before drawing anything or else it won't clear the screen (in other words, it'll keep whatever it drew last frame onscreen).

Seth
  • 2,214
  • 1
  • 7
  • 21
  • But I thougth ```pygame.display.update()``` dealt with that issue, no? – António Rebelo Apr 09 '22 at 10:21
  • 1
    @AntónioRebelo no it doesn't because what if you didn't want it to clear the screen after every draw or you wanted the background a different color than black? – Seth Apr 09 '22 at 14:44