Gra Szybkie Palce! Obsługa pojedynku.

W tym poście zajmiemy się główną częścią logiki gry Szybkie Palce! czyli obsługą pojedynku na refleks pomiędzy dwoma Graczami. O samej grze możesz poczytać w poście Piszemy grę. Dotychczas stworzyliśmy strukturę gry oraz napisaliśmy funkcję rozpoczynającą rozgrywkę (Gra Szybkie Palce! Funkcja RozpocznijGre.). Dziś dodamy obsługę zdarzeń w przeglądarce takich jak: naciśnięcie klawisza oraz upłynięcie określonego czasu.

Dla przypomnienia, nasz pomysł na grę wygląda następująco: dwóch graczy siada przy jednej klawiaturze i wchodzą na stronę naszej gry. Gracze będą musieli wykazać się refleksem i w odpowiednim momencie nacisnąć klawisz na klawiaturze komputera. Ten który zrobi to pierwszy zdobywa punkt. Ten który zdobędzie 3 punkty wygrywa grę. Moment naciśnięcia klawisza będzie wybierany losowo oraz dodatkowo zabezpieczymy się przed nieuczciwymi graczami, którzy mogliby chcieć bezmyślnie naciskać klawisz cały czas.

Gra będzie napisana głównie w języku JavaScript i zamieszczona na stronie HTML a do jej graficznego uatrakcyjnienia skorzystamy z języka styli CSS. Kod gry jest dostępny na stronie github.com. Cała gra znajduje się w jednym pliku index.html co ułatwi jej tworzenie.

W grę można już pograć. Jest dostępna na stronie: Szybkie Palce!

Nowa funkcja: RozpocznijRunde

W funkcji RozpocznijGre do tej pory tylko ustawialiśmy początkowe wartości zmiennych. Jednak powinna ona również wystartować całą rozgrywkę. Rozgrywka polega na tym, że po losowo wybranym czasie rozpoczynany jest pojedynek (wyświetlenie informacji dla Graczy oraz oczekiwanie na naciśniecie klawiszy). Dlatego też możemy ją rozszerzyć o odpowiednie instrukcje.

Jednak funkcja RozpocznijGre powinna być wywołana tylko raz (po naciśnięciu przycisku START). A rund z pojedynkami może być kilka. Dlatego też powstała osobna funkcja odpowiedzialna tylko za to co się dzieje na początku danej rundy.

Funkcja window.setTimeout

Do obsługi zdarzeń związanych z czasem mamy dostępnych kilka funkcji JavaScript. Jedną z nich jest window.setTimeout i jest ona powiązana z obiektem window (czyli głównym elementem przeglądarki, rodzicem obiektu document o którym pisaliśmy we wcześniejszym poście).

Funkcja window.setTimeout przyjmuje dwa parametry: nazwę funkcji do uruchomienia (Pojedynek) oraz czas po którym zostanie ona uruchomiona przez przeglądarkę. W naszym przypadku musimy zastosować dodatkowe mnożenie, ponieważ funkcja window.setTimeout przyjmuje wartość czasu w milisekundach a nasza funkcja WylosujCzasRundy zwraca wartość w sekundach (od 6 do 10 sekund). Czyli 1000 razy więcej, ponieważ musimy przekazać wartości od 6000 do 10000).

Refaktoryzacja

Podczas programowania tworzymy kod, który z czasem musi się zmieniać. Dzieje się tak z wielu powodów. Między innymi dlatego, że na przykład nie jesteśmy w stanie od początku do końca przewidzieć jak kod będzie wyglądał. Czasami też zmieniamy podejście do tworzonego rozwiązania. Czasami też po prostu szybciej jest nam napisać kod “mniej elegancki” a dopiero w późniejszym etapie go poprawić.

Jednak bez względu na powód, nasz kod musi się zmieniać i ewoluować. To jest całkowicie naturalne. Taki proces jest nazywany Refaktoryzacją. Chodzi tu tylko i wyłącznie o to, aby zmienić kod. Przeważnie dany kawałek kodu można napisać na wiele różnych sposobów.

Ważne jest też, żeby nie popsuć istniejącego rozwiązania 🙂 W przypadku większych projektów stosuje się różne strategie i podejścia do refaktoryzacji. Opieramy się wtedy na zestawach testów, które sprawdzają działanie aplikacji przed i po zmianie. W naszym przypadku refaktoryzacja była dość prosta i rozszerzała funkcje Gry.

diff

Widzimy jak zmieniła się funkcja RozpocznijGre. Zielone linijki to nowy kod, czerwone linijki to kod usunięty. Dodaliśmy na początku wywołanie funkcji Zanotuj aby Gracze wiedzieli że rozpoczyna się gra. W poprzedniej wersji już w tej funkcji wyliczaliśmy czas rundy. Obecnie przenieśliśmy ten kod do funkcji RozpocznijRunde wywoływaną na sam koniec, w ostatniej linijce. Dodatkowo też dodaliśmy ustawienie kodu klawiszy na 80 (klawisz “p”) oraz 81 (klawisz “q”).

