Menu
CoddyTech

Daire Hitbox'ları

Coddy'nin Pygame Journey'sinin Sprite'lar ve Görseller bölümünün bir parçası. Ders 24 / 36.

Piksel testi kesindir, ancak kesin olan her zaman adil hissettirmez. Bir dikenin kanadın ucuna sürtmesi isabet sayılır. Bunun yerine birçok oyun daha küçük ve basit bir şekli, yani bir isabet alanını test eder ve kıl payı kaçırmaları isabet saymaz.

Yuvarlak nesneler için daireleri test edin. Her sprite'a bir radius verin; pygame.sprite.collide_circle, merkezler arasındaki mesafe iki yarıçapın toplamından küçük olduğunda bunu isabet sayar:

self.radius = 24  # Player.__init__ içinde
self.radius = 22  # Ball.__init__ içinde

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

Burada merkezler arasındaki mesafe 24 + 22 = 46 pikseldir. Daireler resimlerden daha küçük olduğundan, en dış kenarlar birbirine değse bile isabet sayılmaz. Daire testi ayrıca ucuzdur: tek bir mesafe hesabı, piksel yok.

radius olmadan collide_circle, Rect'in tamamının çevresinde Rect'in kendisinden daha büyük bir daire kullanır. Kutu şeklindeki bir sprite için daha küçük bir Rect aynı işi görür: self.rect.inflate(-16, -16), aynı merkezle 16 piksel daha dar ve daha kısa olan Rect'tir.

challenge icon

Görev

Orta
  1. Player için self.radius = 24 ve Ball için self.radius = 22 değerlerini verin.
  2. collide_mask yerine pygame.sprite.collide_circle ile test edin.

Kendin dene

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 iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Sprite'lar ve Görseller bölümündeki tüm dersler

Kendi başına pratik yap: Pygame playground