Menu
CoddyTech

Sprite’y z dokładnością do piksela

Część sekcji Sprite’y i obrazy ścieżki Pygame w Coddy. Lekcja 23 z 36.

Duski również mogą używać masek, a pygame sam oblicza przesunięcie. Przypisz każdemu duszkowi self.mask, utworzoną raz w __init__:

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

Następnie przekaż pygame.sprite.collide_mask jako czwarty argument do spritecollide:

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

Czwarty argument określa test wykonywany dla każdej pary. Bez niego testowane są prostokąty Rect. Z collide_mask testowane są maski, umieszczone zgodnie z położeniem prostokąta Rect każdego duszka. groupcollide przyjmuje taki sam piąty argument.

Testy masek są bardziej kosztowne niż testy Rect, ale overlap porównuje tylko piksele, na których obszary dwóch prostokątów Rect się pokrywają, więc pary położone daleko od siebie są szybko sprawdzane. W przypadku kilkudziesięciu duszków nie zauważysz tego kosztu. Jeśli duszek nie ma mask, collide_mask tworzy ją z jego obrazu przy każdym teście, więc ustaw ją w __init__.

challenge icon

Wyzwanie

Średni
  1. Utwórz dla Player i Ball self.mask na podstawie self.image.
  2. Przekaż pygame.sprite.collide_mask do spritecollide, aby Hit! wyświetlało się tylko wtedy, gdy obraz statku dotyka piłki.

Spróbuj swoich sił

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()

Wszystkie lekcje w sekcji Sprite’y i obrazy

Poćwicz samodzielnie: Edytor online Pygame