Rozdział 21 · Projekt: kosmiczny strzelec

Życia, obrażenia i tymczasowa niewrażliwość

Spotkania i ucieczki wrogów to dwa różne źródła śmierci z różnymi zasadami.

Rozdział 21.6 zakończyła grę pojedynczą kolizją statku z wrogiem. Wersja ostateczna Zamiast tego liczy się życie — ale jest tu mniej oczywista pułapka: co jeśli jest ich kilka naraz Wrogowie zderzają się ze statkiem w tym samym momencie?

fragment_player_damage.py
def resolve_enemy_player_collisions(self):
    hit = pygame.sprite.spritecollide(self.player, self.enemies, True)
    for vrag in hit:
        self._spawn_explosion(vrag.rect.center)
    return len(hit) > 0

# w aktualizacji ramek:
collided = self.resolve_enemy_player_collisions()
if collided and not self.player.is_invulnerable:
    self.lives -= 1
    self.player.take_hit()
Trzech wrogów jednocześnie – minus jedno życie, nie minus trzy
spritecollide() bezwarunkowo usuwa wszystkie zderzające się wrogie sprite'y — ale obrażenia statku nie są odejmowane przez osobny test na więcej niż jedno życie na odświeżenie klatki, niezależnie od liczby wrogów uderzających w statek jednocześnie. Bez tej rozdzielczości trzech jednoczesnych wrogów zabrałoby trzy życia w jednej klatce, co wydawałoby się niesprawiedliwie surowe.

Tymczasowa odporność

Po trafieniu aktywowany jest krótki okres niewrażliwości – podczas niego kolizje trwają Usuń wrogów, ale nie odbieraj już życia:

fragment_invulnerability.py
PLAYER_INVULNERABLE_SECONDS = 1.2

@property
def is_invulnerable(self):
    return self.invulnerable_timer > 0.0

def update_timers(self, dt):
    self.invulnerable_timer = max(0.0, self.invulnerable_timer - dt)

def take_hit(self):
    self.invulnerable_timer = PLAYER_INVULNERABLE_SECONDS
Realne Okno: Cienki niebieski pierścień wokół statku gracza jest wizualnym wskaźnikiem tymczasowej niewrażliwości
Prawdziwe okno — równe koło wokół statku, a nie miganie: spokojny, nieirytujący wskaźnik nietykalności.
Pierścień prosty zamiast migać
Migający sprite — popularny trik, ale przy szybkim miganiu męczy oczy. Tutaj zamiast tego — stała obręcz wokół statku, która po prostu znika, gdy invulnerable_timer spada do zera.

Ucieczka wroga za dolną granicę

Gra ma drugie, odrębne źródło utraty życia. Wróg uważa się za ucieczkę, tylko gdy jego sprite całkowicie przekroczy dolną krawędź pola gry (vrag.rect.top > self.playfield.bottom). Każdy taki wróg zostaje usunięty i kosztuje gracza jedno życie:

fragment_enemy_escapes.py
def resolve_enemy_escapes(self):
    escaped = [
        vrag for vrag in self.enemies
        if vrag.rect.top > self.playfield.bottom
    ]
    for vrag in escaped:
        vrag.kill()
    return len(escaped)

# w aktualizacji ramek:
self.lives -= self.resolve_enemy_escapes()
Limit „jednego życia na klatkę”
Escape nie jest trafieniem statku, więc tymczasowa niewrażliwość go nie blokuje. Jeśli dwóch wrogów opuści pole w tej samej aktualizacji, gra odejmuje dwa życia; jeśli nie ma już żyć, stan staje się GAME_OVER. To zasada celowa: wrogowie zderzający się jednocześnie tworzą jedno zdarzenie uderzenia, a każdy nietrafiony przeciwnik to osobny wynik, który liczy się dokładnie raz.
Praktyka: Obrażenia i niewrażliwość
Zeskanowanie bezpośrednio w przeglądarce – nie wymaga instalacji Pygame
Praktyka kursuje lokalnie
Otwórz praktykę →