Autor | Zpráva | ||
---|---|---|---|
KryVosa Profil * |
#1 · Zasláno: 11. 2. 2015, 20:16:29
Mám takový problém. Mám jednoduchou HTML5
<canvas> kostičkovanou hru, přičemž každá kostička má vlastní vlastnosti:
gameGrid[X][Y].type = gameGrid[X][Y].building gameGrid[X][Y].solider gameGrid[X][Y].select function mainCAnim(X,Y){ mainCD.drawImage(img[gameGrid[X][Y].type],X*15,Y*15); mainCD.drawImage(img[gameGrid[X][Y].building],X*15,Y*15); mainCD.drawImage(img[gameGrid[X][Y].selected],X*15,Y*15); mainCD.drawImage(img[gameGrid[X][Y].solider],X*15,Y*15); if(X==63){X=0;Y++}else X++; if(X==63 && Y==32){X=0;Y=0}; setTimeout("mainCAnim("+X+","+Y+")",0);} mainCD.drawImage je vykreslení všech těchto vlastností na canvas.
Nevíte jak tuto funkci urychlit? Dát pryč setTimeout() jsem zkoušel, ale po chvíli mi to nekonečnou funkci ukončí.
|
||
1Pupik1989 Profil |
#2 · Zasláno: 11. 2. 2015, 21:14:47
Použij requestAnimationFrame nebo setTimeout-u nastav opakování na 1000/60. 1000 snímků za sekundu je zbytečné.
|
||
_es Profil |
#3 · Zasláno: 11. 2. 2015, 21:19:21
KryVosa:
Jednoduché urýchlenie môže byť: Časté potíže, zajímavosti a poučné debaty » Nepoužívejte eval , ani jeho obdoby. Náročnosť bude spočívať asi hlavne v spôsobe vykresľovania, menej by mohlo záležať na iných veciach.
|
||
Chamurappi Profil |
#4 · Zasláno: 11. 2. 2015, 21:21:37
Reaguji na 1Pupika1989:
„1000 snímků za sekundu je zbytečné.“ Má tam požadovanou prodlevu nulu milisekund, takže teoreticky by mohl mít nekonečno snímků za sekundu. Méně teoreticky ale minimální prodleva bývá 4 ms a prakticky bývá ještě větší v závislosti na tom, jak se systému daří. Reaguji na KryVosu: Proč nastavuješ pro každé políčko vlastní časovací smyčku? Proč nemáš jednu, která by řídila celé hrací pole najednou? „Nevíte jak tuto funkci urychlit?“ Pokud existuje konečné rozumné množství kombinací typů, budov a vojáků, můžeš si všechny stavy předgenerovat na začátku hry do jiného <canvas> u a pak vykreslovat z něj.
|
||
1Pupik1989 Profil |
#5 · Zasláno: 11. 2. 2015, 22:41:27
Chamurappi: Nekonečno neni reálné. setTimeoutm s časem 0 má vždy prodlevu větší než obyčejný kód.
Leč javascript to vyhodnotí jako nekonečnou smyčku. Za prodleva na smyčku může být 60s, ale syntaktický analyzér to vyhodnotí jako nekonečné volání ala "maximum call stack exceed". |
||
Radek9 Profil |
#6 · Zasláno: 11. 2. 2015, 23:24:10
1Pupik1989:
„Nekonečno neni reálné.“ On ale zmiňoval, že by mohl mít teoreticky nekonečno snímků. Což při zpoždění 0 ms dává smysl. „Leč javascript to vyhodnotí jako nekonečnou smyčku.“ Nevyhodnotí, protože i timeout se zpožděním 0 ms se spouští asynchronně. Call stack tedy nepřeteče, protože se to volá odjinud a vždy postupně. |
||
1Pupik1989 Profil |
#7 · Zasláno: 12. 2. 2015, 00:00:37
On ale zmiňoval, že by mohl mít
teoreticky nekonečno snímků. Což při zpoždění 0 ms dává smysl. Nedává, protože 0ms je prostě okamžitě. Javascript to zkrouhne a cyklus ořeže. Tudíž tam zustane jen vnitřek funkce, kterou vyhodnotí jako nekonečnou smyčku. Zobrazení kódu je jedna věc, ale zpracování je jiná. Stojím si za tím na 100%, zkuste mě vyvést z omylu. |
||
_es Profil |
[#7] 1Pupik1989:
Funkcia setTimeout funguje tak, že sa priradená funkcia zavolá až po príkazoch, ktoré sa majú vykonať za setTimeout .
|
||
Joker Profil |
1Pupik1989:
Nedává, protože 0ms je prostě okamžitě. Javascript to zkrouhne a cyklus ořeže. … Stojím si za tím na 100%, zkuste mě vyvést z omylu. Čili tvrzení zní, že setTimeout(foo, 0); JavaScript při zpracování převede na foo(); tzn. ty dvě konstrukce jsou ekvivalentní, ano?
V tom případě tvrdím, že to není pravda. Já tvrdím, že setTimeout(foo, 0) je pořád timeout a, přesně jak píše Chamurappi, volání se v praxi načasuje na další timeout, který ve skutečnosti nastane za delší čas, než 0ms. Takže zatímco function foo() { foo(); } provede hodně rychle spousty volání a následně spadne na vyčerpání zásobníku, function foo() { setTimeout(foo, 0); } projde a volání bude provádět řádově pomaleji.
Tak to vyzkoušíme: i = 0; function foo() { i++; var tm = new Date(); console.log(tm.getMilliseconds()); // aby to někdy skončilo if (tm.valueOf() < max) { setTimeout(foo, 0); } else console.log(i); } max = new Date().valueOf() + 1000; // limit bude 1 sekunda foo(); Na mém počítači bylo výsledkem zhruba 240-280 volání funkce foo, přitom rozestupy mezi voláními jsou nepravidelné, ta řada milisekund je: 366, 442, 442, 448, 451, 453, 455, … Už z toho počtu volání (~260 za sekundu je málo) a rozdílných rozestupů mezi nimi je zřejmé, že to tvrzení z [#7] není pravdivé. Nicméně ještě druhý test, pokud se označený řádek skriptu nahradí za foo(); .
Pak je výsledek zhruba podle očekávání, řada vypadá 805, 805, 805, … („805“ bylo prvních 179 hodnot) a po zhruba 27 milisekundách a necelých 3800 voláních to spadlo na vyčerpání zásobníku. |
||
_es Profil |
Jednoduchšie je to overiť, ak sa do stránky pridá:
<script> setTimeout("alert('pokus')", 0); document.write("pokus"); </script> <script> alert('pokus'); document.write("pokus"); </script> alert dokáže pozastaviť beh skriptu do kliknutia na OK. V prvom prípade sa však na stránke objaví text pokus už pred kliknutím. V druhom prípade však až po kliknutí.
|
||
KryVosa Profil * |
#11 · Zasláno: 12. 2. 2015, 14:51:17
Chamurappi:
Proč nastavuješ pro každé políčko vlastní časovací smyčku? Proč nemáš jednu, která by řídila celé hrací pole najednou? Myslíš že bych udělal něco jako je tohle? function mainCAnim(X,Y){ mainCD.drawImage(img[gameGrid[X][Y].type],X*15,Y*15); mainCD.drawImage(img[gameGrid[X][Y].building],X*15,Y*15); mainCD.drawImage(img[gameGrid[X][Y].select],X*15,Y*15);X++; mainCD.drawImage(img[gameGrid[X][Y].type],X*15,Y*15); mainCD.drawImage(img[gameGrid[X][Y].building],X*15,Y*15); mainCD.drawImage(img[gameGrid[X][Y].select],X*15,Y*15);X++; mainCD.drawImage(img[gameGrid[X][Y].type],X*15,Y*15); mainCD.drawImage(img[gameGrid[X][Y].building],X*15,Y*15); mainCD.drawImage(img[gameGrid[X][Y].select],X*15,Y*15);X++; mainCD.drawImage(img[gameGrid[X][Y].type],X*15,Y*15); mainCD.drawImage(img[gameGrid[X][Y].building],X*15,Y*15); mainCD.drawImage(img[gameGrid[X][Y].select],X*15,Y*15);X++; //A takhle dál až do počtu těchto trojřádků, který odpovídá počtu poliček na ose X.... if(Y==31)Y=0;else Y++;X=0; setTimeout("mainCAnim("+X+","+Y+")",0);} Nevím jestli by uživatel ocenil, kdyby si tohle celé musel stahovat. I když málokdo má dnes pomalejší net než počítač :) |
||
Joker Profil |
#12 · Zasláno: 12. 2. 2015, 14:54:24
KryVosa:
Umm, JavaScript, stejně jako skoro všechny programovací jazyky, umí i cykly ;-) |
||
KryVosa Profil * |
#13 · Zasláno: 12. 2. 2015, 15:05:25
Joker:
Jo, máš pravdu, sem blbej :) Už to fachá, odhadem na 8 Fps, což jako odezva bohatě stačí. Díky moc. |
||
1Pupik1989 Profil |
Joker: Máš pravdu. Teď si připadám jak začátečník. Přísahal bych na svůj život, že jses zkoumal překladač javascriptu v nějakém prohlížeči a ten to právě ořízl jen na funkci. Od té doby asi bazíruji na tom, že je to špatné. Pokud najdu v kterém prohlížeči se to stalo, tak ho sem dám. Je to pár let, takže tomu dávám tak 15% šanci. Nicméně prodleva 0 je špatné řešení, na tom se shodneme snad všichni.
|
||
_es Profil |
#15 · Zasláno: 13. 2. 2015, 23:48:39
1Pupik1989:
„Nicméně prodleva 0 je špatné řešení, na tom se shodneme snad všichni.“ Nemusí to byť vždy zlé riešenie, môže to byť príkaz v zmysle: „keď spravíš všetko zvyšné príkazy, tak sprav toto“, čo sa niekedy môže hodiť. |
||
1Pupik1989 Profil |
_es: Funkci dáš za poslední příkaz a zavolá se poslední. Pořád v tom žádný smysl nevidím. Docela by mě zajímala nějaká ukázka v praxi.
|
||
KryVosa Profil * |
#17 · Zasláno: 15. 2. 2015, 17:16:24
Zkoušel jsem ten
setTimeout("funkce()",0) nahradit requestAnimationFrame(funkce) a je to daleko pomalejší než moje řešení. Co dělám špatně?
|
||
_es Profil |
#18 · Zasláno: 17. 2. 2015, 18:21:06
1Pupik1989:
„Funkci dáš za poslední příkaz a zavolá se poslední. Pořád v tom žádný smysl nevidím.“ Nemá to však rovnaký efekt. Ak sa použije setTimeout , tak prehliadač môže „stihnúť“ pred spustením časovača aj iné veci - napríklad nejakú interakciu s návštevníkom - nie je to celkom „blokujúca“ nekonečná slučka.
KryVosa: „Co dělám špatně?“ Čo tak použiť nejaké normálnejšie cykly - napríklad for či while? |
||
1Pupik1989 Profil |
#19 · Zasláno: 18. 2. 2015, 07:52:38
KryVosa: Neděláš nic špatně. requestAnimationFrame má za úkol držet 60 snímků za sekundu. Používá se do herní smyčky jako náhrada za setTimeout.
|
||
Časová prodleva: 10 let
|
0