Hypersomnia - multiplayer top-down shooter z otwartym źródłem


#1

Hypersomnia to rozwijana przeze mnie strzelanka z widokiem z góry, której dynamika i zachowanie kamery są silnie inspirowane grą Hotline Miami (ale oprócz tego nie ma z nią absolutnie nic wspólnego). Mam ambicję aby stworzyć z niej kiedyś MMO z persystentnym światem, gdzie podobnie jak w Tibii można będzie rozwijać swoją postać, będąc nieustannie ostrożnym aby nie umrzeć ze względu na drastyczne tegoż konsekwencje. W pierwszej kolejności jednak zaprogramuję prostą arenę na szybkie mecze.

Gra osadzona będzie w hipotetycznej, pośmiertnej rzeczywistości zamieszkałej przez trzy frakcje istot które pozostają we wrogich stosunkach przez wzgląd na różniące je poglądy o moralnej doskonałości; frakcje te zwane są kolejno: Metropolis, Atlantis oraz Resistance.

Głównymi elementami rozgrywki będą bronie palne z fizycznymi pociskami, szybkie pojazdy oraz zaklęcia które w tym uniwersum nie są rezultatem magii znanej z gier fantasy - będzie to raczej materia programowalna umysłem.

Widok z menu głównego:

Fragment scenki z intro:

Filmik z gameplayu wraz z moim komentarzem głosowym można oglądnąć tutaj:

Gra ma oraz zawsze będzie miała otwarte źródło na GitHubie, które można zbudować w dosłownie dwóch krokach w Visual Studio 2015 lub nowszym:

Licencja którą stosuję to AGPL-3.0.
Cała gra pozostanie również na zawsze darmowa, z jedynym wyjątkiem opłaty za dostęp do oficjalnego serwera gry jeżeli taki kiedyś powstanie - ten niestety sam się nie opłaci. Nic jednak nie będzie stało na przeszkodzie aby samemu zahostować taki serwer do gry z kolegami, nawet komercjalny.

Grę piszę w C++ z pomocą surowego OpenGL. Wykorzystuję poboczne biblioteki takie jak: Box2D do fizyki, Lua do skryptów konfiguracyjnych, Luabind, FreeType do czcionek, ENet do networkingu, googletest do testowania, OpenAL Soft do dźwięku, libsndfile do ładowania plików dźwiękowych, lodepng do ładowania plików .png oraz libmicrohttpd do hostowania widgeta z informacjami o serwerze który pojawia się na moim blogu gdy serwer Hipersomnii jest włączony na moim roboczym komputerze.

Projekt rozwijam mniej więcej od półtora roku kiedy to zacząłem mieć czas aby wziąć się za niego na poważnie.

Zapraszam na mojego developerskiego bloga aby uzyskać pojęcie o wszystkich już istniejących funkcjonalnościach gry:

http://hypersomnia.pl/


#2

@Hypersomnia Dawno nikt nie zamieścił linka do tak zaawansowanego projektu, obowiązkowo na gamedev.pl (instrukcja) ! :slight_smile:


#3

Update - tym razem nieco bardziej techniczny - gra na pierwsze uruchomienie automatycznie regeneruje atlasy, mapy neonów, fonty i oskryptowane tekstury dla gui. Potem już tylko wczytuje wszystko bez przetwarzania, wobec czego czas startu spadł o jakiś ułamek sekundy - zawsze coś, zważając na to, że startuję grę tysiące razy:

http://hypersomnia.pl/newscast/content-pipeline-neon-atlas-regeneration


#4

Fajne.
Jeśli byś chciał robić następną grę z kimś, to napisz, szczególnie jeśli będziesz realizował ten MMO-like. Jestem programistą i szukam kogoś na moim lub trochę wyższym poziomie w celu nauki, zabawy, tworzenia.

Pozdrawiam
Michał


#5

Efekty cząsteczkowe robią naprawdę pozytywne wrażenie :slight_smile: keep up the good work, jak bede miał dostęp do kompa to chętnie zajrzę do kodu


#6

Właśnie nagrałem nowy gameplay, tym razem wprowadziłem granaty:

Zaprogramowałem też w międzyczasie wygodny support dla introspekcji typów w C++,
który pozwala mi wywołać dowolną generyczną lambdę na wszystkich składnikach dowolnego typu:

Więcej info w artykule:

http://hypersomnia.pl/newscast/grenades-and-introspection


#7

