Rozdział 20 · Tworzenie gier z Pygame

Kolizje i hitboxy

colliderect() pod maską — cztery porównania liczb, a hitbox nie musi pasować do widocznego obrazu pixel w pixel.

Kolizja to moment, gdy dwa obiekty gry przecinają się w przestrzeni, a gra musi na to zareagować: piłka odbija się od ściany, postać podnosi monetę, pocisk pokonuje wroga. U pygame.Rect istnieje gotowa metoda na to:

colliderect.py
if igrok_rect.colliderect(vrag_rect):
    print(„Kolizja!”)

Jak to jest naprawdę zorganizowane

colliderect() sprawdza przecięcie dwóch prostokątów, Wyrównany do osi (AABB, axis-aligned bounding box) jest metodą redukcją pod maską do czterech prostych porównań liczbowych:

aabb_vruchnuyu.py
def pryamougolniki_peresekayutsya(a, b):
    ax1, ay1, aw, ah = a
    bx1, by1, bw, bh = b
    ax2, ay2 = ax1 + aw, ay1 + ah
    bx2, by2 = bx1 + bw, by1 + bh
    return ax1 < bx2 and ax2 > bx1 and ay1 < by2 and ay2 > by1

Dwa prostokąty nie przecinają się, jeśli jest się całkowicie po lewej, po prawej, Wyższe lub niższe niż pozostałe, powyższa kontrola ma na celu tylko upewnić się, że żadna z tych czterech Warunki nie są spełnione.

Okno rzeczywiste: niebieskie i żółte kwadraty częściowo nakładają się na siebie – colliderect() zwraca True
Prawdziwe okno: nakładające się prostokąty – drugie jest zacienione na żółto, bo colliderect() wróciło True.
Rzeczywiste okno: niebieski i czerwony kwadrat daleko od siebie — colliderect() zwraca False
Faktyczne okno: prostokąty się nie przecinają — drugi pozostał czerwony.

Hitbox nie zawsze jest tym samym co rysowanie

"Hitbox" to prostokąt (lub inny kształt), używany specjalnie do sprawdzania kolizji, i nie musi odpowiadać rozmiarowi widocznego rysunku znaku w Jeden. Okrągła kula z przezroczystymi krawędziami zwykle ma kwadratowy obraz — jeśli liczyć kolizja na pełnym kwadracie obrazu, gracz zobaczy niesprawiedliwe "trafienia" chybił", gdzie nic nie dotykało oka.

Hitbox nie pasuje do obrazu – kolizje wydają się „niesprawiedliwe”
Częsta przyczyna: Rect pobiera się bezpośrednio z rozmiaru całego załadowanego obrazu, w tym przezroczystych pól wokół samej postaci. Rozwiązanie — zmniejszyć hitbox względem widocznego obrazu przez rect.inflate(-20, -20): inflate() zmiany ogólnie wymiary prostokąta, zachowując środek, dlatego -20 według szerokości i wysokości usuwa dokładnie 10 pikseli z każdej strony, a nie 20. Konkretne marginesy dobiera się wzrokowo dla każdego sprite'a.
Rzeczywiste okno: czerwony piłka z dwoma ramkami na wierzchu — dużą czerwoną na krawędzi obrazu i mniejszą zieloną wewnątrz niej
Rzeczywiste okno: czerwona ramka — pełny rozmiar obrazu, zielona — zmniejszony hitbox, bliżej do rzeczywistych widocznych krawędzi piłki.
Praktyka: sprawdzanie przecięcia prostokątów
Zeskanowanie bezpośrednio w przeglądarce – nie wymaga instalacji Pygame
Otwórz praktykę →