Menu
CoddyTech

Hitbox Lingkaran

Termasuk bagian Sprite dan Gambar dalam perjalanan Pygame di Coddy. Pelajaran 24 dari 36.

Pengujian piksel bersifat tepat, tetapi ketepatan tidak selalu terasa adil. Sentuhan duri pada ujung sayap dihitung sebagai benturan. Banyak game menguji bentuk yang lebih kecil dan sederhana, yaitu hitbox, sehingga sentuhan yang nyaris meleset tidak dihitung.

Untuk benda bulat, uji lingkaran. Beri setiap sprite radius, lalu pygame.sprite.collide_circle menganggapnya sebagai benturan jika jarak antara titik pusatnya kurang dari jumlah kedua radius:

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

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

Di sini, jarak antara titik pusatnya adalah 24 + 22 = 46 piksel. Lingkarannya lebih kecil daripada gambar, jadi bagian tepinya bisa bersentuhan tanpa dihitung sebagai benturan. Pengujian lingkaran juga ringan: cukup satu perhitungan jarak, tanpa piksel.

Tanpa radius, collide_circle menggunakan lingkaran yang mengelilingi seluruh Rect, sehingga ukurannya lebih besar daripada Rect itu sendiri. Untuk sprite berbentuk kotak, Rect yang lebih kecil melakukan hal yang sama: self.rect.inflate(-16, -16) menghasilkan Rect yang 16 piksel lebih sempit dan lebih pendek, dengan titik pusat yang sama.

challenge icon

Tantangan

Sedang
  1. Beri Player nilai self.radius = 24 dan Ball nilai self.radius = 22.
  2. Uji dengan pygame.sprite.collide_circle, bukan collide_mask.

Coba sendiri

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 iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Sprite dan Gambar

Latihan sendiri: Playground Pygame