W ramach chwilowej przerwy od projektu zakodziłem sobie symulator mechanicznej klawiatury - program generuje dźwięki za każdym razem gdy jakiś przycisk na klawiaturze jest wciśnięty lub puszczony. Jest też opcjonalny support dla myszki, ale niestety czasami GetAsyncKeyState jej nie łapie, nie wiem czemu.

Dźwięki są odtwarzane przestrzennie w zależności od pozycji przycisków na klawiaturze.

Wierzcie lub nie, takie klikanie w słuchawkach daje mi natchnienie.


#8

Jakieś postępy ? Bo projekt bardzo ciekawy a od pewnego czasu cisza :frowning:


#9

(Sorki - coś tu się ten markdown sypie przy listach i fragmentach kodu więc może być gdzieniegdzie rozjechane)

Niestety nie zrobiłem jeszcze żadnych nowych gameplayowych ficzerów @Spicmir , same techniczne rzeczy więc wolałem nie zanudzać, ale skoro zostałem zapytany to napiszę tutaj co zrobiłem od tamtej pory :slight_smile:

  • Zmiany w użyciu zależności:

  • zamieniłem luabind na nowoczesny sol2,

  • zamieniłem googletest na Catch,

  • zamieniłem masywny libsndfile na biblioteki ogg + vorbis. Gra jest budowana w pełni statycznie i już nie korzysta z ani jednego osobnego DLLa!

  • zamieniłem glew na generowany przy każdej kompilacji glad.

  • Całe budowanie projektu zostało przepisane na CMakeLists.txt. Oznacza to, że w repozytorium już nie będzie visualowych .sln, .vcxproj, a raczej można sobie wygenerować pliki projektu na jakiekolwiek środowisko - jest to też, oczywiście, pierwszy krok do sportowania tej gry na Linuxa.
    Dodatkowo, aktualizacja wszystkich zależności jest tak prosta jak wpisanie jednej komendy do gita - nie muszę nic zmieniać w swoim projekcie.

  • W CMakeLists.txt zrobiłem flagi do warunkowej kompilacji OpenAL, ENet, unit testów oraz whardcodowanych w C++ testowych scen do debugowania gry.
    Dzięki temu można sobie zbudować minimalną binarkę gry kompletnie bez dźwięku albo networkingu. Przydaje się ogromnie przy codziennym rozwijaniu żeby szybciej przebudowywać.

    option(BUILD_SOUND_FORMAT_DECODERS “Build ogg and vorbis. If this is off, there is also no point in enabling OpenAL.” ON)
    option(BUILD_OPENAL “Build OpenAL Soft.” ON)
    option(BUILD_UNIT_TESTS “Build unit tests that are run on game startup.” ON)
    option(BUILD_VERSION_FILE_GENERATOR “Build version file generator to generate commit information.” ON)
    option(BUILD_ENET “Build ENet networking library.” ON)
    option(BUILD_TEST_SCENES “Build unscripted test scenes hardcoded in C++.” ON)

  • Przy wybranej w Visualu konfiguracji Release, po zakończeniu budowania odpalany jest automatycznie 7-Zip który kompresuje wszystkie potrzebne pliki gry i wypluwa do wyznaczonego folderu gotowe archiwum podpisane numerem commita.

  • Zakodziłem version file generator który przy każdym rozpoczęciu budowania w Visualu generuje taki oto plik .cpp, do wykorzystania z kodu gry:
    (oczywiście opcjonalnie dodany z CMakeLists)

    #include “hypersomnia_version.h”
    #include “generated/setting_was_version_generator_built.h”

    #if WAS_VERSION_GENERATOR_BUILT

    unsigned HYPERSOMNIA_COMMIT_NUMBER = 3719;
    std::string HYPERSOMNIA_COMMIT_MESSAGE = “moved ingredients/ to hardcoded_content/”;
    std::string HYPERSOMNIA_COMMIT_DATE = “Thu Jun 15 23:22:35 2017”;
    std::string HYPERSOMNIA_COMMIT_HASH = “d09479e16fd9a8bbe4a8a17ed9811698ebf3594a”;
    std::vectorstd::string HYPERSOMNIA_WORKING_TREE_CHANGES = {
    “src/game/transcendental/cosmos_structs.h”,
    “src/game/transcendental/data_living_one_step.h”,
    };

    #else

    unsigned HYPERSOMNIA_COMMIT_NUMBER = 0;
    std::string HYPERSOMNIA_COMMIT_MESSAGE = “Unknown”;
    std::string HYPERSOMNIA_COMMIT_DATE = “Unknown”;
    std::string HYPERSOMNIA_COMMIT_HASH = “Unknown”;
    std::vectorstd::string HYPERSOMNIA_WORKING_TREE_CHANGES = {};

    #endif

