Хорошее начало, но вы должны немного изменить свой дизайн.
Давайте подумаем о том, кто игрок / змея в вашей игре: в основном это просто список частей тела, поэтому давайте реализуем этознание в коде.Таким образом, у нас должен быть один класс для змеи, который отвечает за отслеживание / рисование / перемещение всех его частей.Это сделает остальную часть кода проще.
Я немного изменил ваш код, чтобы реализовать это, а также удалил некоторые ненужные функции.Вместо того, чтобы менять каждую часть тела каждый раз, когда змея двигается, мы просто создаем новую часть спереди и удаляем последнюю часть в списке.
Я добавил несколько комментариев для дальнейшего объяснения:
import random
import sys
import pygame
from pygame.locals import *
pygame.init()
pygame.mouse.set_visible(False)
grid = list(range(0, 581, 20))
screenW, screenH = 600, 600
wn = pygame.display.set_mode((screenW, screenH))
pygame.display.set_caption("Snake @codingeagle")
class player(object):
def __init__(self, x, y, w, h):
# list of all body parts
self.body = []
# let's keep track of where the first (the head) part is
# so we can easily move and check if we eat food
# since each part is a coordinate and a size, we simply use pygame's Rect class
self.head = pygame.Rect(x, y, w, h)
self.body.append(self.head)
self.xvel = 20
self.yvel = 0
def draw(self, wn):
# drawing is easy
# we have a bunch of body parts, and we draw them all
for part in self.body:
# since we use pygame's Rect class, we can pass it directly to the draw function
pygame.draw.rect(wn, (5, 125, 125), part, 1)
def grow(self):
# when we want to grow, we just create a new body part before our head
new_part = pygame.Rect(self.head.x + self.xvel, self.head.y + self.yvel, 20, 20)
# check if out of screen
if new_part.x >= 600: new_part.x = 0
elif new_part.x < 0: new_part.x = 580
if new_part.y >= 600: new_part.y = 0
elif new_part.y < 0: new_part.y = 580
# and add the new part to the front
self.body.insert(0, new_part)
# the new part is also the new head
self.head = new_part
def move(self):
# now moving is also easy
# we just grow and remove the last part in the list
self.grow()
self.body.pop()
def try_eat(self, food):
# check if your head is in the same place as the food
# Note: that only works because the Rects have the same size
if self.head == food:
self.grow()
# we return True if we eat the fruit so the game knows that we need a new one
return True
snake = player(screenW/2, screenH/2, 20, 20)
# the food is just a rectangle, so let's use pygame's Rect class also here
food = pygame.Rect(grid[random.randint(0, 30)], grid[random.randint(0, 30)], 20, 20)
while True:
# simple standard 3-step main loop:
# 1. handle events
# 2. update the game state
# 3. draw everything
# events
for ev in pygame.event.get():
if ev.type == QUIT:
pygame.quit()
sys.exit()
if ev.type == KEYDOWN:
if ev.key == K_LEFT:
snake.xvel = -20
snake.yvel = 0
if ev.key == K_RIGHT:
snake.xvel = 20
snake.yvel = 0
if ev.key == K_UP:
snake.xvel = 0
snake.yvel = -20
if ev.key == K_DOWN:
snake.xvel = 0
snake.yvel = 20
# game logic
snake.move()
if snake.try_eat(food):
food = pygame.Rect(grid[random.randint(0, 30)], grid[random.randint(0, 30)], 20, 20)
# drawing
wn.fill((0, 0, 0))
pygame.draw.rect(wn, (255, 0, 0), food, 1)
snake.draw(wn)
pygame.display.update()
pygame.time.Clock().tick(10)
![enter image description here](https://i.stack.imgur.com/PE26Q.gif)