dejme tomu, že dělám souboj dvou protivníků v jedné RPG hře. Souboj
probíhá ve stylu jednotlivých kol, kde se pokaždé určí, jaké poškození
hráč způsobí. Poškození ovlivní několik různých faktorů a popis
každého kola se poté objeví ve zprávě o souboji.
Potřebuji od vás zkušenějších radu - mám do databáze ukládat každé
kolo zvlášť, nebo to průběžně ukládat do proměnné a tu pak hodit do
jednoho řádku?
Počet kol může být až do 100 (v pozdějších fází možná dokonce i
více). To znamená min. 100 insertů do DB, a to pouze průběh souboje (o
dalších asi deseti query dotazech nemluvím). Pracují s MySQL databází
(InnoDB), která, pokud si správně pamatuji, není v insertech úplně
nejrychlejší.
Jen bych ještě chtěl dodat, že v jednu chvíli může probíhat více
soubojů, takže se celý počet insertů znásobí n krát v závislosti na
počtu.
Edit: Mám pocit, že už jsem to někdy někde řešil. Pokud to bylo zde,
tak se omlouvám.
Cituji: "Poškození ovlivní několik různých faktorů a popis každého
kola se poté objeví ve zprávě o souboji."
Chci dát hráči vědět o detailním průběhu souboje, čili i o každém
kolu. Varianta "co kolo, to insert" je podle mě lepší, ale nejsem expert na
databáze a nevím, jak by to mohlo být zatěžující.
Stále jsi mi neodpověděl. Že aplikace zobrazí nějaké zprávy o souboji
neimplikuje, že je bude také ukládat. Mohla by jen uložit výsledek souboje,
ne průběh. Inserty nemusíš dělat postupně, ale najednou (jedním dotazem)
až zápas skončí, takže to pak pomalé nebude.
Souboj probíhá pomocí nekonečného cyklu, který se přeruší v
případě, že život jednoho ze soupeřů klesne na nulu.
Když bude chtít hráč na někoho zaútočit, klikne na tlačítko, PHP
vygeneruje souboj a stránka se hned přesměruje.
V podstatě ano, uvidí až výsledek. Po vygenerování souboje se stránka
přesměruje na stránku se zprávami, kde hráč uvidí, jak souboj probíhal.
Ale v době generování souboje hráč nic neuvidí.
Teď to zkouším a je pravda, že je to jednoduché. Jen mi to oproti PHP
přijde docela nepřehledné.
Pokud to chápu správně, pak nejvhodnější bude předat pouze ID
soupeřů a procedura si vše potřebné najde sama a provede souboj. Znamená
to, že pak bude stačit zavolat něco takového:
Přijde mi lepší napsat si tu logiku hezky objektově v PHPčku, SQL na
tohle není dělané a vždy to bude nepřehledné. Na konci jen zavoláš jeden
dotaz s pár inserty jak jsi napsat nahoře.
OOP není všelék. Business logika v databázi být může. Relační
databáze nejsou jen skladištěm dat. Použitím OOP by se to dost zpomalilo.
Kompilace několika set SQL dotazů je mnohem náročnější než kompilace
jednoho.
Také díky. Ještě bych se rád zeptal, zda nevadí vytváření hodně
proměnných a provádění hodně výpočtů. Jde o to, že to, jaké hráč
způsobí poškození, ovlivní cca 7 faktorů s tím, že se všechny faktory
ještě přepočítávají na procentuální šanci (např. kritický útok,
blokování, úhyb apod.).
Zatím se vytváří 27 proměnných pro jednoho hráče, čili 54
proměnných jen pro oba soupeře. Z toho 8 proměnných pracuje s funkcí
RAND().
A říkám snad, že ano? Je opravdu hloupost dělat tohle v databázi,
jedná se o simulaci, k tomu jsou určené objekty. Stored
procedures jsou mocným nástrojem, ale určitě ne na tohle, kdy se ukládá
jen výstup nějakého procesu, nedochází
tedy k zpomalení databáze.
Tím, že uložím hotový výsledek? To ani ne. Má tak jednoduchou logiku
že to více nejde a cituji tebe: " Podle mne tu hru děláš příliš
komplexní.". Nechci vidět, jak bude v tom GOTO paskvilu vypadat až to bude
opravdu komplexní.
co pozměnit nějak návrh průběhu souboje co třeba nějaká rekurzivní
funkce? která by si předávala pole s datama a pak uložit výsledek jen na
konci kdo vyhrál atd atd
Abys ten výsledek spočítal, musíš nejprve z databáze ty parametry
vytáhnout a to je hodně velká zátěž, pokud jich má tolik. Taháš pak
data mezi PHP a DB jak kočka koťata.
Na co ty nepoužíváš SQL. Přijde mi, že 98% tvých rad je něco jako:
"Proč používat tenhle jazyk, když to jde přes databázy...". Popř. když
hájíš nějaký jazyk, oháníš se maticemi a nebo do každého sql kódu
házíš triggery. V SQL
se nevyznám na takové úrovni, ale rohodně není všemocná. Je to
dotazovací jazyk, tak proč tam dávat výpočetní funkce? Chci jen
vysvětlení a argumentaci. Netvrdím, že nemáš pravdu. Každopádně pokud opravdu chce
zaznamenávat každé kolo, bude to rychlejší.
Ty výpočty vůbec nejsou složité, dají se napsat do jednoho selectu. Ani
nejsou výpočetně náročné a navíc tyto operace SQL zvládá lépe než
PHP.
Základním argumentem je co nejjednoduší a co nejméně početná
komunikace mezi vrstvami aplikace, ale i třeba mezi objekty. Tedy princip
zapouzdření a izolovanosti.
Nenašel jsem nic, co by cyklus přerušilo, žádný ekvivalent k break.
Proto mi přišlo nejvhodnější použít slovo LOOP, se kterým to jde
snadno.
Edit: Pardon, kecám nesmysly. Potřebuji ukončit cyklus podle jedné nebo
druhé podmínky, ale nedošlo mi, že to jde.
Možná by se sem měla přidat i možnost smazání vlastního příspěvku,
ať pak nejsem za blbce.
Jestli děláš hru jako shakes and fidget, gladiatus atp. tak nač
potřebuješ ukládat průběh jednotlivých kol do databáze ?
Podle mně by bylo lepší ... hráč klikne na zaútočit na hráče BLABLA,
přejde se na jinou stránku abc.cz/utok/blabla kde se provede výpočet a
následně se provede animace kolo po kole souboje, nebo můžeš přeskočit na
konečný výsledek.
Databázi do toho zatáhneš jen tak, že odečteš body či peníze apod. co
hráč získá/ztratí...
Vážně nevidím důvod proč bys měl zaznamanávat průbehy jednotlivých
kol ...
Abys měl přehled o souboji i poté, co ho provedeš. A kdo ví, co se s
těmi daty dá ještě dělat, přinejmenším nějaké statistiky, které by
hráči určitě uvítali (a to mluvím z vlastní herní zkušenosti).
Kdysi jsem to takhle měl, že se uložilo prakticky jen to, kdo vyhrál a
kolik jsi získal, ale průběžné ukládání je, alespoň pro mě, mnohem
vhodnější.
trochu jsem nepochopil způsob, který jsi zvolil.
Neznám princip tvé hry, ale jestli jsem pochopil:
co kolo to cca jeden záznam do DB, jeden hráč, sto kol. Sto hráčů deset
tisíc záznamů...
není to tak trochu zbytečné hromadění informací?
Spíš bych to viděl na podrobnější popis hráče, od záznamu zdraví,
síly a pod.
Záleží na tom, co od toho chceš.
Bral bych to ve více rovinách. Zaznamenávat vývoj postavy je určitě
potřebné, ale tam bych to zredukoval na záznam kdy dosáhl dalšího levelu,
kdy koho porazil. Pak nějaký inventář který se bude také asi dost
měnit.
A pak ten boj. A u toho bych si asi vystačil jen s tím, že bych updatoval
data.
Podle funkce v DB soudím, že o programování něco víš a nerad bych tě
svedl z tvé cesty. Je to na tobě
A když budu chtít vidět, jak probíhala jednotlivá kola, tak to jinak
než za pomocí insertů udělat nemohu, ne? Kdybych chtěl například vidět,
do kterého kola jsme si se soupeřem byli rovni, a od kterého šly mé šance
na výhru výrazně dolu. Výsledky soubojů nebudou tak jasně předem
určené, proto bych chtěl dopřát detailní výpis.
Rád si vyslechnu každý názor, nápad a kritiku. Sice už nějakou dobu
programuji, ale vím, že v tom pořád nejsem dobrý - a právě proto jsem
založil tohle téma.
Když chceš udělat detailní výpis tak si ho udělej (nejdřív
vypočítáš souboj a poté si to z informací vytáhni), ale nic neukládej do
databáze, jsou to zbytečnosti...
Hráč ho chce vidět jen jednou, pak ho zajímá jen
vítězství/prohra...
Nevím, jestli tou statistikou máš na mysli to, co já, ale pokud ne, tak
bych JSON formátem tedy mohl uložit klidně i detaily souboje (kolo po kolu).
V PHP bych to pak dekódoval pomocí json_decode() a dostal bych pole, které
bych pak jen prošel a vypsal detaily.
Jako vážně nechápu proč pořád chceš ukládat celý zápas - 100 kol -
do databáze, tam pak budeš mít strašně hodně záznamů a úplně
zbytečných
Prostě budeš mít :
stránka 1 : vybereš si hráče na kterého zaútočíš -> klik ->
odkaz na stranku 2
stránka 2 : výpočet souboje, vytáhnutí dat do statistiky(max úder atp.)
+ animaci souboje, zkontrolování ocenění (max úder, přidat 1 k
vítězství/prohře), změna peněz/předmětů
do databáze si tedy uložíš jen maximálně záznam že jsi měl zápas a
prohra/vítězství a případně si přeuložíš ocenění...
jako mít tam při 1000 soubojů denně 100,000 zápisů je zbytečnost
...
Při JSON formátu by tam bylo tolik záznamů, kolik by bylo soubojů.
Možná se budeš divit, ale hodně hráčů zajímají detaily souboje i potom,
co se provede.
V databázích se dnes řeší třeba i takové záležitosti, jako jsou
např. kolize a průniky polygonů, statistická analýza dat apod. Jen webaři
dělají z SQL databází obyčejný KVS. Zabíjejí tak jejich schopnosti a
výkon.
Porušení normální formy to je, když bude chtít přidat nějaký atribut
k souboji, tak má problém. Teoreticky je všechno v pořádku, prakticky se
někdy rozhodně něco změnit a bude mít velký problém. Tento způsob
ukládání dat silně nedoporučuji.
To je pravda, ale ona atomická není Pokud je ten postup souboje důležitý, měl by se normálně
ukládat jako řádky, vybrat pár řádků podle klíče není nic hrozného.
Pokud se do db něco ukládá serializované, asi na těch datech moc
nezáleží, půjde je jen špatně editovat a je otázka zda jsou vůbec
potřeba. IMHO když se tohle dělá, tak je někde chyba v návrhu.
Zas takový nesmysl to není, jestli to dobře chápu, tak se to k těm 100
kolům téměř nedostane, je možný že protivník umře třeba ve třetím,
občas, když to bude vyrovnané tak třeba v patnáctém (takhle to je běžně
u her, ale nevím k čemu těch 100 kol, to je zbytečně moc). Pokud by to bylo
kolem těch deseti kol, pak si to velká část hráčů bude chtít přečíst.
Už třeba jen proto, že se z toho dají zjistit principy hry, důležitost
různých atributů, nejvýhodnější jednotky, zbraně a tak dále
Hmm, jak tak vidím, tak asi celé detaily ukládat nebudu. Maximálně dát
možnost hráči, aby si zprávu uložil - to by se převedlo do JSON a uložilo
do DB, v jiném případě by se to jen jednou vypsalo a pak by ve zprávě byly
jen základní informace (vítěz, odměna, celkové způsobené poškození
atp.).
Takhle by problém nebyl ani s tím, kdybych třeba přidal nový atribut.
Uložená zpráva o souboji by byla jen kopií toho, co se stalo před updatem
hry.
Výsledek by byl takový, že by se nehromadily zbytečně nepoužitelné
informace, ale zároveň by byla možnost se na ten výsledek podívat i
jindy.
Mně se tohle zdá jako docela rozumné řešení, co myslíte?
Pokud to bude realtime boj, tak se mu to ukáže z paměti. Tam to má
nějaký smysl, člověk na to čeká atd. Pokud to není realtime, tak mi
průběh nepřijde moc důležitý.
Když budu chtít vědět, kdo vyhrál, podívám se na zprávu o souboji,
která přijde vždy. Když si budu chtít uložit kopii detailů, bude mě
zajímat pouze průběh souboje. V nejhorším případě se to dá poznat i z
toho výpisu, kdo vyhrál (= ten, kdo dal poslední ránu).
Je vidět, že jsi tu jeho hru zatím nehrál. Už jsem ji zkoušel a vím o
co v ní jde. Martin Konečný (pavelco1998) potřebuje jen vygenerovat zprávu ze souboje tak,
aby si ji oba soupeři mohli kdykoli přečíst. Po přečtení ji zpravidla
vymažou, ale někteří si ji budou chtít ponechat.
Zabiják na tebe vystřelil z kuše, ale minul. Udeřil jsi ho mečem,
ale ochránila ho zlatá přilba. Zabiják na tebe zaútočil kopím, zasáhl
tě a ubral ti 6 životů. Vystřelil jsi na něj z luku, ...
Pokud ten tvůj text uložím do JSONu, bude to poměrně složité. Když
potom rozšíří způsob boje, bude potřebovat změnit ten formát. Skončí
to tak, že bude udržovat zpětnou kompatibilitu se starými logy nebo je bude
parsovat a updatovat, obojí je nešikovné. Pokud si uloží řádky textového
výstupu, tak proti tomu řešení nic nemám a je správné.
Pokud ty záznamy bude chtít poslat klientovi přes AJAX, tak se naopak JSON
docela hodí. A pokud po najetí myší na "zlatou přilbu" bude chtít v
bublině zobrazit její schopnosti, je nějaká struktura nutná. Ale až u
klienta.
Parsování a updatování JSONu je velmi jednoduché v PHP i v JS.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.