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().
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(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() 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.