Menu
CoddyTech

Пиксельно точные спрайты

Часть раздела Спрайты и изображения путешествия по Pygame на Coddy. Урок 23 из 36.

Спрайты тоже могут использовать маски, а pygame сам учитывает смещение. Задайте каждому спрайту self.mask, создав его один раз в __init__:

self.mask = pygame.mask.from_surface(self.image)

Затем передайте pygame.sprite.collide_mask в качестве четвёртого аргумента функции spritecollide:

hits = pygame.sprite.spritecollide(player, balls, False, pygame.sprite.collide_mask)

Четвёртый аргумент — это проверка, выполняемая для каждой пары. Без него проверяются Rect. С collide_mask проверяются маски, размещённые в соответствии с Rect каждого спрайта. Функция groupcollide принимает такой же пятый аргумент.

Проверка масок обходится дороже, чем проверка Rect, но overlap сравнивает только пиксели, на которых Rect пересекаются, поэтому пары, находящиеся далеко друг от друга, проверяются быстро. Для нескольких десятков спрайтов вы не заметите разницы. Если у спрайта нет mask, collide_mask создаёт её на основе его изображения при каждой проверке, поэтому задайте её в __init__.

challenge icon

Задание

Средне
  1. Создай для Player и Ball self.mask на основе self.image.
  2. Передай pygame.sprite.collide_mask в spritecollide, чтобы надпись Hit! отображалась, только пока изображение корабля касается шара.

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

import pygame

pygame.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("Spike Field")
clock = pygame.time.Clock()

ship_image = pygame.image.load("assets/images/ship.png").convert_alpha()
ball_image = pygame.image.load("assets/images/spike_ball.png").convert_alpha()
font = pygame.font.Font(None, 40)


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = ship_image
        self.rect = self.image.get_rect(topleft=(420, 320))

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            self.rect.x -= 4
        if keys[pygame.K_RIGHT]:
            self.rect.x += 4
        if keys[pygame.K_UP]:
            self.rect.y -= 4
        if keys[pygame.K_DOWN]:
            self.rect.y += 4


class Ball(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = ball_image
        self.rect = self.image.get_rect(center=(x, y))


player = Player()
balls = pygame.sprite.Group(Ball(160, 240), Ball(320, 240), Ball(480, 240))

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    player.update()
    hits = pygame.sprite.spritecollide(player, balls, False)

    screen.fill((20, 22, 40))
    balls.draw(screen)
    screen.blit(player.image, player.rect)
    if hits:
        text = font.render("Hit!", True, (240, 240, 240))
        screen.blit(text, (10, 10))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()

Все уроки раздела Спрайты и изображения

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