Vanar.io
Koniec sesji, upały oraz skręcona kostka poskutkowały nadmiarem wolnego czasu, więc postanowiłem spróbować czegoś nowego. Chociaż właściwie jako bordo i tak bym to napisał bez względu na okoliczności, bo po prostu lubię programować ;) Ostatnie projekty na studiach wybitnie mnie zanudziły, więc szukałem sobie czegoś przyjemnego i rozwijającego. Jako że gry multiplayer w przeglądarce ostatnio są całkiem popularne, nigdy czegoś takiego nie pisałem i lubię tworzyć aplikacje sieciowe, wybór był dość prosty. W efekcie powstała gra //vanar.io, w której wcielasz się w kosmonautę, zasiadasz za sterami statku kosmicznego i niszczysz innych. Na pierwszy rzut oka nic skomplikowanego, ale nie o to chodziło.
//vanar.io
Dlaczego taka gra?
Nie pasjonuję się grami na tyle, żeby tworzyć coś o rozbudowanej fabule, nie jestem też grafikiem. Jako programista szukałem czegoś, co koncepcyjnie będzie banalnie proste, lecz nietrywialne do napisania. Przypomniało mi się, że z dobre 10 lat temu w jakiejś starej dystrybucji Mandrake'a była dołączona gra, w której latało się statkiem kosmicznym i strasznie mnie wciągnęła. A więc padło na dynamiczną grę multiplayer i patrząc z perspektywy czasu, była to dość dobra decyzja - problemów było sporo i był to całkiem niezły wstęp do gamedevu. Wyszło około 13 000 linii kodu, więcej niż się spodziewałem.
Wybór technologii
Tutaj sprawa była prosta - skoro gra po stronie klienta działa w JavaScripcie a spora część kodu miała być współdzielona, najwygodniej na serwerze użyć tego samego - czyli NodeJS. Do tego jeszcze Redis do trzymania informacji o podłączonych serwerach, jakieś reverse-proxy i można działać.
Problemy z wydajnością
Niby V8 i inne nowe silniki JavasScript są szybkie, ale nadal zupełnie się nie nadają do takiej ilości obliczeń. Uzyskanie płynnej animacji wymagało spędzenia prawie tygodnia na jsperf.com (chwilowo leży, trzeba wchodzić przez cache google), przepisywania każdego fragmentu kodu po kilka-kilkanaście razy i użycia masy różnych sztuczek żeby poprawić wydajność i zminimalizować czas działania garbage collectora. Zaskoczeniem było, że po stronie serwera udało mi się uzyskać prawie dwukrotny wzrost wydajności, gdy zacząłem intensywnie używać nowości z EcmaScript 6. Tak czy inaczej strasznie syzyfowa praca, ale na szczęście jak się już raz przez to przejdzie, to później już się pamięta czego się wystrzegać...
Sam canvas również nie powala wydajnością, zwłaszcza gdy włączy się tryb pełnoekranowy. Szybkie rysowanie dynamicznych obiektów jest właściwie niemożliwe i wszystko trzeba intensywnie cache'ować. Może sytuacja się poprawi wraz z rozwojem WebGL.
Problemy z lagami
To bardzo fajny temat i jedno z głównych wyzwań w tym projekcie. W internecie można znaleźć sporo ciekawych artykułów jak radzono sobie z tym w Quake'u (który podobno przecierał szlaki) i jak się to robi obecnie. Trochę zdziwił mnie na początku fakt, że model symulacji
//vanar.io najbardziej przypomina ten z fpsów i ostatecznie skorzystałem z podobnych tricków. Jakby ktoś chciał o tym więcej poczytać to dobry wstęp daje ten artykuł:
//www.gabrielgambetta.com/fpm1.html
Boli mnie tylko, że w moim przypadku do skaczącego pingu dokłada się jeszcze podła wydajność JavaScriptu i jednowątkowe przetwarzanie danych. Pakiety są przetwarzane z jeszcze większym, mocno losowym opóźnieniem a przy dynamicznych zmianach przewidywanie stanów nie działa tak dobrze jak powinno i czasami widać lekkie lagi nawet na dobrym łączu.
Wnioski
Przyjemnie się to pisało, ale przy obecnej wiedzy pewnie nie zdecydowałbym się na napisanie takiej gry. Jest zbyt dynamiczna jak na możliwości JavaScriptu i mam wrażenie, że nie działa tak dobrze jak powinna. Ale może to tylko ja jestem przewrażliwiony, bo gapiłem się na to przez ostatnie 2.5 tygodnia ;) Chętnię usłyszę Wasze opinie i odpowiem na pytania.
I na koniec bonus dla graczy CS:GO i innych fpsów
Nie używajcie magicznych, "poprawiających" wydajność configów, które wyłaczają interpolację i inne mechanizmy walczące z lagami. Na pierwszy rzut oka może wyglądać to lepiej, ale w praktyce będziecie znacznie rzadziej trafiać przeciwnika (mimo animacji trafienia, którą zobaczycie na ekranie). Jednym z podstawowych tricków przy pisaniu dynamicznych gier jest wyświetlanie przeciwników z lekkim opóźnieniem, dzięki czemu nie trzeba zgadywać gdzie przeciwnik znajdzie się w następnej klatce, gdyby pakiety przyszły po czasie. Efekt jest taki, że zawsze strzela się do pozycji graczy z przeszłości a nie ich obecnego położenia. Serwer otrzymując pakiet informujący o strzale nie bierze pod uwagę stanu teraźniejszego, lecz odtwarza stan z przeszłości - tak jak to widział klient - na podstawie czasu wysłanego w pakiecie. Jeżeli wyłączycie interpolację możecie widzieć inny stan, niż ten odtworzony przez serwer - i nie będziecie trafiać. Warto też wspomnieć o jeszcze jednym skutku tego mechanizmu: nawet nie mając lagów, możecie zostać zabici zaraz po tym jak schowacie się za ścianą - ktoś mógł trafić w odtworzonym stanie w przeszłości.
O tym jak to jest zaimplementowane w CSie można poczytać tutaj:
https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
Komentarze (209)
najlepsze
1. Ile masz lat?
2. Studiowales czy sam sie uczyles?
3. Dlugo programujesz?
Dużo fajniej by sie grało, jak by statek podążał za kursorem myszki :), takie sterowanie.
Vanar.io can't be played on a mobile device.
Szkoda(╯︵╰,)
Możesz przybliżyć które rzeczy z es6 okazały sie wydajniejsze? masz na mysli client czy serwer?
2) stawiasz na DigitalOcean, ma znaczenie wydajnośc maszyny? Czy opoznienie pakietów wynika z tego że serwer ma zbyt dużo obliczeń,pakiety są za duże, czy to po prostu cecha sieci. Chodzi mi o to czy
Fakt - automatyczne sprawdzanie, byłoby mniej uciążliwe, ale dla takiej pierdółki nie ma sensu kombinować z "hackami". Oczywiście pozostaje kwestia czemu akurat klawiatura bluetooth nie działa zgodnie z założeniami.
https://youtu.be/xv50Ln6lEbk
1) Czemu teraz? Przeciez gdybyś wystartował wcześniej niż agar miałbyś już mega ustawione wszystko
2) Nie obraź się na przezwiska
3) Czemu nodejs ? Każdy doświadczony wie że w websocketach się nie nadaje. ?
Dzięki za mega gierke - zastępstwo za agario znalezione - gratulacje i życzę sukcesów .
@KubusiowyKubus: Dlaczego w websocketach nie? Co innego proponujesz?
ale propsy dla @snowak'a :)
;-)
1. DŹWIĘKI!!! - dowolne, darmowe dźwięki na strzał, trafienie, poruszanie się, jakiś 'ambient sound' w tle i najważniejsze - zniszczenie.
2. Respawn na klawisz "spacja" , "R" , "enter".
3. Upgrade pocisków - zaczynasz od pojedynczych, zwiększasz ich skuteczność.
4. Faktycznie, problem z dużymi postaciami jest istotny - powinieneś dodać jakiś element, który pozwala na atak z poziomu małych statków - Laser, który rozbija te
Szkoda ze na telefonie nie pogram ;(
Komentarz usunięty przez moderatora
Genialnie by było dodać hamowanie lub ruch do tyłu na np. "s"