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.
Aufgabe
Mittel- Gib
Playerself.radius = 24undBallself.radius = 22. - Teste mit
pygame.sprite.collide_circlestatt mitcollide_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()
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
1Bilder laden
Ein Bild ladenMit einem Rect platzierenDas Bild bewegenEinen Hintergrund kachelnTransparente Pixel2Drehen, Spiegeln, Skalieren
Um den Mittelpunkt drehenIn Flugrichtung ausrichtenEin Bild skalierenVom Original aus drehen3Klassen für Spielobjekte
Deine erste KlasseMethodenSelf ist das ObjektEine Liste von ObjektenObjekte mit BildernEine Unterklasse6Animation mit Sprite Sheets
Ein Sprite Sheet zuschneidenEin Frame-ZählerMit Zeit animierenEine einmalige ExplosionÜbe selbstständig: Pygame-Playground