проблема со змейкой на pygame
Написал игру со спрайтами, через классы. При столкновении с яблоком змейка увеличивается, но также сильно ускоряется. В чём проблема?
from pygame import *
import random
#! Размер клетки 30 на 30 пикселей
class GameSprite(sprite.Sprite):
def __init__(self, picture, w, h, x, y):
super().__init__()
self.image = transform.scale(image.load(picture), (w,h))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def draw(self):
window.blit(self.image, (self.rect.x, self.rect.y))
class Snake(GameSprite):
def __init__(self, picture, w, h, x, y, x_speed, y_speed):
GameSprite.__init__(self, picture, w, h, x, y)
self.x_speed = x_speed
self.y_speed = y_speed
def update(self):
if self.rect.x >= 0 and self.rect.x <= 600:
self.rect.x += self.x_speed
if self.rect.y >= 0 and self.rect.y <= 600:
self.rect.y += self.y_speed
class Apple(GameSprite):
def __init__(self, picture, w, h, x, y):
GameSprite.__init__(self, picture, w, h, x, y)
def spawn(self,foodx,foody):
window.blit(self.image, (foodx,foody))
# Размеры экрана 600 на 600
width = 600
height = 600
window = display.set_mode((width, height))
display.set_caption('Python snake')
clock = time.Clock()
# Змея
w = 30
h = 30
snake_speed_x = 30
snake_speed_y = 0
snake_tail = Snake("snake_hull.png", w,h,0,30,0,0)
snake_list = []
length = 1
snake_list.append(snake_tail)
#Яблоки
foodx = round(random.randrange(0,height - 30)/ 30.0) * 30.0
foody = round(random.randrange(0,width - 30)/ 30.0) * 30.0
apple = Apple("apple.png", 30,30,0,0)
apple_list = []
apple_list.append(apple)
play = True
while play:
window.fill((255,0,230))
for e in event.get():
if e.type == QUIT:
play = False
elif e.type == KEYDOWN:
if e.key == K_w:
snake_speed_y = -30
snake_speed_x = 0
if e.key == K_a:
snake_speed_y = 0
snake_speed_x = -30
if e.key == K_s:
snake_speed_y = 30
snake_speed_x = 0
if e.key == K_d:
snake_speed_y = 0
snake_speed_x = 30
for a in snake_list:
a.draw()
a.update()
a.x_speed = snake_speed_x
a.y_speed = snake_speed_y
if a.rect.x < 0 or a.rect.x > 600 or a.rect.y < 0 or a.rect.y > 600:
play = False
for i in apple_list:
i.spawn(foodx,foody)
if snake_tail.rect.x == foodx and snake_tail.rect.y == foody:
apple_list.remove(i)
length += 1
foodx = round(random.randrange(0,height - 30)/ 30.0) * 30.0
foody = round(random.randrange(0,width - 30)/ 30.0) * 30.0
apple_list.append(apple)
if len(snake_list) < length:
snake_list.append(snake_tail)
display.update()
clock.tick(5)
Ответы (1 шт):
Автор решения: Kalaps
→ Ссылка
Скорее всего это вызвано тем, что весь snake_list
состоит из одного и того же объекта. Советую переписать код.
Мой вариант вашего переписанного кода:
import pygame
import random
# ! Размер клетки 30 на 30 пикселей
class GameSprite(pygame.sprite.Sprite):
def __init__(self, picture, w, h, x, y):
super().__init__()
self.image = pygame.transform.scale(picture, (w, h))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def draw(self):
window.blit(self.image, (self.rect.x, self.rect.y))
class Snake:
def __init__(self, tiles: list[GameSprite], x_speed, y_speed, keys):
self.keys = keys
self.tiles = tiles
self.x_speed = x_speed
self.y_speed = y_speed
def update(self): # Перемещение всех тайлов змеи
for i in range(len(self.tiles)-1, 0, -1):
self.tiles[i].rect.x = self.tiles[i-1].rect.x
self.tiles[i].rect.y = self.tiles[i-1].rect.y
self.tiles[0].rect.move_ip(self.x_speed, self.y_speed)
def draw(self):
for i in self.tiles:
i.draw()
def key_handler(self, event): # Управление
if event in self.keys:
self.x_speed, self.y_speed = self.keys[event]
def add_tile(self):
self.tiles.append(GameSprite(snake_hull, w, h, 0, 30))
# Размеры экрана 600 на 600
width = 600
height = 600
window = pygame.display.set_mode((width, height))
pygame.display.set_caption('Python snake')
clock = pygame.time.Clock()
w = 30
h = 30
# Змея
snake_hull = pygame.image.load("snake_hull.png")
snake = Snake([GameSprite(snake_hull, w, h, 0, 30)], 30, 0,
{
pygame.K_a: [-30, 0],
pygame.K_d: [30, 0],
pygame.K_w: [0, -30],
pygame.K_s: [0, 30]
})
# Яблоки
foodx = round(random.randrange(0, height - 30) / 30.0) * 30.0
foody = round(random.randrange(0, width - 30) / 30.0) * 30.0
apple_sprite = pygame.image.load("apple.png")
apple_list = [GameSprite(apple_sprite, w, h, foodx, foody)]
run = True
while run:
window.fill((200, 200, 200))
for i in pygame.event.get():
if i.type == pygame.QUIT:
run = False
elif i.type == pygame.KEYDOWN:
snake.key_handler(i.key)
snake.update()
snake.draw()
for i in apple_list:
i.draw()
if snake.tiles[0].rect.colliderect(i.rect):
snake.add_tile()
apple_list.remove(i)
foodx = round(random.randrange(0, height - 30) / 30.0) * 30.0
foody = round(random.randrange(0, width - 30) / 30.0) * 30.0
apple_list.append(GameSprite(apple_sprite, w, h, foodx, foody))
pygame.display.update()
clock.tick(5)
pygame.display.quit()
Из изменений: убрал ненужные классы и переменные, создал класс Snake, исполняющий все что было у вас и сделал, чтобы новые объекты создавались по каждому чиху. Попутно существенно улучшил управление. Не смог удержаться и не сделать импорт исключительно pygame, чтобы обращаться через него.