How to Chain the Movement of a Snake'S Body

How do I chain the movement of a snake's body?

In general you have to distinguish between 2 different types of snake. In the first case, the snake moves in a grid and every time when the snake moves, it strides ahead one field in the grid. In the other type, the snakes position is not in a raster and not snapped on the fields of the grid, the position is free and the snake slides smoothly through the fields.

In former each element of the body is snapped to the fields of the grid, as the head is. The other is more trick, because the position of a body element depends on the size of the element and the dynamic, previous positions of the snakes head.


First the snake, which is snapped to a grid.

The elements of the snake can be stored in a list of tuples. Each tuple contains the column and row of the snakes element in the grid. The changes to the items in the list directly follow the movement of the snake. If the snake moves, a the new position is add to the head of the list and the tail of the list is removed.

For instance we have a snake with the following elements:

body = [(3, 3), (3, 4), (4, 4), (5, 4), (6, 4)]

When the snakes head moves form (3, 3) to (3, 2), then the new head position is add to the head of the list (body.insert(0, (3, 2)):

body = [(3, 2), (3, 3), (3, 4), (4, 4), (5, 4), (6, 4)]

Finally the tail of the ist is removed (del body[-1]):

body = [(3, 2), (3, 3), (3, 4), (4, 4), (5, 4)]

Sample Image

Minimal example: Sample Image repl.it/@Rabbid76/PyGame-SnakeMoveInGrid

Sample Image

import pygame
import random

pygame.init()
COLUMNS, ROWS, SIZE = 10, 10, 20
screen = pygame.display.set_mode((COLUMNS*SIZE, ROWS*SIZE))
clock = pygame.time.Clock()

background = pygame.Surface((COLUMNS*SIZE, ROWS*SIZE))
background.fill((255, 255, 255))
for i in range(1, COLUMNS):
pygame.draw.line(background, (128, 128, 128), (i*SIZE-1, 0), (i*SIZE-1, ROWS*SIZE), 2)
for i in range(1, ROWS):
pygame.draw.line(background, (128, 128, 128), (0, i*SIZE-1), (COLUMNS*SIZE, i*SIZE-1), 2)

def random_pos(body):
while True:
pos = random.randrange(COLUMNS), random.randrange(ROWS)
if pos not in body:
break
return pos

length = 1
body = [(COLUMNS//2, ROWS//2)]
dir = (1, 0)
food = random_pos(body)

run = True
while run:
clock.tick(5)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT: dir = (-1, 0)
elif event.key == pygame.K_RIGHT: dir = (1, 0)
elif event.key == pygame.K_UP: dir = (0, -1)
elif event.key == pygame.K_DOWN: dir = (0, 1)

body.insert(0, body[0][:])
body[0] = (body[0][0] + dir[0]) % COLUMNS, (body[0][1] + dir[1]) % ROWS
if body[0] == food:
food = random_pos(body)
length += 1
while len(body) > length:
del body[-1]

screen.blit(background, (0, 0))
pygame.draw.rect(screen, (255, 0, 255), (food[0]*SIZE, food[1]*SIZE, SIZE, SIZE))
for i, pos in enumerate(body):
color = (255, 0, 0) if i==0 else (0, 192, 0) if (i%2)==0 else (255, 128, 0)
pygame.draw.rect(screen, color, (pos[0]*SIZE, pos[1]*SIZE, SIZE, SIZE))
pygame.display.flip()

Now the snake with completely free positioning.

We have to track all the positions which the snake's head has visited in a list. We have to place the elements of the snakes body on the positions in the list like the pearls of a chain.

Sample Image

The key is, to compute the Euclidean distance between the last element of the body in the chain and the following positions on the track.
When an new point with a distance that is large enough is found, then an new pearl (element) is add to the chain (body).

dx, dy = body[-1][0]-pos[0], body[-1][1]-pos[1]
if math.sqrt(dx*dx + dy*dy) >= distance:
body.append(pos)

The following function has 3 arguments. track is the list of the head positions. no_pearls is then number of elements of the shakes body and distance is the Euclidean distance between the elements. The function creates and returns a list of the snakes body positions.

def create_body(track, no_pearls, distance):
body = [(track[0])]
track_i = 1
for i in range(1, no_pearls):
while track_i < len(track):
pos = track[track_i]
track_i += 1
dx, dy = body[-1][0]-pos[0], body[-1][1]-pos[1]
if math.sqrt(dx*dx + dy*dy) >= distance:
body.append(pos)
break
while len(body) < no_pearls:
body.append(track[-1])
del track[track_i:]
return body

Minimal example: Sample Image repl.it/@Rabbid76/PyGame-SnakeMoveFree

Sample Image

import pygame
import random
import math

pygame.init()
COLUMNS, ROWS, SIZE = 10, 10, 20
WIDTH, HEIGHT = COLUMNS*SIZE, ROWS*SIZE
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()

background = pygame.Surface((WIDTH, HEIGHT))
background.fill((255, 255, 255))
for i in range(1, COLUMNS):
pygame.draw.line(background, (128, 128, 128), (i*SIZE-1, 0), (i*SIZE-1, ROWS*SIZE), 2)
for i in range(1, ROWS):
pygame.draw.line(background, (128, 128, 128), (0, i*SIZE-1), (COLUMNS*SIZE, i*SIZE-1), 2)

def hit(pos_a, pos_b, distance):
dx, dy = pos_a[0]-pos_b[0], pos_a[1]-pos_b[1]
return math.sqrt(dx*dx + dy*dy) < distance

def random_pos(body):
pos = None
while True:
pos = random.randint(SIZE//2, WIDTH-SIZE//2), random.randint(SIZE//2, HEIGHT-SIZE//2)
if not any([hit(pos, bpos, 20) for bpos in body]):
break
return pos

def create_body(track, no_pearls, distance):
body = [(track[0])]
track_i = 1
for i in range(1, no_pearls):
while track_i < len(track):
pos = track[track_i]
track_i += 1
dx, dy = body[-1][0]-pos[0], body[-1][1]-pos[1]
if math.sqrt(dx*dx + dy*dy) >= distance:
body.append(pos)
break
while len(body) < no_pearls:
body.append(track[-1])
del track[track_i:]
return body

length = 1
track = [(WIDTH//2, HEIGHT//2)]
dir = (1, 0)
food = random_pos(track)

run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT: dir = (-1, 0)
elif event.key == pygame.K_RIGHT: dir = (1, 0)
elif event.key == pygame.K_UP: dir = (0, -1)
elif event.key == pygame.K_DOWN: dir = (0, 1)

track.insert(0, track[0][:])
track[0] = (track[0][0] + dir[0]) % WIDTH, (track[0][1] + dir[1]) % HEIGHT

body = create_body(track, length, 20)

if hit(body[0], food, 20):
food = random_pos(body)
length += 1

screen.blit(background, (0, 0))
pygame.draw.circle(screen, (255, 0, 255), food, SIZE//2)
for i, pos in enumerate(body):
color = (255, 0, 0) if i==0 else (0, 192, 0) if (i%2)==0 else (255, 128, 0)
pygame.draw.circle(screen, color, pos, SIZE//2)
pygame.display.flip()

How do I chain the movement of a snake's body?

In general you have to distinguish between 2 different types of snake. In the first case, the snake moves in a grid and every time when the snake moves, it strides ahead one field in the grid. In the other type, the snakes position is not in a raster and not snapped on the fields of the grid, the position is free and the snake slides smoothly through the fields.

In former each element of the body is snapped to the fields of the grid, as the head is. The other is more trick, because the position of a body element depends on the size of the element and the dynamic, previous positions of the snakes head.


First the snake, which is snapped to a grid.

The elements of the snake can be stored in a list of tuples. Each tuple contains the column and row of the snakes element in the grid. The changes to the items in the list directly follow the movement of the snake. If the snake moves, a the new position is add to the head of the list and the tail of the list is removed.

For instance we have a snake with the following elements:

body = [(3, 3), (3, 4), (4, 4), (5, 4), (6, 4)]

When the snakes head moves form (3, 3) to (3, 2), then the new head position is add to the head of the list (body.insert(0, (3, 2)):

body = [(3, 2), (3, 3), (3, 4), (4, 4), (5, 4), (6, 4)]

Finally the tail of the ist is removed (del body[-1]):

body = [(3, 2), (3, 3), (3, 4), (4, 4), (5, 4)]

Sample Image

Minimal example: Sample Image repl.it/@Rabbid76/PyGame-SnakeMoveInGrid

Sample Image

import pygame
import random

pygame.init()
COLUMNS, ROWS, SIZE = 10, 10, 20
screen = pygame.display.set_mode((COLUMNS*SIZE, ROWS*SIZE))
clock = pygame.time.Clock()

background = pygame.Surface((COLUMNS*SIZE, ROWS*SIZE))
background.fill((255, 255, 255))
for i in range(1, COLUMNS):
pygame.draw.line(background, (128, 128, 128), (i*SIZE-1, 0), (i*SIZE-1, ROWS*SIZE), 2)
for i in range(1, ROWS):
pygame.draw.line(background, (128, 128, 128), (0, i*SIZE-1), (COLUMNS*SIZE, i*SIZE-1), 2)

def random_pos(body):
while True:
pos = random.randrange(COLUMNS), random.randrange(ROWS)
if pos not in body:
break
return pos

length = 1
body = [(COLUMNS//2, ROWS//2)]
dir = (1, 0)
food = random_pos(body)

run = True
while run:
clock.tick(5)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT: dir = (-1, 0)
elif event.key == pygame.K_RIGHT: dir = (1, 0)
elif event.key == pygame.K_UP: dir = (0, -1)
elif event.key == pygame.K_DOWN: dir = (0, 1)

body.insert(0, body[0][:])
body[0] = (body[0][0] + dir[0]) % COLUMNS, (body[0][1] + dir[1]) % ROWS
if body[0] == food:
food = random_pos(body)
length += 1
while len(body) > length:
del body[-1]

screen.blit(background, (0, 0))
pygame.draw.rect(screen, (255, 0, 255), (food[0]*SIZE, food[1]*SIZE, SIZE, SIZE))
for i, pos in enumerate(body):
color = (255, 0, 0) if i==0 else (0, 192, 0) if (i%2)==0 else (255, 128, 0)
pygame.draw.rect(screen, color, (pos[0]*SIZE, pos[1]*SIZE, SIZE, SIZE))
pygame.display.flip()

Now the snake with completely free positioning.

We have to track all the positions which the snake's head has visited in a list. We have to place the elements of the snakes body on the positions in the list like the pearls of a chain.

Sample Image

The key is, to compute the Euclidean distance between the last element of the body in the chain and the following positions on the track.
When an new point with a distance that is large enough is found, then an new pearl (element) is add to the chain (body).

dx, dy = body[-1][0]-pos[0], body[-1][1]-pos[1]
if math.sqrt(dx*dx + dy*dy) >= distance:
body.append(pos)

The following function has 3 arguments. track is the list of the head positions. no_pearls is then number of elements of the shakes body and distance is the Euclidean distance between the elements. The function creates and returns a list of the snakes body positions.

def create_body(track, no_pearls, distance):
body = [(track[0])]
track_i = 1
for i in range(1, no_pearls):
while track_i < len(track):
pos = track[track_i]
track_i += 1
dx, dy = body[-1][0]-pos[0], body[-1][1]-pos[1]
if math.sqrt(dx*dx + dy*dy) >= distance:
body.append(pos)
break
while len(body) < no_pearls:
body.append(track[-1])
del track[track_i:]
return body

Minimal example: Sample Image repl.it/@Rabbid76/PyGame-SnakeMoveFree

Sample Image

import pygame
import random
import math

pygame.init()
COLUMNS, ROWS, SIZE = 10, 10, 20
WIDTH, HEIGHT = COLUMNS*SIZE, ROWS*SIZE
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()

background = pygame.Surface((WIDTH, HEIGHT))
background.fill((255, 255, 255))
for i in range(1, COLUMNS):
pygame.draw.line(background, (128, 128, 128), (i*SIZE-1, 0), (i*SIZE-1, ROWS*SIZE), 2)
for i in range(1, ROWS):
pygame.draw.line(background, (128, 128, 128), (0, i*SIZE-1), (COLUMNS*SIZE, i*SIZE-1), 2)

def hit(pos_a, pos_b, distance):
dx, dy = pos_a[0]-pos_b[0], pos_a[1]-pos_b[1]
return math.sqrt(dx*dx + dy*dy) < distance

def random_pos(body):
pos = None
while True:
pos = random.randint(SIZE//2, WIDTH-SIZE//2), random.randint(SIZE//2, HEIGHT-SIZE//2)
if not any([hit(pos, bpos, 20) for bpos in body]):
break
return pos

def create_body(track, no_pearls, distance):
body = [(track[0])]
track_i = 1
for i in range(1, no_pearls):
while track_i < len(track):
pos = track[track_i]
track_i += 1
dx, dy = body[-1][0]-pos[0], body[-1][1]-pos[1]
if math.sqrt(dx*dx + dy*dy) >= distance:
body.append(pos)
break
while len(body) < no_pearls:
body.append(track[-1])
del track[track_i:]
return body

length = 1
track = [(WIDTH//2, HEIGHT//2)]
dir = (1, 0)
food = random_pos(track)

run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT: dir = (-1, 0)
elif event.key == pygame.K_RIGHT: dir = (1, 0)
elif event.key == pygame.K_UP: dir = (0, -1)
elif event.key == pygame.K_DOWN: dir = (0, 1)

track.insert(0, track[0][:])
track[0] = (track[0][0] + dir[0]) % WIDTH, (track[0][1] + dir[1]) % HEIGHT

body = create_body(track, length, 20)

if hit(body[0], food, 20):
food = random_pos(body)
length += 1

screen.blit(background, (0, 0))
pygame.draw.circle(screen, (255, 0, 255), food, SIZE//2)
for i, pos in enumerate(body):
color = (255, 0, 0) if i==0 else (0, 192, 0) if (i%2)==0 else (255, 128, 0)
pygame.draw.circle(screen, color, pos, SIZE//2)
pygame.display.flip()

Python Snake Game snake does not follow

See the answer referenced in your question How do I chain the movement of a snake's body?.

You need to use the 2nd solution and adjust the function that creates the snake body. The new function needs to update the positions of the Snakes body Sprites:

def update_body(track, distance):
body = snakegroup.sprites()
no_parts = len(body)
body[0].update(*track[0])
track_i = 1
next_i = 1
for i in range(1, no_parts):
while track_i < len(track):
pos = track[track_i]
track_i += 1
dx, dy = body[i-1].x_pos-pos[0], body[i-1].y_pos-pos[1]
if math.sqrt(dx*dx + dy*dy) >= distance:
body[i].update(*pos)
next_i = i+1
break
while next_i < no_parts:
body[next_i].update(*track[-1])
next_i += 1
del track[track_i:]
return body

Example based on your (revised) code:

Sample Image

import pygame
import math
from random import randint
from sys import exit

pygame.init()
clock = pygame.time.Clock()
disp_surface = pygame.display.set_mode(size = (610, 700))

class Snake(pygame.sprite.Sprite):
def __init__(self, x_pos = 300, y_pos = 300):
#Access the super class of Sprite
super().__init__()
#self.image = pygame.image.load("square1.png").convert_alpha()
self.image = pygame.Surface((20, 20), pygame.SRCALPHA)
pygame.draw.circle(self.image, (0, 255, 0), (10, 10), 10)
self.x_pos = x_pos
self.y_pos = y_pos
self.rect = self.image.get_rect(x = x_pos, y = y_pos)
def update(self, x_pos, y_pos):
self.x_pos = x_pos
self.y_pos = y_pos
self.rect = self.image.get_rect(center = (x_pos, y_pos))

class Food(pygame.sprite.Sprite):
"""class to control food action"""
def __init__(self):
super().__init__() #access the Sprite super class methods
#self.image = pygame.image.load("food1.png").convert_alpha()
self.image = pygame.Surface((20, 20), pygame.SRCALPHA)
pygame.draw.circle(self.image, (255, 0, 0), (10, 10), 10)
x_pos = randint(50,600)
y_pos = randint(50,650)
self.rect = self.image.get_rect(x = x_pos,y = y_pos)
def update(self, pos):
x_pos = randint(50,600)
y_pos = randint(50,650)
self.rect = self.image.get_rect(x = x_pos,y = y_pos)


def update_body(track, distance):
body = snakegroup.sprites()
no_parts = len(body)
body[0].update(*track[0])
track_i = 1
next_i = 1
for i in range(1, no_parts):
while track_i < len(track):
pos = track[track_i]
track_i += 1
dx, dy = body[i-1].x_pos-pos[0], body[i-1].y_pos-pos[1]
if math.sqrt(dx*dx + dy*dy) >= distance:
body[i].update(*pos)
next_i = i+1
break
while next_i < no_parts:
body[next_i].update(*track[-1])
next_i += 1
del track[track_i:]
return body

snakegroup = pygame.sprite.Group()
original_snake = Snake()
snakegroup.add(original_snake)
track = [(original_snake.x_pos, original_snake.y_pos)]

foods = pygame.sprite.GroupSingle()
foods.add(Food())

direction = (0, 0)
speed = 1
run = True
while run:
for eachevent in pygame.event.get():
if eachevent.type == pygame.QUIT:
run = False
if eachevent.type == pygame.KEYDOWN:
if eachevent.key == pygame.K_LEFT and direction[0] != 1:
direction = (-1, 0)
if eachevent.key == pygame.K_RIGHT and direction[0] != -1:
direction = (1, 0)
if eachevent.key == pygame.K_UP and direction[1] != 1:
direction = (0, -1)
if eachevent.key == pygame.K_DOWN and direction[1] != -1:
direction = (0, 1)

track.insert(0, track[0][:])
track[0] = (track[0][0] + direction[0] * speed) % disp_surface.get_width(), (track[0][1] + direction[1] * speed) % disp_surface.get_height()
update_body(track, 20)

if pygame.sprite.spritecollideany(foods.sprite, snakegroup):
foods.empty()
foods.add(Food())
last_part = snakegroup.sprites()[-1]
snakegroup.add(Snake(last_part.x_pos, last_part.y_pos))
speed = min(10, speed + 1)

disp_surface.fill((64,64,64))
snakegroup.draw(disp_surface)
foods.draw(disp_surface)
pygame.display.update()
clock.tick(120)

Snake bodies not appending to snake correctly

You have to track the positions which have been met by the snake. Add a list attribute self.position to the class Snake:

class Snake:

def __init__(self, x, y):
# [...]

self.positions = [(self.x, self.y)]

# [...]

Add the new position to the list when the snake moves:

class Snake:
# [...]

def update(self):

# move
if self.direction == 1:
self.y -= self.speed
if self.direction == 2:
self.x += self.speed
if self.direction == 3:
self.y += self.speed
if self.direction == 4:
self.x -= self.speed

# add ne position
if self.x != self.positions[0][0] or self.y != self.positions[0][1]:
self.positions.insert(0, (self.x, self.y))

Update the x and y coordinate of the body along the stored positions in events. Define a distance between the parts of the body (e.g. 35). And use a method getPos to get the position of a part, by its index:

class Snake:
# [...]

def events(self):
# change direction on key press
self.keys = pygame.key.get_pressed()

if self.keys[pygame.K_UP] and self.direction != 3:
self.direction = 1
if self.keys[pygame.K_DOWN] and self.direction != 1:
self.direction = 3
if self.keys[pygame.K_LEFT] and self.direction != 2:
self.direction = 4
if self.keys[pygame.K_RIGHT] and self.direction != 4:
self.direction = 2

if self.rect.colliderect(food.rect):
self.speed += 0.5
food.x = random.randint(100, WIN_WIDTH - 125)
food.y = random.randint(150, WIN_HEIGHT - 175)
self.score += 5
self.colliide = False
self.bodies.append(Body(0, 0))

# Move the end bodies first in reverse order
for i in range(len(self.bodies)):
pos = self.getPos(i+1, 35, i == len(self.bodies)-1)
snake.bodies[i].x = pos[0]
snake.bodies[i].y = pos[1]
snake.bodies[i].draw()

The arguments to method getPos are the index of the body part, the distance between the parts and delToEnd. delToEnd becomes true, when the last part of the body is get and indicates, that the positions at the end of the list, which are "behind" the last part of the snake can be deleted:

class Snake:
# [...]

def getPos(self, i, dist, delToEnd):
lenToI = i * dist
lenAct = 0
px, py = self.positions[-1]
for j in range(len(self.positions)-1):
px, py = self.positions[j]
pnx, pny = self.positions[j+1]
delta = math.sqrt((px-pnx)*(px-pnx) + (py-pny)*(py-pny))
lenAct += delta
if lenAct >= lenToI:
w = (lenAct - lenToI) / delta
px = pnx - (pnx-px) * w
py = pny - (pny-py) * w
if delToEnd:
del self.positions[j:]
break
return (round(px), round(py))

Sample Image

How to add snake body in pygame

The comments below might sound harsh, and I've tried to write them in a neutral way simply pointing out facts and state them as they are. If you are truly a new programmer, this is a pretty good project to learn from and you've done quite good to come this far. So keep an mind that these comments are not meant to be mean, but objective and always comes with a proposed solution to make you an even better programmer, not to bash you.

I also won't go into detail in the whole list as a body thing, others have covered it but I'll use it also in this code.


Here's the result, and blow is the code and a bunch of pointers and tips.

Sample Image


Never mix logic in one function

You've also bundled the food into the player object, which is a big no-no. As well as render logic in the movement logic. So I propose a re-work in the shape of even more OOP where food and player are two separate entities and a function for each logical operation (render, move, eat, etc..).

So I restructured it into this logic:

Sample Image

While I'm at it, I also re-worked the movement mechanics a bit, to use less lines and logic to produce the same thing. I also removed all this logic:

self.r = random.randint(0,500)
while True:
if self.r % 25 == 0:
break
else:
self.r = random.randint(0,500)
continue

And replaced it with this, which does the exact same thing, but uses built-ins to produce it. And hopefully the functions/variables are more descriptive than a rogue while loop.

self.r = random.choice(range(0, 500, 25))

And the final result would look something like this:

import random
import pygame
from pygame import *
import sys
import os
import time

# Constants (Used for bitwise operations - https://www.tutorialspoint.com/python/bitwise_operators_example.htm)
UP = 0b0001
DOWN = 0b0010
LEFT = 0b0100
RIGHT = 0b1000

###objects
class Food:
def __init__(self, window, x=None, y=None):
self.window = window
self.width = 25
self.height = 25
self.x, self.y = x, y
if not x or not y: self.new_position()

def draw(self):
pygame.draw.rect(self.window, (255,0,0), (self.x, self.y, 25, 25))

def new_position(self):
self.x, self.y = random.choice(range(0, 500, 25)), random.choice(range(0, 500, 25))

class Snake:
def __init__(self, window):
self.width = 25
self.width = 25
self.height = 25
self.window = window
self.vel = 25
self.update = pygame.display.update()

start_position = random.choice(range(0, 500, 25)), random.choice(range(0, 500, 25))
self.body = [start_position]
self.direction = RIGHT

def move(self, window):
self.keys = pygame.key.get_pressed()
# since key-presses are always 1 or 0, we can multiply each key with their respective value from the
# static map above, LEFT = 4 in binary, so if we multiply 4*1|0 we'll get binary 0100 if it's pressed.
# We can always safely combine 1, 2, 4 and 8 as they will never collide and thus always create a truth map of
# which direction in bitwise friendly representation.
if any((self.keys[pygame.K_UP], self.keys[pygame.K_DOWN], self.keys[pygame.K_LEFT], self.keys[pygame.K_RIGHT])):
self.direction = self.keys[pygame.K_UP]*1 + self.keys[pygame.K_DOWN]*2 + self.keys[pygame.K_LEFT]*4 + self.keys[pygame.K_RIGHT]*8

x, y = self.body[0] # Get the head position, which is always the first in the "history" aka body.
self.body.pop() # Remove the last object from history

# Use modolus to "loop around" when you hit 500 (or the max width/height desired)
# as it will wrap around to 0, try for instance 502 % 500 and it should return "2".
if self.direction & UP:
y = (y - self.vel)%500
elif self.direction & DOWN:
y = (y + self.vel)%500
elif self.direction & LEFT:
x = (x - self.vel)%500
elif self.direction & RIGHT:
x = (x + self.vel)%500 # window.width
self.body.insert(0, (x, y))

defeat(self, food):
x, y = self.body[0] # The head
if x >= food.x and x+self.width <= food.x+food.width:
if y >= food.y and y+self.height <= food.y+food.height:
self.body.append(self.body[-1])
return True
return False

def draw(self):
for x, y in self.body:
pygame.draw.rect(self.window, (0,255,0), (x, y, self.width, self.width))

##variables
clock = pygame.time.Clock()

##game
pygame.init()
window = pygam

Related Topics



Leave a reply



Submit