Tomasz Gajda
Celem projektu było stworzenie prostej gry, która dostępna byłaby z poziomu różnorodnych urządzeń. Jako że najłatwiejszą opcją do stworzenia gry międzyplatformowej jest skorzystanie z technologii internetowych - tak właśnie uczyniłem.
Stos technologiczny:
- Typescript
- React
- SASS
- @react-three/fiber
- zustand
- netlify
Pomniejsze wykorzystane biblioteki:
- react-icons
- react-device-detect
Stworzona gra korzysta z frameworka React i wrappera React-Three-Fiber który obudowuje zawarte w Three.js klasy w komponenty wykorzystywane w React. Biblioteka ta oferuje prostszy interfejs obsługi 3D w Javascript/Typescript nie tracąc przy tym na wydajności.
Oprócz tego wykorzystałem preprocesor SASS do stylowania elementów, które tego wymagały w aplikacji (np. HUD). Na koniec za pomocą netlify i konsolowego interfejsu szybko deployowałem grę do sieci.
Zasady gry są dość proste - gracz ma za zadanie omijać sześciany znajdujące się na trasie i przebyć w ten sposób jak największy dystans.
Kontrolując blok za pomocą strzałek bądź klawiszy “A” oraz “D” (czy też specjalnych przycisków na ekranach mobilnych) gracz musi omijać przeszkody znajdujące się na płaszczyźnie.
Rys. 1 - Główny ekran gry
Uzyskany wynik jest widoczny w trakcie gry jak i na ekranie po przegranej. Trzy najlepsze wyniki są zapisywane do **localStorage **i wyświetlane na ekranie “Game Over”.
Rys. 2 - Zestaw wyników na ekranie końcowym
W grze dodany jest również Soundtrack - za pomocą przycisku w prawym górnym rogu ekranu możemy go włączać/wyłączać w trakcie gry.
Rys. 3 - Przycisk, którym możemy manipulować muzyką
W aplikacji znajdziemy zbiór komponentów, które wraz z zapisywanym stanem tworzą całą grę:
W folderze “store” znajduje się zapisany stan naszej aplikacji. Do manipulacji stanem w aplikacji wykorzystałem bibliotekę “zustand”, czyli rozwiązanie dużo prostsze w użyciu niż popularne aktualnie biblioteki Redux czy też oferowane przez samego React’a Context API. Możemy tam znaleźć wszystkie zmienne przechowywane w stanie. Są one aktualizowane w czasie działania aplikacji.
Komponent ten przedstawia model sześcianu, którym steruje gracz oraz wszystkie operacje które manipulują jego pozycją, szybkością poruszania itp. Są tutaj też manipulację kamerą, która powinna podążać za sześcianem.
Komponent ten odpowiada za generowanie przeszkód na trasie - sześcianów o losowo wygenerowanej pozycji na płaszczyźnie Z.
Komponent generuje płaszczyznę o teksturze fioletowej siatki, po której porusza się gracz i na której pojawiają się przeszkody.
Pomimo przechowywania stanu gry w innym miejscu, stworzyłem również ten komponent by śledził aktualną sytuację w grze, aktualizował wynik i w przypadku końca gry zmieniał stan.
Komponent w pełni poświęcony śledzeniu inputa z klawiatury - na bieżąco zapisuje do stanu, które przyciski są naciskane.
Komponent obsługujący muzykę zaimplementowaną w grze. Nasłuchuje zmiany na przycisku odpowiadającego za manipulację muzyką w HUD.
Komponent nakładający HUD na ekran gry - przedstawia wszystkie ważne dla użytkownika informacje w jasny i czytelny sposób. W tym komponencie również sprawdzane jest jakim urządzeniem posługuje się użytkownik - jeśli jest to urządzenie mobilne, renderowane są dodatkowe przycisku do sterowania.
Komponent z ekranem “Game Over” - wyświetla wynik aktualnej próby oraz listę najlepszych wyników zapisaną w localStorage.
React-Three-Fiber daje niesamowite możliwości tworzenia gier i aplikacji internetowych przy użyciu całkiem prostego API. Bardzo przyjemnie mi się z nim pracowało, natomiast czas który chciałem poświęcić na stworzenie gry był ograniczony, dlatego też kod nie we wszystkich miejscach wygląda tak jak powinien, a i kilka funkcjonalności, które planowałem na początku nie zostało zaimplementowane:
W planach miałem implementację zwiększającego się poziomu trudności - wraz z przekroczeniem kolejnych kamieni milowych (np. 5000 pkt.) ilość przeszkód lub prędkość kierowanego obiektu miały się zwiększyć (dlatego też mamy licznik prędkości w lewym dolnym rogu HUD).
W tym momencie tło nad płaszczyzną jest czarne - dodaje to klimatu grze, natomiast można by było tam wstawić jakąś ładną grafikę, która pasowałaby do aplikacji.
Nie jestem największym fanem tego w jaki sposób wyglądają obecnie przeszkody - materiał klocków mógłby być ładniejszy. Można w tym miejscu nawet pobawić się shader’ami.
Pomimo że wszystkie obiekty są sześcianami, detekcja opiera się na odległości po promieniu okręgu o środku wewnątrz sześcianu - to powoduje że czasami pomimo dotknięcia krawędzi przeszkody uda się nam ujść z życiem.
Choć sześcian się wpisuje w kwadratowy wygląd świata przedstawionego, zdecydowanie ciekawym pomysłem byłaby możliwość dodania modelu, którym sterował by gracz zamiast sześcianu.
Do stworzenia projektu wykorzystałem głównie oficjalną dokumentację RTF, oraz pomniejsze strony służące jako poradniki do obsługi tej biblioteki:



