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