[WWW] Rozbudowa w grze po wylogowaniu gracza


#1

Cześć!

Ostatnio zastanawiałem się nad stworzeniem na prawdę prostej gry ekonomicznej… nie dla opublikowania czy zarobku tylko tak dla siebie - dla własnej satysfakcji i nauki.

Myślałem o grze dostępnej przez www - powiedzmy coś na wzór ogame, aby lepiej przybliżyć w czym leży mój problem.

Nie do końca wiem jak poprawnie rozwiązać sytuację, że gracz rozpoczyna budowę budynku, który ma wpływ na produkcję jednego z surowców (ma to jakąś fachową nazwę?).

Próbują to zrobić korzystając z systemu kolejkowania zadań, czyli:

  1. Gracz klika rozbudowę kopalni na 2 lvl - budowa trwa np. 10 min. (po żądaniu rozbudowy wylogowuje się z gry)
  2. Skrypt zapisuje w bazie danych czas rozpoczęcia, zakończenia tej budowy plus inne dane wiążące wpis z graczem.
  3. W tle działa skrypt php (laravel queue), który wykonuje to zadanie gdy czas zakończenia zostanie osiągnięty.
  4. Wykonanie zadania dolicza graczowi surowce do czasu zakończenia kopalni na 2 lvl po stawce kopalni z 1 lvl i zwiększa poziom kopalni na 2 lvl, aby zacząć naliczać surowce po wyższej stawce.

Czy to ma sens? Czy są inne sposoby na to?


#2

Nie implementowane w praktyce i może wyjść dość zagmatwanie, ale:

  1. Gracz żąda rozbudowy -> zapisujemy czas startu, końca.
  2. Dopóki gracz nie wróci nic się nie zmienia (surowce etc…), CHYBA, ŻE
    3. Cokolwiek będzie żądać zasobu związanego z tym wydarzeniem (ktoś chce podejrzeć surowce / ukraść itd) -> Wtedy przeliczamy jaki powinien być stan aktualny
  3. Gracz wraca do gry - przeliczamy aktualny stan.

Nie wiem czy ma sens wtrącać tu Event Sourcing, ale może warto by poczytać, czy da się to jakoś razem połapać :wink:


#3

Można też spróbować zrobić coś w stylu time-based-turn. Czyli wszystko dzieli się na przykład na 5 minut i co 5 minut na serwerze update wszystkich stanów. Dla niewielkiej ilości graczy nie powinno być problemu, a wydaje mi się nieco prostszym rozwiązaniem niż powyższe (niekoniecznie lepszym)


#4

Pisałem już podobnie gierki, to mogę coś doradzić.
Sprawa jest prostsza niż się wydaje, można zrobić jedną akcje na raz, albo kolejkę.

  1. Gracz klika rozbudowę kopalni, która trwa na przykład 10minut
  2. Zapisujemy w bazie, przykładowo w oddzielnej tabeli
    1. id użytkownika
    2. typ budynek/statek/badanie itp
    3. id budynku/statku/badania
    4. datę startu
    5. czas budowy

Jeśli to ma być kolejka akcji, to datę startu, ma tylko pierwszy obiekt na liście.
Musisz uwzględnić w kolejce, że ktoś będzie chciał 2x ten sam obiekt wybudować, wiec musi odpowiednio program obliczyć czas i pobrane surowce, dla wyższego poziomu.
Surowce możesz pobierać od razu, dodając do kolejki, albo żeby zabezpieczyć, przed ukrywaniem surowców przez graczy przed innymi, pobierać w momencie, gdy dany obiekt ma rozpocząć budowę. Budowa rozpocznie się, gdy jest wystarczająca liczba surowców.

Wszelkie akcje związane z aktualizacją stanu konta, zasobów, badań, robisz, w momencie gdy jest to potrzebne.
Więc przykładowo, gracz zaloguje się na konto, w tym momencie program sprawdza tabele kolejki

  1. Budowa kopalni na poziom 2 (czas 10 min)
  2. Budowa kopalni na poziom 3 (czas 15 min)
    gracz zalogował sie po godzinie, wiec od czasu pierwszej akcji do teraz, mineło 60 minut.

W pętli pobieramy

1 obiekt, czas budowy minał, wiec dodamy poziom kopalni i zwiększamy wydobycie
przeliczamy surowce według aktualnego stanu wydobycia, od ostatniego przeliczenia do zakończenia budowy

2 obiekt, czas budowy minał, wiec dodamy poziom kopalni i zwiększamy wydobycie
przeliczamy surowce według aktualnego stanu wydobycia, od ostatniego przeliczenia do zakończenia budowy lub jeśli to ostatni element który został przetworzony, przeliczamy od ostatniego przeliczenia do teraz.

Wszystko się aktualizuje, dopiero gdy właściciel konta, lub inny gracz, będzie wchodził w interakcje z danym kontem. Na przykład gracz zaloguje się na swoje konto, ktoś skanuje stan surowców lub atakuje. Z atakowaniem jest analogiczna sytuacja, gracz wysyła swoje wojsko na innego gracza. Czas ataku to 20 min. Ale przez 6h oboje się nie zalogują do gry, ani nikt inny nie będzie skanował/atakował tych graczy, to bitwa rozegra się w momencie, gdy na przykład jeden z nich się zaloguje.


#5

Ja jako doświadczony programista Symfony oparłbym to właśnie o skrypty wykonywane CRONem co minutę. Tylko że w Symfony to nie są skrypty tylko command, ale to szczegół.
Zrobiłbym kilka takich skryptów/command dla różnych zadań np:

  • budowanie budynków
  • naliczanie surowców
  • poruszanie się
  • itd

Wadą użycia CRON jest odpalanie tych skryptów/command co minutę, więc sekund tak nie ogarniesz. Sekundy musiałyby być ogarniane przez jeden skrypt/command odpalony w tle na stałe. Problemem jest tutaj to że za każdą zmiana musiałbyś go w prawidłowy sposób wyłączać (np poprzez zmianę flagi w MySQL). A jakikolwiek błąd w kodzie o ile nie zostałby oprogramowany spowoduje natychmiastowe ubicie skryptu.
Z drugiej strony odpalanie skryptu co minutę CRONem też ma wady, musi się on wykonać w mniej niż 60 sekund. Niby śmieszne ale przy przeciążeniu dojdzie do błędu.

Przy grach działających na serwerze jest znacznie trudniej, tu nie wywali błędu graczowi a wszystkim graczom.