Jak zrobić walke graczy?


(Konradnie1) #1

Witam.

Mam np taki kod:

<?php

$player1 = '100';


        $player2 = '100';


        echo "Gracz 1 zaczyna ze $player1 życia \n";


        echo "Gracz 2 zaczyna ze $player2 życia \n 
";


        for($i = 0; $i <= 10; $i++) {


        $player1 = $player1-rand(1, 20);


        $player2 = $player2-rand(1, 20);


        if ($player1 <= 0 || $player2 <= 0){


            if ($player1 < $player2){


                echo "wygrał gracz 2, gracz 1 padł";


            } else {


                echo "wygrał gracz 1, gracz 2 padł";


            }


        break;


        }


        echo "Runda $i :";


        echo "Graczowi 1 zostało $player1 życia \n";


        echo "Graczowi 2 zostało $player2 życia 
";


        }

?>

Jak zrobić żeby za każdym odswiezaniem generowało to samo?? Chodzi mi o to żeby nie dało się tego zmienić.

każdą runde mam zapisać w bazie?? czy jak to działa??


(P) #2

Do zapisania masz dwie liczby, więc chyba lepiej zapisać je po prostu w pliku tekstowym. A sam skrypt wygląda nieco dziwnie, możesz podać jego zastosowanie? Być może możesz tę całość umieścić w jednej więcej pętli wykonującej się dopóki któryś z graczy nie umrze, więc nie trzeba będzie nigdzie zapisywać ich punktów życia ani odświeżać strony/uruchamiać ponownie skryptu.

http://php.net/manual/pl/function.fwrite.php

http://php.net/manual/pl/function.fread.php


(Konradnie1) #3

Dlaczego dziwnie?? Co jest nie tak?? To jest tylko przyklad chodzi mi o to ze jak odswieze strone to on od nowa sie wykonuje i mam co innego a ja chce żeby mozna bylo zobaczyc wynik kiedy sie chce.

Rund jest 10. Mam zapisac kazda w bazie?? nie obciaza to serwera bardzo?? To jest przyklad w moim kodzie jest jeszcze $bron, $dmg, $przeciwnik,$(statystyk postaci). naraze kazda runde zapisuje w bazie mysql ale moze jest jakies lepsze rozwiazani?? kazda runda ma taki sam id_walki i potem wyswietlam po tym id. Jesli jest jakis lepszy, szybszy sposob to napiszcie jak zrobic.


(kostek135) #4

Co jest nie tak hmm… nie jestem specem od gier, ale coś tam wiem:

-> gry tworzy się w pewnym kanonie, pętla główna, która jest uruchomiona do czasu gdy gra działa, etc.

-> samo php jest beznadziejną technologią do stworzenia gry, która jak mniemam przypominać ma rozgrywką final fantasy

Przede wszystkim przez to, że do przeglądarki nie możesz czegoś wysłać od tak, przeglądarka musi o to zażądać oraz nie możesz się komunikować graczy na poziomie serwera tylko przez bazę danych. To będzie wymagać pollingu - mało to ciekawe.

Jeśli upierasz się na technologie webową, to może połączenie serwletów + js ? Wyjaśnię jakby to miało wyglądać dla dwóch graczy = nie jest to podejście skalowalne = jest bardzo słabe = ciągle lepsze od twojego.

W serwlecie mógłbyś komunikować dwa wywołania dzięki zmiennym statycznym - to pierwszy plus (oraz wada jeśli chodzi o skalowalność - można to zrobić lepiej ale zostawiam to już tobie = podpowiedź słowo-klucz kolejki komunikatów + identyfikatory graczy)

Co to daje?

  1. Tworzysz dwa obiekty statyczne reprezentujące graczy.

  2. Gracz drugi wysyła asynchronicznie komunikat “OCZEKUJE NA RUCH”. Wątek, który go obsługuje zasypia, bądź blokuje się na jakimś zamku.

  3. Gracz pierwszy może powiedzmy wysłać komunikat ATAK, też asynchronicznie. Drugi wątek, który będzie przetwarzał gracza pierwszego sprawdzi sobie w obiekcie, jaką masz broń, siłe, etc. Jaki ten drugi gracz ma pancerz, życie, etc. wyliczy dmg, wykona modyfikację na obiekcie reprezentującym gracza drugiego wybudzi wątek gracza drugiego i pójdzie sam spać.

  4. Wątek gracza drugiego dokończy wywołanie zwracając zawartość obiektu gracza drugiego i odpowiednio przeglądarka to przeładuje.

  5. Teraz gracz drugi ma inicjatywę a gracz pierwszy czeka. Wrócić do punktu 2 tylko teraz czytając gracz 1 => 2 a 2 => 1.