Masywny refactor w kodzie:

  • komponenty damage, grenade oraz contact_explosive zostały zastąpione komponentami missile, explosive oraz hand_fuse z odpowiednimi parametrami.
    Umożliwiają w prosty sposób stworzenie bytów takich jak pociski, rzucalne granaty oraz wybuchające rakiety. Test rocket launchera już był!
  • powszechne wykorzystanie konstruktów C++17 takich jak constexpr if, std::variant, std::optional.

Masywne poprawki (uproszczenia) do kodu introspekcji, przykłady:

  • czyścimy obiekt który zawiera kilka różnych kontenerów:

      augs::introspect(
      	[](auto, auto& member) {
      		member.clear();
      	},
      	*this
      );
    

(pierwszym argumentem jest zawsze nazwa pola)

  • przepisujemy, rekursywnie, z jednego komponentu do drugiego komponentu, tylko obiekty o typie child_entity_id:

      augs::introspect(
      	augs::recursive([&](auto&& self, auto, auto& into, const auto& from) {
      		if constexpr(std::is_same_v<decltype(into), child_entity_id&>) {
      			into = cosm.clone_entity(from);
      		}
      		else {
      			augs::introspect_if_not_leaf(augs::recursive(self), into, from);
      		}
      	}),
      	cloned_to_component,
      	cloned_from_component
      );
    

C++ nie supportuje w ludzki sposób rekursywnych lambd bez uciekania się do std::function, a generycznych rekursywnych lambd już w ogóle, więc potrzebny jest trick rodzaju augs::recursive:

    template <class F>
    auto recursive(F&& callback) {
    	return [&](auto&&... args) { 
    		callback(
    			std::forward<F>(callback), 
    			std::forward<decltype(args)>(args)...
    		);
    	};
    }
  • mocniejsze unit testy, np. sprawdzanie przez introspekcję czy składniki trywialnych struktur są ułożone obok siebie w pamięci
    (czy kompilator nie wsadził paddujących bajtów)

  • dodana domowa introspekcja enumów:

      enum class launch_type {
      	// GEN INTROSPECTOR enum class launch_type
      	MAIN_MENU,
      	LOCAL,
      	LOCAL_DETERMINISM_TEST,
      	DIRECTOR,
      	CHOREOGRAPHIC,
      	ONLY_CLIENT,
      	ONLY_SERVER,
      	CLIENT_AND_SERVER,
      	TWO_CLIENTS_AND_SERVER,
      	COUNT
      	// END GEN INTROSPECTOR
      };
    

generuje:

template <class... T>
const char* enum_to_string(const launch_type e, T...) {
	switch(e) {
	case launch_type::MAIN_MENU: return "MAIN_MENU";
	case launch_type::LOCAL: return "LOCAL";
	case launch_type::LOCAL_DETERMINISM_TEST: return "LOCAL_DETERMINISM_TEST";
	case launch_type::DIRECTOR: return "DIRECTOR";
	case launch_type::CHOREOGRAPHIC: return "CHOREOGRAPHIC";
	case launch_type::ONLY_CLIENT: return "ONLY_CLIENT";
	case launch_type::ONLY_SERVER: return "ONLY_SERVER";
	case launch_type::CLIENT_AND_SERVER: return "CLIENT_AND_SERVER";
	case launch_type::TWO_CLIENTS_AND_SERVER: return "TWO_CLIENTS_AND_SERVER";
	case launch_type::COUNT: return "COUNT";
	default: return "Invalid";
	}
}

(templatka po to aby nie skompilowała się dopóki jej nie użyję)

  • Config umożliwia ustawianie klawiszy sterowania (tu też wykorzystałem automatyczną introspekcję enumów).
  • Mnóstwo innych refactorów których nie sposób tutaj wspomnieć.

A tak w ogóle to ktoś z Softpedii znalazł mój Mechanical-keyboard-simulator, wrzucił go tam i napisał recenzję!

Teraz wybieram się w kierunku edytora do gry, będę musiał odświeżyć swój kod GUI sprzed kilku lat :smiley: . Chcę wreszcie jakąś ładną scenę ustawić i zrobić fajne ciało fizyczne dla gracza, potem zrobię jakiś deathmatch przez sieć, która to sieć już w sumie od jakiegoś czasu działała, tylko nie miała sensu bo nie było przeładowywania, odradzania po śmierci etc.


#10

