Спрайты и «Змейка»
Когда объектов в игре много — звёзды, враги, пули, монеты, — удобно описывать каждый как спрайт, а похожие объединять в группы. Группа сама обновит, нарисует и проверит столкновения для всех своих спрайтов.
Спрайт
Спрайт — класс-наследник pygame.sprite.Sprite с двумя обязательными полями: image (как выглядит) и rect (где находится).
class Enemy(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__() # обязательно
self.image = pygame.Surface((30, 30))
self.image.fill((220, 60, 60))
self.rect = self.image.get_rect(topleft=(x, y))
def update(self): # поведение за один кадр
self.rect.x += 2
image.get_rect(topleft=…) создаёт прямоугольник по размеру картинки и сразу ставит его в нужную точку.
Группа
enemies = pygame.sprite.Group()
enemies.add(Enemy(0, 0), Enemy(50, 0))
enemies.update() # вызывает update() у каждого спрайта
enemies.draw(screen) # рисует image каждого спрайта в его rect
print(len(enemies)) # сколько спрайтов в группе
sprite.kill() убирает спрайт из всех групп. Так убирают объекты, ушедшие за экран, сбитых врагов, собранные монеты. Если забыть их убирать, группа растёт, и игра постепенно тормозит.
Столкновения спрайтов
hits = pygame.sprite.spritecollide(player, enemies, False) # список врагов, которых касается игрок
hits = pygame.sprite.spritecollide(player, coins, True) # и сразу убрать их из группы
one = pygame.sprite.spritecollideany(player, enemies) # любой один или None
pairs = pygame.sprite.groupcollide(bullets, enemies, True, True) # пули × враги
Третий аргумент dokill решает, убирать ли задетые спрайты. Для бонусов и монет он почти всегда True, иначе один и тот же предмет засчитается каждый кадр, пока игрок на нём стоит.
Игровая логика отдельно от рисования
Самое ценное в игре — правила: что происходит за один шаг. Их удобно писать отдельной функцией, которая получает состояние и возвращает новое, ничего не рисуя. Например, шаг «Змейки»:
- вычислить новую клетку головы;
- проверить, съедена ли еда;
- решить, где будет тело: если еда съедена, хвост остаётся, иначе — последний сегмент уходит;
- проверить гибель: выход за поле или столкновение с новым телом;
- собрать новую змейку: голова + тело.
Порядок шагов 3 и 4 важен: хвост, который уходит на этом шаге, не препятствие.
Такую функцию легко проверить без окна — именно так и проверяются задачи этого курса.
Итог
- спрайт:
image,rect,update();super().__init__()обязательно; - группа:
add,update,draw,len;kill()убирает спрайт; spritecollide(sprite, group, dokill),spritecollideany,groupcollide;- правила игры — в отдельной функции «состояние → новое состояние».