Najlepsze roguelike nie tylko cię zabijają. One sprawiają, że chcesz umrzeć.
Brzmi to dziwnie, ale każdy, kto przegrał run o północy i zaczął kolejny o 12:03, zna to uczucie. Śmierć boli. Twoje zdrowie spada do zera. Ekran zalewa porażka. A jednak twój palec już wisi nad przyciskiem „play”. Coś w tych ostatnich dwudziestu minutach było na tyle istotne, że nie możesz zostawić gry w miejscu, w którym się skończyła.
To pętla „jeszcze jeden run” i nie jest ona dziełem przypadku. Została zaprojektowana. Jeśli budujesz roguelike lub jakąkolwiek grę z mechaniką permadeath, twoim całym zadaniem jest zbalansowanie dwóch przeciwstawnych sił. Gracz musi przegrywać wystarczająco dużo, by czuć napięcie. Musi zachowywać wystarczająco dużo, by czuć nadzieję.
Waluta porażki
W moim najnowszym projekcie, Neon Survivor, chciałem uzyskać właśnie takie napięcie. Gdy gracz ginie, wszystko, co zebrał podczas runu, znika z wyjątkiem jednej rzeczy: złota. To złoto jest automatycznie deponowane. W menu gracz wydaje je na stałe ulepszenia. Następnie wskakuje do gry ponownie, będąc nieco silniejszym niż wcześniej.
Ta prosta pętla napędza całą grę. Bez niej śmierć jest kropką. Gracz odchodzi, ponieważ ostatni run nie przyniósł mu niczego. Z nią śmierć jest przecinkiem. Run stał się wyprawą po łupy. Strata boli, ale zapłaciła też za jutro.
Trik jest prosty. Zachowujesz coś, nawet gdy tracisz wszystko inne. Trudność polega na tym, aby to, co zachowujesz, miało znaczenie, nie niszcząc przy tym wyzwania. Jeśli ulepszenia są zbyt słabe, gracz przestaje się nimi przejmować. Jeśli są zbyt silne, gra gra się sama. W obu przypadkach pętla się rozpada.
Dwa zegary, zero zamieszania
Aby zbudować to właściwie, musiałem zarządzać dwiema oddzielnymi osiami czasu.
Zegar Runu (Run Clock) resetuje się za każdym razem, gdy naciśniesz play. Śledzi zdrowie, aktualny wynik, liczbę fal przeciwników i wszelkie tymczasowe wzmocnienia zebrane podczas sesji. Gdy postać ginie, zegar ten cofa się do zera.
Zegar Meta (Meta Clock) nigdy się nie resetuje. Przechowuje całkowitą ilość zdobytego złota ze wszystkich prób, najwyższą osiągniętą falę oraz wszystkie zakupione stałe ulepszenia. Ten zegar tyka bez względu na to, ile razy odświeżysz przeglądarkę.
Wymieszaj te dwa zegary, a otrzymasz błędy, które trudno namierzyć i boleśnie naprawić. Widziałem deweloperów, którzy przypadkowo kasowali postępy graczy podczas rutynowego resetowania sceny, ponieważ funkcja czyszcząca dotknęła niewłaściwego magazynu danych. Dane Zegara Meta wyparowują. Gracz wraca do zera złota i zera ulepszeń. W tym momencie relacja między tobą a graczem zostaje zerwana. On nie zaczyna nowego runu; on zaczyna nową urazę.
Utrzymywanie zegarów oddzielnie to nie tylko wybór stylistyczny. To strategia przetrwania.
Jak Phaser v4 radzi sobie z tym podziałem
Zbudowałem Neon Survivor w Phaser v4, który oferuje dwa konkretne narzędzia do tego problemu.
Registry przechowuje dane na żywo w pamięci dla bieżącej sesji. Jest szybkie. Jest proste. Wyparowuje jednak w momencie, gdy gracz odświeży stronę.
LocalStorage zapisuje dane bezpośrednio w przeglądarce. Przetrwa zamknięcie karty, restart przeglądarki i przerwy w dostawie prądu. Jest jednak wolniejsze i mniej niezawodne. Przeglądarki mogą je blokować, ograniczać lub czyścić, jeśli limity pamięci zostaną wyczerpane.
Mój wybór projektowy był rygorystyczny. Registry jest jedynym źródłem prawdy podczas rozgrywki. Gra czyta z niego, zapisuje w nim i całkowicie mu ufa. LocalStorage nie pełni roli współautora. Pełni rolę lustra.
Oto jak działa ten przepływ. Gra zapisuje zakup ulepszenia w Registry. Pojedyncza klasa menedżera obserwuje Registry. W odpowiednim momencie menedżer ten lustruje dane z Registry do LocalStorage. Jeśli przeglądarka zablokuje zapis, gra nie będzie zacinać. Jeśli zapis w pamięci zawiedzie, bieżąca sesja nadal będzie działać idealnie. Gracz może stracić postęp tylko wtedy, gdy zamknie kartę w tej samej sekundzie, ale sama sesja nigdy się nie zawiesi.
Ten wzorzec zapobiega subtelnym katastrofom. Jeśli pozwolisz każdemu systemowi zapisywać dane bezpośrednio do LocalStorage, stworzysz zależności od kruchego API. Gracz z mocno ustawionymi ustawieniami prywatności lub urządzeniem z małą ilością miejsca może zauważyć spowolnienie lub zawieszenie gry podczas walki, ponieważ jakaś funkcja działająca w tle próbowała zapisać statystyki. Poprzez uczynienie Registry jedynym źródłem prawdy, utrzymujesz szybką akcję i ograniczasz ryzyko.
Pozwól kodowi oddychać
Użyłem również zdarzeń, aby odizolować systemy od siebie. Gdy run się kończy, GameScene nie zajmuje się własnym pogrzebem. Nie wywołuje funkcji zapisu. Nie importuje narzędzia do przechowywania danych. Po prostu emituje zdarzenie „run-ended” z ładunkiem odpowiednich danych.
A separate listener handles the bookkeeping. It receives the event, updates the Meta Clock, and tells the manager to mirror the new totals to LocalStorage.
This separation pays off immediately. I can rewrite the entire GameScene, swap out the player character, change the camera angle, or even shift the genre from survival to bullet hell without touching the save system. The systems are independent. They talk through events, not direct function calls. That means fewer merge conflicts, fewer bugs, and a codebase that does not turn into spaghetti after six months.
Upgrades That Change the Game
Having a technical backbone is useless if the rewards feel like a spreadsheet. I spent a lot of time on how upgrades actually feel to play.
Some upgrades are safe. Extra movement speed. Bonus health. Faster reload. These give the player more room for error. They are comforting. They shrink the game without changing its rules.
Other upgrades rewrite the rules entirely. In Neon Survivor, I added "Piercing Rounds." Before this upgrade, a bullet stopped on the first enemy it hit. After the upgrade, it punches through enemies, potentially clearing entire lines in a single shot.
The difference is dramatic. Speed and health might let you survive longer, but Piercing Rounds changes how you position yourself. You start lining up enemies. You stop kiting around the edges and start cutting through the center. The decision space of the game expands.
Good progression should change a player's decisions, not just increase their numbers. If every upgrade is a percentage bump, the player stops reading the descriptions. They click, they upgrade, they forget. If an upgrade makes them rethink their strategy, they remember it. They talk about it. They come back to see what else might flip the game on its head.
The Real Payoff
The "one more run" loop is not a single system. It is a relationship between loss and gain, built on clean architecture and meaningful rewards.
Build two distinct timelines and protect the Meta Clock like it holds your players' trust, because it does. Use your engine's tools to keep live data fast and persistent data safe. Decouple your scenes from your storage so you can iterate without fear. And when you design upgrades, ask whether they give the player more time, or more interesting choices.
Get this right, and your players will not just tolerate death. They will depend on it. Every run becomes a down payment on the next one. The game stops being a series of restarts and becomes a single, continuous climb.
