Rozdział 19 · Model gry

Prawdziwa pętla rozgrywki

screen.ontimer() planuje kolejne tiknięcie i natychmiast przywraca kontrolę — zamiast blokować program w while.

while nie jest jedynym sposobem na powtarzanie tików

Pierwszy prototyp prowadzi grę przez cały proces while igrovoj_shag(): ... z time.sleep() w ciele to prosty i prosty cykl blokowania. Łatwo wyciągnąć tu błędne wnioski, więc warto opowiedzieć o tym osobno: screen.update() wewnątrz pętli FAKTYCZNIE przetwarza zgromadzone Tkinter zdarzeń, w tym naciśnięcia klawiszy, oznaczają, że handler jest związany przez onkeypress(), technicznie może zadziałać bezpośrednio podczas tego wywołania. Problem takiej pętli nie polega na tym, że klawiatura „nie nadąża” — ale na tym, że on posiada zarządzanie od początku do końca gry i nikogo o to nie pyta rozdzielczość. Prędkość w niej to jedna stała ZADERZHKA_SEK, którego nie można zmienić w trakcie gry; a pauza i restart musiałyby być ręcznie wplecione w ciało pętli z osobnymi flagami i kontrolami w każdej iteracji. I przez cały ten czas program nie może Nic więcej: ona siedzi w środku sleep().

ontimer_cikl.py
def game_tick(self):
    if self.state.status is not GameStatus.RUNNING:
        return
    # ...zastosować kierunek, przesunąć głowę, sprawdzić jedzenie i kolizje...
    self.render()
    self.screen.ontimer(self.game_tick, self.state.delay_ms)
screen.ontimer() planuje kolejny tick zamiast blokować program
screen.ontimer(callback, delay_ms) prosi cykl zdarzeń Tkinter (ten sam, co w rozdziale 17) o wywołanie callback około delay_ms — i natychmiast wraca do kontroli. Między taktami program jest całkowicie wolny: klawiatura, zmiany pauzy i prędkości są przetwarzane jako zwykłe zdarzenia i nie czekają na swoją kolej w pętli.
time.sleep() w pętli Tkinter/Turtle gry to zły pomysł
time.sleep() zatrzymuje wszystkim proces, włączając obsługę zdarzeń — okno przestanie odpowiadać na klawiaturę i zamykanie dokładnie na czas uśpienia. screen.ontimer() niczego nie blokuje: przekazuje zegar do pętli zdarzeń, która w tym czasie nadal obsługuje wszystko inne.

Każde wyzwanie game_tick() sam planuje następny przez ontimer() — powstaje łańcuch, a nie cykl w zwykłym znaczeniu. Tutaj jest subtelność: ontimer() planuje tylko przyszłe wyzwanie — Nie usuwa się samodzielnie, jeśli status gry się zmieni. Rozdział 19.22 wyjaśnia dlaczego Dlatego pauza nie może polegać wyłącznie na weryfikacji status wewnątrz ticku — i co się stanie, jeśli polegać tylko na niej.

Praktyka: Pętla gry na ontimer()
Moduł turtle otwiera natywne okno Python – uruchamiane lokalnie w VS Code, PyCharm lub Jupyter
Praktyka kursuje lokalnie
Otwórz praktykę →