*. Każde zadanie asynchroniczne po stronie widoku powinno tworzyć jakąś animację loadingu. Coby użytkownik wiedział, że czeka na ruch oponenta + może jakiś timeout = mało zabawne jak ktoś to uruchomi i pójdzie, a my gapimy się 10 minut w kontrolkę oczekiwania

Generalnie:

  • Trzeba zaprojektować jakiś protokół komunikatów

  • Przesyłać tylko komunikaty i modyfikować obiekty a graczom odsyłać kopie tych informacji celem odrysowania widoku. Dzięki temu nawet jak ktoś w js podmieni sobie życie na 102130213921, to i tak po wysłaniu ATAK w niego odejmiesz to co jest w obiekcie i mu powiesz ze ma 50. Innymi słowy stworzysz coś takiego, że przeglądarka to tylko widok, buttony + asynchroniczne wywołania stworzą kontroler, a logika będzie bezpieczna po stronie serwera. Dlaczego komunikaty? To będzie taki zbiór operacji elementarnych poza które nie można wyjść. Np. jeśli przesyłał byś coś w stylu ?DMG=50, to każdy może sobie podmienić to na 200, 500, ile chce. Przy komunikacie nie ma problemu: “ATAK”, znaczy zastosuj formułę znaną po stronie serwera, używając zmiennych po stronie serwera = większe bezpieczeństwo.

Oczywiście jak wspomniałem mało to skalowalne, ze wzlędu na static + wątek == gracz == dużo wątków. Ale można zaprojektować coś takiego jak jest w nio, podział kanałów z selektorem.

Ogólna idea: Każdy gracz ma swój id, wątek serwleta rejestruje, że jest coś do przetworzenia w jakiejś liście pod kluczem danego gracza, natomiast inny wątek przelatuje co jakiś czas listę sprawdzając czy dla któregoś z graczy można coś wykonać. Można też dodać flagę oznaczjącą cięższe obliczeniowo zadanie, i wtedy wątek oblatujący kolejkę komunikatów wywoływałby widząc falgę ciężkiego zadania dodatkowy wątek, co by nie zblokować się na długo. A przy okazji, nie byłoby sytuacji, że tworzymy wątek dla zadania, które wymaga dwóch dodawań i dzielenia. Bo koszt utworzenia wątku by to znacząco przekraczał.


(Drobok) #5

Ale do tego musisz kupić vps’a :stuck_out_tongue:

Zawsze można zrobić coś podobnego w php + cron. A jak już upierać się przy vps to lepiej napisać w .net :slight_smile:


(Konradnie1) #6

kostek135 z tego co zrozumiałem to opisałeś mi walke w której 1 gracz wykonuje czynność a potem 2 tak??

Ja chce zrobić tak ze gracz klika przycisk atakuj innego gracza i wykonuje się pętla obrazenia i hp są w bazie user każdego gracza teraz tylko jak zrobić żeby nie wykonywało za każdym razem gdy odswieze strone w tej walce gracze nic nie robią.

Mogą wyłączyć komputer a za 10 min wrócić i będzie po walce i wyświetli wynik.

Potrzebuje walke (losówke) bez integracji graczy czyli coś takiego jak jest wyżej tylko żeby nie wykonywało się za każdym razem gdy odświeżę.


(Drobok) #7

Po pierwsze weź pod uwagę że taki jest urok php (odświeżenie = ponowne wysłanie formularza). Musisz zablokować możliwość powtórnego ataku na jakiś czas.

Po drugie musisz określić czy obrażenia mają się wyświetlać dynamiczne (np z użyciem jquery), jeśli tak robisz tak jak określił kostek135, pętla wywołania cronem (przeglądarka odpytuje o aktualny stan). Ew przy odpytywaniu przez usera określ aktualne hp przez (czas_rozpoczęcia-aktualny czas)/czas_jednego_ciosu.

