Jason. Cała informatyka w jednym miejscu!

Artykuł niespodzianka na temat nowo wstawionej znienacka pozycji, którą mogłeś(-aś) już ujrzeć w sekcji gier. Pojawiła się nowa produkcja, którą udało mi się szybko skleić (bo w niecały miesiąc 😯!), aby sobie odkurzyć wiedzę z języka JavaScript 📖. "Frog Guy", bo taki tytuł nosi nowa gierka, to klon kolejnej innej znanej produkcji z lat .80, "Frogger" 🐸! Zapraszam do środka!

"FROGGER". TROCHĘ O ORYGINALE I O SWOIM KLONIE

Produkcja firmy Konami z 1981 roku już wiele razy doczekała się od programistów nowych klonów, co widać po samych filmach na YouTube ▶️. Nic w tym dziwnego, bo sama gra choć mała w zawartości, to stanowi świetne ćwiczenie umiejętności programistycznych 🏋️‍♀️. Na początek, krótkie wyjaśnienie.

Co to za gra?

"Frogger" to gra, w której steruje się żabką i Twoim zadaniem jest "przeprowadzić" ją do 5 wolnych miejsc u góry mapy. Gdy zajmiesz jedno z miejsc, to pojawia się kolejna żabka i tę samą czynność należy powtórzyć jeszcze 4 razy, aż wszystkie zostaną "umieszczone" na wszystkich miejscach. Liczy się szybka reakcja i przewidywalność ⏩, gdyż po drodze trzeba ominąć jezdnię, po której jeżdżą samochody 🚗 (i tak, dobrze myślisz, są zabójcze dla Ciebie 💀), a następnie przejść jeszcze przez rzekę, po której pływają drewniane belki oraz żółwie 🐢, i trzeba je wykorzystać jako platformę 🌉. Żółwiki od czasu do czasu lubią się chować, co uatrakcyjnia (i utrudnia 🙂) rozgrywkę.

Postanowiłem stworzyć mój własny klon gry "Frogger" i tak powstał "Frog Guy" 😊. Ciekawostką niech będzie fakt, iż nie użyłem żadnego zewnętrznego narzędzia - silnika, frameworka, nawet biblioteki! Całość gry to płótno HTML (canvas), szczypta formatowania CSS, a reszta to tylko czysty JavaScript! Niżej masz zrzut ekranu z efektu końcowego wersji 1.0 🧨!

"Frog Guy" (2025)

Zrzut ekranu z gry "Frog Guy".

Trochę o implementacji

Teraz co nieco o szczegółach prac. Złożenie wszystkiego do kupy zajęło mi 24 dni ⏰. W ciągu jednej doby spędzałem jakieś 3-5 godzin, więc moim zdaniem poszło sprawnie i jestem zadowolony 👍. Było trochę łamania głowy, lecz na szczęście nie tak, jak przy klonie "Battle City" 😉. Nie będę Cię zanudzać opisywaniem każdego elementu, bo jak jesteś ciekawy(-a), to możesz sobie zerknąć na repozytorium, lecz przytoczę parę takich najciekawszych części, które czasem wymagały obejścia 🚧.

Podział mapy na części (i kafelki)

To był jeden z najcięższych puzzli 🧠. Wizualnie, mapa na której znajdują się obiekty, to prostokątna przestrzeń składająca się z rzędów różnego typu. Szerokość jest uzależniona od liczby miejsc dla żabek, aby zachować spójność i nie było rysowania miejsca "do połowy" 😜. Co więcej, wysokość (czyli liczba wierszy) na typ także jest nieregularna (np. chodnik ma jeden wiersz, a rzeka składa się z pięciu). Wiedziałem, że bezpośrednie operowanie na współrzędnych nie wchodzi w grę na dłuższą metę, bo dużo trudniej dodawałoby się nowe implementacje, więc trzeba było podejść do tego inaczej.

