Menu
CoddyTech

Столкновение

Часть раздела Правила игры путешествия по Pygame на Coddy. Урок 27 из 29.

При касании препятствия забег заканчивается. pygame.sprite.spritecollideany(sprite, group) возвращает первый спрайт из группы, который касается спрайта, или None.

По умолчанию сравниваются прямоугольники. У изображений прозрачные углы, особенно у капли, поэтому два прямоугольника могут перекрываться, хотя видимые части не соприкасаются. Третий аргумент выбирает более точную проверку:

if pygame.sprite.spritecollideany(runner, obstacles, pygame.sprite.collide_mask):
    state = "over"

collide_mask сравнивает нарисованные пиксели изображений и игнорирует прозрачные. Поэтому столкновение происходит именно тогда, когда игрок его видит.

Состояние работает так же, как в Meteor Dodge: обновление, прыжки и появление новых препятствий происходят, только пока оно равно "play", а на экране завершения игры отображается замороженная игра и сообщение.

challenge icon

Задание

Средне
  1. Добавь шрифт assets/fonts/pixel.ttf размером 32 и state = "play".
  2. Только пока состояние равно "play": выполняй прыжок, добавляй препятствия, обновляй бегуна и препятствия.
  3. Когда бегун касается препятствия (collide_mask), установи состояние "over".
  4. Когда игра завершится, покажи Game over в цвете (40, 50, 80) по центру в точке (320, 140).

Попробуйте сами

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((640, 320))
pygame.display.set_caption("Sky Runner")
clock = pygame.time.Clock()

SKY = (140, 200, 240)
GROUND = (90, 160, 80)
GROUND_Y = 260
GRAVITY = 1
SPAWN = pygame.USEREVENT + 1


class Runner(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.frames = [
            pygame.image.load("assets/images/player.png").convert_alpha(),
            pygame.image.load("assets/images/player_walk.png").convert_alpha(),
        ]
        self.image = self.frames[0]
        self.step = 0
        self.rect = self.image.get_rect(midbottom=(100, GROUND_Y))
        self.vy = 0

    def jump(self):
        if self.rect.bottom == GROUND_Y:
            self.vy = -16

    def update(self):
        self.vy += GRAVITY
        self.rect.y += self.vy
        if self.rect.bottom >= GROUND_Y:
            self.rect.bottom = GROUND_Y
            self.vy = 0
        if self.rect.bottom == GROUND_Y:
            self.step += 1
            self.image = self.frames[self.step // 8 % 2]
        else:
            self.image = self.frames[1]


class Obstacle(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = random.choice(obstacle_images)
        self.rect = self.image.get_rect(midbottom=(664, GROUND_Y))

    def update(self):
        self.rect.x -= speed
        if self.rect.right < 0:
            self.kill()


obstacle_images = [
    pygame.image.load("assets/images/spike_ball.png").convert_alpha(),
    pygame.image.load("assets/images/blob.png").convert_alpha(),
]
runner = Runner()
obstacles = pygame.sprite.Group()
speed = 6
pygame.time.set_timer(SPAWN, 1500)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN and event.key in (pygame.K_SPACE, pygame.K_UP):
            runner.jump()
        if event.type == SPAWN:
            obstacles.add(Obstacle())
            pygame.time.set_timer(SPAWN, random.randint(1000, 2000))

    runner.update()
    obstacles.update()

    screen.fill(SKY)
    pygame.draw.rect(screen, GROUND, (0, GROUND_Y, 640, 60))
    screen.blit(runner.image, runner.rect)
    obstacles.draw(screen)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Все уроки раздела Правила игры

Потренируйтесь самостоятельно: Песочница Pygame