Jeśli nie to pętla jest nie potrzebna. Zrób ((hp_przeciwnika%nasze_dmg)>(nasze_hp%dmg_przeciwnika))?“Wygraleś”:“przegrałeś”; W skrócie kto wytrzyma więcej ciosów wygrywa, możesz to np pomnożyć jeszcze o szybkość ataku etc (wena twórcy)


(Konradnie1) #8

Ustawiłem limit atakow na 1 gracza jak się go raz zaatakowało to 2 raz nie da się.

Ale dzięki za pomoc może kiedyś zrobie dynamiczną :smiley:


(kostek135) #9

Rozumiem. Tak trzeba to rozwiązać zrobić tabele pośrednią między tabelą graczy, a tabelą graczy (tą samą tabelą). I w niej wpisywać kto z kim walczył + ewentualnie czas. Czas wtedy jak nie chcesz żeby jeden gracz za często atakował drugiego w tym spamował, ale mógł kilka razy zaatakować (generalnie ta sama technika służy do blokowania zdublowanych komentarzy - user się nie cierpliwi klika w przycisk i bum 4 te same posty). Ewentualnie bez czasu jak można zaatakować gracza tylko raz w ciągu istnienia. Lub z polem klucza obcego jeśli nie może zaatakować 2x tego samego gracza. Innymi słowy w kolumn klucza obcego gracza A wstawiasz B, teraz spamowanie nic mu nie da, musi zaatakować dajmy na to gracza C i dopiero może zaatakować B.

Nie wiem czy też chcesz mieć archiwum runda po rundzie, ale jeśli tak musisz to zapisać każdą z nich. Albo dane jakie są w i-tej rundzie, albo jeśli tabela postaci jest rozbudowana skorzystać z zapisu różnicowego (przechowywać to co się zmieniło) dzięki temu z rundy o jeden wcześniej wstawisz to co było i się nie zmieniło do raportu. Przydatne jak mało rzeczy się zmienia i tabela jest rozbudowana.


(Konradnie1) #10

Walka jest w pętli. Jeśli dam do pętli zapytanie bazy danych to zapisze mi każdą runde do bazy danych czy tak można czy bardzo obciąży serwer albo coś innego??

Rozwiązałem wyżej podany błąd prze zapisanie w bazie pprzy user czas ataku ostatniego i jeśli ten czas nie jest mniejszy o 2 godz to nie da się go zaatakować 2 raz


(kostek135) #11

Ad1. Innej opcji nie widzę, serwera to nie obciąży nie wiem jak z bazą danych, ale wiadomo do jakieś poziomu (liczby użytkowników) powinno być ok. Moim zdaniem ważniejsze od wstawiania będzie wyciąganie tego, co by się nie urobić przeglądając wszystkie rundy i wyciągając po id, że należą do gracza X. A potem jeszcze dokonywać jakiegoś strasznego GROUP BY które rundy są z której walki. Co ja bym zrobił, to zakładając, że jest tabela użytkowników, z kluczem głównym, to dwie tabele Rundy i Walki.

Wiersz tabeli ‘Walki’ posiadałby sztuczny klucz główny, klucz obcy do tabeli użytkowników (albo dwa - jeśli broniący się też powinien mieć dostęp) wskazujący czyja to walka (żeby wiadomo było kto może przeglądać) oraz 10 kluczy obcych do tabeli ‘Rundy’. Przy dwóch kluczach będzie można zrobić filtrowanie, np. pokaż raport z moich ataków albo obron.

W tabeli ‘Rundy’ identyfikatory oczywiście i dane w każdej z nich.

Dzięki temu można:

  • szybko zmienić na 12 czy 15 rund jeśli zajdzie kiedyś potrzeba,

  • wybierasz swoje walki (10 razy mniejsza ilość wierszy niż przeglądanie runda po rundzie),

  • przynależność rundy do walki (częścią której walki, była rozważana runda)

  • nie musisz ‘psuć’ innych tabel jak dojdziesz do wniosku, że w rundzie chcesz nie tylko zapisać kto ile zadał obrażeń, ale inne informacje (zmienisz tylko schemat tabeli ‘Rundy’)

  • kaskadowe usuwanie, nie pozostawisz przez przypadek jakiejś rundy jak usuniesz walkę z tabeli.

Ad2. Zawsze jakieś rozwiązanie.