W moim klonie, mapa jest budowana z pojedynczych kafelków przez zaprogramowany system. Najpierw dodawane są miejsca dla żabek. Domyślnie jest 5, więc szerokość mapy przyjmie 15 kafelków po 8x8 każdy (ponieważ jedno miejsce przyjmuje szerokość 24 pikseli, zatem: 24 / 8 = 3). Do utworzonej grupy obiektów zostaje umieszczonych 5 obrazów ("sprite'ów"). Wewnątrz nich są jeszcze zaimplementowane pozycje dla żabek, aby jeszcze bardziej "związać" je dla zachowania zgodności z grafiką.

Tak powstała grupa jest dodawana do listy. Potem system przechodzi do utworzenia kolejnej (idąc od góry, więc następna jest rzeka) i postępuje podobnie. Wprowadzając parametry, tworzy przestrzeń o wymiarach 15x5 kafelków, dodaje sprite'y, nakłada odpowiednio pozycję, dodaje do grupy, a grupa jest dodawana do listy. Całość idzie tak samo, aż do chodnika, na którym stoi nasz zielony bohater 🐸.

Implementacja tego wszystkiego dała do wiwatu, jednak przyniosła pozytywny efekt 🌞, bo później takie rzeczy, jak dodawanie obiektów na odpowiednich rzędach czy wykrywanie na jakim rodzaju terenu stoi gracz, były już bardzo proste do zaimplementowania i wprowadzania przyszłościowych zmian 😀.

Grupowanie obiektów i nieregularna liczba sztuk

W grze "Frogger", są tylko 2 rodzaje obiektów pływających na rzece, aczkolwiek przyjmują różne wielkości. Drewniana belka może być raz krótsza, raz dłuższa, a jedna grupa żółwi może składać się z 2 lub 3 sztuk ustawionych obok siebie 🙂. Łamigłówka przyjęła dwie twarze: graficzną i w materii wykrywania kolizji 😳!

Graficznie, drewnianą belkę trzeba było pociąć na 3 części: lewy koniec, środek i prawy koniec. Następnie wiedząc, że żeby była ona wizualnie sensowna, minimalnie musi przyjmować lewy i prawy koniec, należało umożliwić wprowadzenie do parametru liczbę środkowych kafelków. W taki sposób była generowana w rzeczywistości grupa pojedynczych kafelków, a całość prezentowała się jak jedna belka, która może być dowolnie długa, jak będę chciał. Żółw nie potrzebował takiej przeróbki bowiem, z uwagi na animację, wystarczyło dodać obiekt do grupy i zdecydować ile sztuk ma być osadzonych w jednej grupie.

Wykrywanie kolizji musiało uwzględnić grupowanie obiektów, tak aby znów była spójność z tym, co gracz widzi na ekranie. Lewy górny róg pierwszego obiektu, to jednocześnie lewy górny róg całej grupy, a jej szerokość to liczba obiektów przemnożona przez szerokość każdego z obrazka z osobna (8 pikseli).

Udźwiękowienie

Ostatnia rzecz to dźwięki. W JavaScript zaskoczyły mnie mało przyjemnie dwie sprawy. Po pierwsze, nie da się bezboleśnie pobrać czasu trwania klipu dźwiękowego z samego pliku (można co prawda kombinować poprzez metodę "onloadedmetadata", lecz byłoby trudno to pogodzić z inicjalizacją poszczególnych elementów gry), a po drugie nie można odtwarzać tego samego dźwięku, dopóki nie skończy grać, a to mi było potrzebne głównie do dźwięku przemieszczenia się żabki przez gracza, bo możesz naciskać prędzej, niż skończy się dźwięk ☺️.

Żeby nie przeciągać czasu na szukanie jakichś niekonwencjonalnych sposobów, podszedłem do obu kwestii następująco: czas trwania dźwięku wstawiłem jako parametr i przypisywanie go w konstruktorze, a dźwięk gdy ma się odpalać jeszcze w trakcie grania, tworzy za każdym razem nową instancję, zamiast korzystać z przechowywanej - tylko tak można sprawić, żeby dany dźwięk odpalał się w czasie, gdy jeszcze gra (wtedy de facto są to dwie różne instancje tego samego dźwięku).

Logo gry "Frog Guy"

Logo gry "Frog Guy".


I to tyle. Gra nie otrzymała zwiastuna, bo to taki mały projekt zrobiony na szybko, na potrzeby repozytorium.

PODOBNE ARTYKUŁY