Rozdział 21 · Projekt: kosmiczny strzelec

Ruch statków i wrogowie

od początku prędkość pikseli na sekundę – i wrogów pojawiających się z góry z czasem.

Przesuwamy statek kosmiczny

Sterowanie – przez get_pressed() z rozdziału 20 (ruch ciągły, dopóki klawisz jest wciśnięty). Prędkość od razu podana w pikselach na sekundę (px/s), a pozycja statku przechowywana jest jako osobna liczba ułamkowa — Rect rozumie tylko całkowite współrzędne, a aktualizowanie go bezpośrednio po troszeczku w każdej klatce oznaczałoby utratę części ułamkowej ruchu:

dvizhenie_korablya.py
KORABL_SKOROST = 260.0   # px/s

korabl_x = float(korabl.x)   # ułamkowa kopia pozycji – sam Rect przechowuje jedynie liczby całkowite

def obrabotat_klavishi(korabl_x, klavishi, dt):
    napravlenie = klavishi[pygame.K_RIGHT] - klavishi[pygame.K_LEFT]
    korabl_x += napravlenie * KORABL_SKOROST * dt
    return max(0.0, min(korabl_x, SHIRINA - KORABL_SHIRINA))

# w pętli gry:
korabl_x = obrabotat_klavishi(korabl_x, klavishi, dt)
korabl.x = round(korabl_x)
max/min jest tą samą metodą powstrzymania co w rozdziale 20
max(0.0, min(korabl_x, SHIRINA - KORABL_SHIRINA)) gwarantuje, że korabl_x nigdy nie przekroczy granic [0, SHIRINA - KORABL_SHIRINA] jest ta sama technika „ściskania”
napravlenie to liczba -1, 0 lub 1
klavishi[pygame.K_RIGHT] - klavishi[pygame.K_LEFT] są wartościami boolowskimi True/False zachowują się jak 1/0 (Rozdział 4), więc różnica daje dokładnie to, czego chcesz: 1, jeśli trzymasz tylko strzałkę w prawo, −1, jeśli trzymasz tylko strzałkę w lewo, i 0, jeśli obie lub żadne. Rozdział 21.11 podsumowuje tę samą technikę w dwóch wymiarach jednocześnie Vector2.

Tworzenie i przesuwanie wrogów

Wróg pojawi się później jako osobna klasa sprite'ów (sekcja 21.9), ale na razie – słownik z Rect i współrzędną ułamkową Y, z tej samej przyczyny co statek. Będzie wielu wrogów i pojawiają się z czasem — więc potrzebny jest lista (rozdział 11) i timer w sekundach do kolejnego pojawienia się:

vragi.py
VRAG_SHIRINA, VRAG_VYSOTA = 32, 28
VRAG_SKOROST = 150.0            # px/s
INTERVAL_POYAVLENIYA_VRAGA = 0.75   # sekund między nowymi wrogami

vragi = []
vremya_do_vraga = INTERVAL_POYAVLENIYA_VRAGA

def sozdat_vraga():
    x = random.randint(0, SHIRINA - VRAG_SHIRINA)
    return {{
        "rect": pygame.Rect(x, -VRAG_VYSOTA, VRAG_SHIRINA, VRAG_VYSOTA),
        "y": float(-VRAG_VYSOTA),
    }}

# w pętli gry, każda klatka:
vremya_do_vraga -= dt
if vremya_do_vraga <= 0.0:
    vragi.append(sozdat_vraga())
    vremya_do_vraga += INTERVAL_POYAVLENIYA_VRAGA

for vrag in vragi:
    vrag["y"] += VRAG_SKOROST * dt
    vrag["rect"].y = round(vrag["y"])
Prawdziwe okno: mały pomarańczowy trójkątny wróg schodzi z góry w stronę niebieskiego statku gracza
Prawdziwym Oknem jest Mały Zwiadowca (scout), jeden z dwóch typów wrogów w ostatecznej wersji (Rozdział 21.17).
y = -VRAG_VYSOTA — wróg pojawia się nieco powyżej ekranu
Ujemna początkowa współrzędna Y oznacza, że wróg rodzi się nieco powyżej widocznego obszaru i płynnie „wjeżdża” do kadru od góry — a nie pojawia się nagle pośrodku ekranu.
+= interval, a nie = interval — to właśnie zachowuje resztę
Gdy pojawia się wróg, dodajemy ten przedział do aktualnej wartości timera zamiast przypisywać go ponownie. W związku z tym nie tracimy niewielkiego przekroczenia czasu: jeśli vremya_do_vraga zeszedł do −0.01, następny odczyt rozpocznie się właśnie od tej małej zaległości, a nie od czystego interwału. W rozdziale 21.14 ta sama zasada zostanie uogólniona za pomocą while w przypadku, gdy jeden przetworzony krok może obejmować kilka przedziałów jednocześnie.
Praktyka: ruch statku i wrogów
Pygame otwiera natywne okno Python – uruchomione lokalnie w VS Code, PyCharm lub Jupyter
Praktyka kursuje lokalnie
Otwórz praktykę →