Gra przeglądarkowa php - uruchamianie skryptu o określonych godzinach

Witam,

jestem w trakcie nauki języka php i w najbliższej przyszłości w ramach nauki planuję napisać prostą grę przeglądarkową. Chcę tutaj dość luźno i teoretycznie podejść do tej kwestii. Jeśli chodzi o przyrost surowców to mógłbym zasotosować crona, ale lepszym pomysłem chyba jest obliczanie ilości surowców na podstawie różnicy czasu pomiędzy poprzednim a aktualnym logowaniem użytkownika. To się sprawdza jeśli przyrost jest stały. Ale co jeśli użytkownik zleci ulepszenie kopalni, fabryki, stoczni, koszar, etc? Albo zleci atak, który odbędzie się o określonej godzinie? Wychodzi na to, że tak czy inaczej cron musi być. I to powinno działać w godzinach, które nie są z góry określone, tzn jeśli gracz atakuje innego o godz  12:34, to skrypt odpowiedzialny za ataki powinien się wykonać o tej właśnie godzinie, niezależnie czy takie zadanie zostało zaplanowane. Czy mój tok myślnienia jest prawidłowy? Czy znacie jakieś poradniki, wskazówki, gdzie zawarte są najlepsze rozwiązania dla przedstawionego przeze mnie problemu? Chciałbym m.in dowiedzieć się jak wygląda kwestia cyklicznego wywoływania skryptu bądź wykonywania skryptu o godzinie wynikającej z biażących potrzeb użytkowników.

Możesz stworzyć kolejkę ataków w bazie danych, a po zalogowaniu jakiegokolwiek użytkownika wszystkie ataki do obecnej daty zostaną wykonane. A cron może się uruchamiać co np dzień i wykonywać aktualizację kolejki by odpowiedź serwera nie trwała zbyt długo w razie gdy długo żaden użytkownik się nie zaloguje.

A co do surowców, Licz na zasadzie obecny_surowiec+=czas_ostatniego_wywołania-teraz*współczynnik_produkcji_kopalni, jeśli większa niż pojemność magazynów to ilość surowca to pojemność magazynów

. A podczas ataku możesz wywołać w/w skrypt co pozwoli ci obliczyć aktualną ilość surowców.

Tak można, ale nie sprawdzi się to w przypadku gier, chyba że liczba graczy będzie do około 30. Przy dużej liczbie graczy w momencie odświeżenia po np. nocy będzie tyle zadań do wykonania że uzyskasz w najlepszym przypadku timeout, a w najgorszym unieruchomisz grę na kilka minut.

Ogólnie nie robiłbym tego w php. Z opisu wynika że chcesz zrobić coś a’la plemiona, więc średnio to widzę w php. Nawet przy użyciu ajaxa i zbudowania serwera restowego w php.

Oczywiście da się to zrobić w php, ale to więcej prac a efekt będzie słaby, a web usability naprawdę niska.

Tak mi przyszło do głowy, źe może lepiej byłoby napisać aplikację w innym języku programowania, która byłaby odpowiedzialna za działanie gry, tzn przyrost surowców z uzględnieniem różnych czynników, symulacje ataków, kolejkę tworzenia jednostek, etc., natomiast php byłoby odpowiedzialne jedynie za pobieranie informacji z tej aplikacji, wyświetlanie oraz wysyłanie zleceń tej aplikacji, przy czym aplikacja działałaby bez przerwy. Czy takie rozwiązania są stosowane?

Dokładnie tak. Można iść o krok dalej i z taką aplikację rozszerzyć o funkcję serwera rest i pozbyć się całkiem php. W tedy wszystkie operacje przeprowadzasz przy użyciu JS w przeglądarce wysyłając i odpierając dane do serwera restowego.

Po co budować monolit, którego odpowiedzialnością będzie robienie dosłownie wszystkiego? To fajny przypadek na delikatną wprawkę do mikroserwisów. Czysto serwerowa aplikacja do ciężkich, batchowych obliczeń i reszta napisana w czymkolwiek, nawet PHP. Na styku baza danych. W przyszłości, po zaistnieniu potrzeby stworzenia kolejnego serwisu, można faktyczna dołączyć REST-owy model komunikacji.

Aktualizacje takich danych jak np. surowce wykonywałbym przy zaistnieniu zdarzenia, które ich dotyczy.

Załóżmy, że mamy osadę, w której są hodowane jednorożce. Zdarzenia jakie dotyczą ilości jednorożców to:

  • Sprawdzenie ich ilości przez gracza
  • Przepatatajanie jednorożców do innej osady
  • Porwanie jednorożców, przez wrogie krasnoludki, które napadły na osadę
  • Zmiana tempa hodowli jednorożców wynikła z powiększenia ich zagrody

