Menu
CoddyTech

Kreis-Hitboxen

Teil des Abschnitts Sprites und Bilder der Pygame-Journey von Coddy. Lektion 24 von 36.

Ein Pixeltest ist exakt, aber exakt ist nicht immer das, was sich fair anfühlt. Ein Streifschuss an der Flügelspitze zählt als Treffer. Viele Spiele testen stattdessen eine kleinere, einfachere Form, eine Trefferbox, und lassen knappe Fehlschüsse gelten.

Bei runden Dingen testest du Kreise. Gib jedem Sprite einen radius, und pygame.sprite.collide_circle wertet es als Treffer, wenn die Mittelpunkte näher beieinander liegen als die Summe der beiden Radien:

self.radius = 24  # in Player.__init__
self.radius = 22  # in Ball.__init__

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

Hier sind das 24 + 22 = 46 Pixel zwischen den Mittelpunkten. Die Kreise sind kleiner als die Bilder, sodass sich die äußersten Kanten berühren können, ohne dass ein Treffer vorliegt. Ein Kreistest ist außerdem günstig: eine Entfernung, keine Pixel.

Ohne radius verwendet collide_circle einen Kreis um das gesamte Rect, der größer als das Rect selbst ist. Bei einem Sprite in Kastenform erfüllt ein kleineres Rect denselben Zweck: self.rect.inflate(-16, -16) ist das Rect, das 16 Pixel schmaler und kürzer ist und denselben Mittelpunkt hat.

challenge icon

Aufgabe

Mittel
  1. Gib Player self.radius = 24 und Ball self.radius = 22.
  2. Teste mit pygame.sprite.collide_circle statt mit collide_mask.

Probier es selbst

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))
        self.mask = pygame.mask.from_surface(self.image)

    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))
        self.mask = pygame.mask.from_surface(self.image)


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, pygame.sprite.collide_mask)

    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()
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Sprites und Bilder

Übe selbstständig: Pygame-Playground