Ciekawostka: pisząc tego posta zauważyłem że Firefox nie zna takiego słowa jak Refaktoryzacja i podkreśla je na czerwono 🙂 Jest ono jednak szeroko używane przez programistów i kiedyś na pewno wejdzie na stałe do języka polskiego.

Obsługa pojedynku

Głównym elementem naszej gry jest pojedynek na refleks pomiędzy Graczami. Każdy z nich ma swój klawisz do naciśnięcia: “q” oraz “p”. Wybrałem je ponieważ są dość daleko od siebie na klawiaturze i Gracze nie powinni sobie przeszkadzać.

Do obsługi pojedynku posłużą nam trzy funkcje: Pojedynek, NacisnietoPrzycisk oraz KoniecRundy.

Dlaczego aż trzy funkcje? Ponieważ są one niezależne od siebie. To znaczy, logika wygląda tak:

  • Rozpoczyna się runda, losujemy czas, po którym nastąpi pojedynek (wyświetlimy Graczom wiadomość i zaczniemy czekać na naciśnięcie klawisza),
  • Upływa losowy czas, wyświetlamy Graczom wiadomość i czekamy na naciśnięcie klawisza
  • Gracze naciskają klawisze. Mogą je naciskać w dowolnym momencie, a o tym fakcie informuje nas przeglądarka. Dlatego też obsługa naciśnięcia klawisza jest w osobnej funkcji. Jest ona wywoływana przez przeglądarkę.
  • Po naciśnięciu klawisza kończymy daną rundę i rozpoczynamy kolejną

Główna logika naszej gry znajduje się w funkcji obsługującej naciśnięcie klawisza.

Funkcja NacisnietoPrzycisk

Przeglądarka wywoła naszą funkcję za każdym razem, gdy zostanie naciśnięty dowolny klawisz. Przekaże też parametr z informacjami o tym klawiszu. Nas interesują klawisze “q” oraz “p“. Sprawdzamy czy został naciśnięty jeden z nich. Parametr przycisk ma pole keyCode, który wskazuje na konkretny klawisz. Dla “q” jest to 81, dla “p” jest to 80.

Dopiero po sprawdzeniu, czy zostały naciśnięte odpowiednie klawisze przechodzimy dalej (za pomocą instrukcji “if”: Instrukcje sterujące). Dalsza logika jest taka sama dla obu Graczy. Zgodnie z algorytmem logiki gry Szybkie Palce! (Piszemy grę) zawsze zliczamy naciśnięcia klawiszy (nawet gdy akurat nie ma pojedynku). Dodatkowo, jeżeli trwa pojedynek dodajemy punkty odpowiedniemu Graczowi.

Ostatnim elementem jest zakończenie rundy. Uruchamiamy funkcję KoniecRundy, gdzie na chwilę obecną kończymy pojedynek. W kolejnym poście tutaj umieścimy logikę kończenia całej gry.

Funkcja document.addEventListener

Obsługę naciśnięcia klawisza możemy zrealizować na kilka sposobów. Najprostszym jest poinformowanie przeglądarki że interesuje na zdarzenie keyDown. W ten sposób rejestrujemy funkcję nasłuchującą na zdarzenie.

Dzięki temu za każdym razem jak zostanie naciśnięty klawisz, przeglądarka uruchomi wskazaną przez nas funkcję NacisnietoPrzycisk. Do tej funkcji zostanie przekazana informacja o naciśniętym klawiszu.

Wywołanie tej rejestracji (document.addEventListener) znajduje się na końcu sekcji <script> ale nie jest zamknięty w żadnej funkcji. Przeglądarka uruchamia kod linijka po linijce i gdyby ta rejestracja była w funkcji, nie zostałaby ona uruchomiona a jedynie “zapamiętana na przyszłość” (więcej w poście: Funkcje). Dzięki temu, że ta instrukcja nie jest zamknięta w funkcję, zostanie ona uruchomiona przez przeglądarkę. Podobnie jak instrukcje alert oraz Zanotuj które znajdują się na początku kodu naszej gry.

Na koniec

Na dziś to wszystko. Gra Szybkie Palce! potrafi już rozstrzygnąć, który z Graczy ma lepszy refleks. Dodaliśmy obsługę naciśnięcia klawiszy oraz uruchamianie pojedynku po określonym czasie. Dodatkowo też trochę polepszyliśmy informacje wyświetlane Graczom.

Dla przypomnienia.

Kod gry jest dostępny na platformie github.com (kod gry Szybkie Palce!).

W grę można pograć na stronie: Szybkie Palce!

Zachęcam do sprawdzenia się z kimś już teraz 🙂

 

6 replies

Trackbacks & Pingbacks

  1. […] Gra Szybkie Palce! Obsługa pojedynku. […]

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply to Pawel Kowalik Cancel reply

Your email address will not be published. Required fields are marked *