Jeżeli któreś z nich nastąpi, należy przed ich obsługą zaktualizować ilość jednorożców. Np. doszło do bitwy i wygrał agresor, który jako łup zgarnia zwierzaki. Najpierw aktualizowana jest ilość jednorożców, następnie agresor odbiera swoją część. 

Aktualizacja wygląda mniej więcej tak:

if(tempoPrzyrostuJ * (obecnyCzas - czasOstatniejAktualizacji) >= 1)
{
    ilośćJ += tempoPrzyrostuJ * (obecnyCzas - czasOstatniejAktualizacji);
    czasOstatniejAktualizacji = obecnyCzas;
}

Ponieważ ilość jednorożców to raczej liczba całkowita, należałoby poprawić kod tak, aby dodawał tylko ilość całkowicie wyhodowanych jednorożców, a jako czas ostatniej aktualizacji ustawiał czas, kiedy ostatni jednorożec został w pełni wyhodowany.

Jeżeli zamierzamy prowadzić statystyki, to trzeba dodatkowo podliczać to te wartości dla wszystkich osad co określony czas. Lub podliczać dla tych, które nie były aktualizowane od określonego czasu.

Czytałem że gry takie jak ogame, travian, plemiona oparte są właśnie na tym, że wszystkie przeliczenia dot. surowców, produkcji jednostek, ruchu flot, odbywają się poprzez odwiedzanie stron przez użytkowników - czyli jeśli user się loguje, automatycznie wykonywane są wszystkie operacje. Jeśli chociaż jeden loguje się raz na godzinę, automatycznie odchodzi potrzeba stosowania crona. Czyli wychodzi na to że w niektórych przypadkach wystarczy php + oczywiście frontend. Problem zachodzi w przypadku gdy trzeba nadrobić wszystkie operacji jeśli użytkownicy nie logują się przez dłuższy czas - wtedy cron się przydaje. Może jednak to nie jest wcale takie głupie rozwiązanie? Sam sprawdziłem na własnym komputerze projekt xnova, i wychodzi na to że działa on zgodnie z powyższym schematem.

@czeper Ten system sprawdza się, ale znalazłem w nim kilka problemów:

  • Jeżeli któryś z użytkowników nie loguje się dłuższy czas, a wiele się u niego dzieje, to narasta duża kolejka zadań do wykonania przy logowaniu
  • Tworząc taką grę można o zapomnieć o jakichś ważnych zależnościach, wynikających z zaistniałych zdarzeń. Sam widziałem taką niedoróbkę w pewnej grze, a grało w nią ponad 100 k graczy.
  • Teraz wszystko staje się mobilne. Aplikacje tworzone jako klienty gier przeglądarkowych mają jedną ważną cechę - powiadomienia o zdarzeniach (zresztą na stronach też są). Gracz nie otworzy aplikacji póki nie otrzyma powiadomienia o zdarzeniu, a to zdarzenie zostanie obsłużone dopiero, gdy gracz wyśle jakieś zapytanie. 

Dlatego najlepiej by było gdyby wszystko było robione w czasie rzeczywistym. Znacie może jakieś projekty realizowane w ten sposób? A tak poza tym zastanawiam się jaki język programowania byłby do tego najlepszy?

Dowolny. Cron + prosty algorytm + aktualizacja na bazie, z tym poradzi sobie każdy język od C do JavaScriptu ze wszystkimi stanami pośrednimi (Go, Java, Python, multum innych). Lub inaczej - taki, który znasz lub którego chciałbyś się nauczyć.

z tego co wiem co Plemiona są (a na pewno początkowo były) napisane w PHP. Ale wybór języka może być inny.

ale patrzył bym też na że wiele tanich hostingów nie pozwala na skrypty gier, więc i tak będzie trzeba zaiwestować w lepszą maszynę, która sobie niedość że spokojnie poradzi i taką grą to jeszcze będzie dawała znacznie więcej języków programowania do dyspozycji.

https://aws.amazon.com/free/

Jeżeli język do wyboru, to w tym wypadku wybrałbym coś kompilowanego. Przy dużym ruchu, oszczędza się bardzo dużo mocy. Warto też porzucić CGI, bo przy każdym zapytaniu trzeba uruchomić nowy proces i nowe połączenie z bazą. Obecnie rozwijam projekt oparty na zestawie C++ i FastCGI. Działa całkiem przyzwoicie. Stronę zamierzam oprzeć o AJAX, więc obciążenie serwera będzie naprawdę małe.