Mimo że większość Twych słów brzmi dla mnie jak zaklęcia bojowe cybermaga to są one jak miód na me serce … (Jestem osobą która nawet w game makerze nie potrafi nic spłodzić) Dobrze że się dzieje i to nie mało. Cieszy mnie to ogromnie bo projekt niewiarygodnie ciekawy. Trzymam mocno kciuki i z niecierpliwością czekam nawet i na ‘magiczne’ newsy.


#11

Bardzo fajnie to wygląda, nie ma nic bardziej zachęcającego do gamedevu jak oglądanie czyjejś pracy, i to w takim stadium :slight_smile:

Pozdrawiam i życzę powodzenia przy dalszym prowadzeniu projektu. :wink:


#12

Nowy czar - uzdrawiający. Niedługo napiszę coś więcej, nie obijałem się w każdym razie.


#13

jak zawsze wygląda to świetnie. :thumbsup: czekamy na jakieś nowe wieści :wink:


#14

Zapytam się bo strasznie mnie to nurtuje od dłuższego czasu. Czy to wszystko musi być takie ciemne? Widzę dość dużo gier amatorskich robionych w stylu “zróbmy wszystko czarne”. Ja rozumiem klimat, ale tu nic nie widać, to strasznie męczy wzrok. Czy tylko ja mam takie odczucia?:slight_smile: Chodzi o to aby ukryć kiepską grafikę(nie piszę tego złośliwie-sam znam ból graficzny)?


#15

@Leon Nie tylko Ty masz takie odczucia! Ta sama obserwacja została poczyniona przez parę jeszcze innych osób :grinning:

Finalnie oczywiście nie będzie to takie ciemne, prawie wszystkie przedmioty i postacie będą miały własną emisję światła (tak jak np. ma motor lub ciężarówka), oprócz mocnych dynamicznych świateł które teraz widać na środku sceny. Tak ciemno raczej nie będzie nigdzie oprócz jakichś bezludnych obrzeży Metropolii, ale i tam się zdarzą jakieś uliczne światełka.

Po prostu jak już dodałem do sceny oświetlenie to nie chciało mi się na razie wszędzie rozstawiać tych świateł więc mi się zdarzają takie ciemne screeny, ale fakt, lepiej jak będę je nagrywał bliżej tych źródeł :smiley:

W każdym razie, teraz jak już będę (mam nadzieję niedługo!) miał edytor, to gwarantuję, że każda nieoświetlona strefa otrzyma tyle miłości na ile zasługuje.


#16

Jakieś wieści z frontu ?podziel się co nowe :wink:


#17

@Spicmir Wybacz proszę moje milczenie, ale na więcej wieści jeszcze trzeba będzie poczekać - zacząłem właśnie pracę nad edytorem, chciałbym coś w tym zakresie ukończyć zanim zrobię kolejne nagranie na YT. Dla bardziej dociekliwych jest zawsze log commitów do repozytorium, a choć zwykle mówią niewiele - zawsze mogą służyć za dowód na to, że moje procesy życiowe jeszcze nie zanikły! :smiley:


#18

Toć wiara ma w ciągłą prace nad gra nigdy nie przygasła. Jedynie ciekawość jak owe prace idą posunęła mnie do popełnienia tamtego pytania. Za wskazówką rzuciłem się na Hipersomniczne zasoby i przeżyłem niemały szok.
Ciągle żyłem w przekonaniu że to jednoosobowy projekt.


#19

Projekt wciąż żyje! Jest trochę zmian których na razie nie mam czasu opisywać, a na ten moment małe co nieco z powstającego edytora (in-game):


#20

News: W tym miesiącu zająłem się czymś innym od edytora, a jest to…

Hypersomnia na Linuxie!
Przeniosłem się z Windowsa na Arch Linuxa z managerem i3 i zamierzam tutaj kontynuować rozwój gry. System pokonfigurowałem pod siebie do tego stopnia że wszystko robi mi się o wiele szybciej niż na Windowsie.

Najbardziej żmudną robotą było chyba poprawianie błędów kompilacji na GCC 7.2, ze względu na to że MSVC jest niesamowicie dozwalający, m. in. przepuszcza w ciele templatów losowe ciągi znaków dopóki ten template nie zostanie użyty.

Wrzuciłem też Hypersomnię na Appveyora i Travisa, dzięki czemu jak coś się zepsuje na którejś platformie to powinienem wiedzieć od razu, w miarę staram się aby oba buildy miały okejki.

Oczywiście raz na czas będę sprawdzał osobiście czy wszystko działa pod Windowsem! Będę wspierał aktywnie obie platformy.