| Autor | Zpráva | ||
|---|---|---|---|
| KryVosa Profil |
#1 · Zasláno: 5. 1. 2016, 19:28:48
V jedné nedodělané hře vytvářím možnost přidávat si vlastní 'mutátory' hry, kterými můžete různé vlastnosti hry upravovat za běhu a/nebo přidávat nové. Implementace v samotné hře vypadá nějak takto:
var functions=
{
// ...
move:function(p, x, y)
{
var mut=game.mutator.move.test({functions:functions/*další a další upravovatelné atributy...*/});
mut=mut||false;
if(mut.x||mut)player[p].x += x;
if(mut.y||mut)player[p].y += y;
},
// ...
}move() se provede mutátor, kterému je funkce move() předána a on ji může zavolat, čímž pádem se provede mutátor.... Zároveň však game.mutator.test() může testovat více mutátorů, tudíž nejde přidat 'test zavolání z mutátorů', kterým by se volání stornovalo.¨
Máte-li nějaký nápad, pomocný článek, nebo kritiku kódu, napište, předem děkuji :) |
||
| Chamurappi Profil |
#2 · Zasláno: 6. 1. 2016, 13:04:00
Reaguji na KryVosu:
Nejsem si jistý, jestli jsem správně pochopil, v čem spočívá problém, hodně věcí jsem si musel domyslet. „se provede mutátor, kterému je funkce move() předána a on ji může zavolat“
Můžeš mu tu funkci nepředat. Respektive předat mu místo functions jiný objekt naplněný vším, co je ve functions, s přepsanou metodou move.
Nebo můžeš do volání předávat i nějaký (s každým voláním rostoucí) výčet volaných funkcí a ověřovat, jestli v něm právě volaná funkce už jednou není. Nebo by asi šlo mít v move pojmenovanou funkci (tzn. move: function název(p, x, y)) a pak zevnitř přes název.caller zjistit, čím je volána (a čím je volána to, co ji volá, atd.) – a tím zjistit, jestli nejsi v rekurzi. Ale nevím, jestli by to bylo proveditelné, nikdy jsem caller nepotřeboval.
|
||
| KryVosa Profil |
#3 · Zasláno: 7. 1. 2016, 09:35:08
Problém jsi jako vždy pochopil na jedničku!
Caller nikdy fungovat nebude, nemá 'historii', jen 'poslední' funkci, kterou byl zavolaný. Takže i při konečné rekurzi funkce/funkcí se sám zacyklí. Šlo by to obejít přes jakýsi vlastní 'max CallStack' u calleru, jakékoliv zacyklení by bylo úplně nemožné.
Možná by šlo 'ukládat' si někam funkce, které move() zavolaly, a právě jak říkáš kontrolovat, jestli mezi nimi už není funkce, která move() už zavolala. Popřípadě určit jakýsi 'maximální počet vnoření'.
Děkuji za nakopnutí. |
||
|
Časová prodleva: 5 dní
|
|||
| KryVosa Profil |
#4 · Zasláno: 12. 1. 2016, 11:22:37
Pro ostatní, co by měli podobný problém, sem ještě posílám hotové řešení:
var callStack=[];
function callStackTest()
{
caller=callStackTest.caller.caller;
callStack.push(caller);
var count=0;
var lastIndex=-1;
while((lastIndex=callStack.indexOf(caller,lastIndex+1))>=0)
count++;
if(count>=callStackMax)
{
console.error("Recursive CallStack overfilled! ("+caller.toString().replace(/\{.*\}/i,"")+")");
callStack=[];
return false;
}
else return true;
}callStackMax=10
function a(){if( !callStackTest() ) return; b(); callStack=[];}
function b(){a()} |
||
| Chamurappi Profil |
#5 · Zasláno: 12. 1. 2016, 11:50:26
Reaguji na KryVosu:
„Caller nikdy fungovat nebude, nemá 'historii', jen 'poslední' funkci, kterou byl zavolaný.“ Předpokládám, že tohle tedy není pravda, když nyní používáš callStackTest.caller.caller. Takže by asi šlo projít callery i bez pole callStack.
|
||
| KryVosa Profil |
#6 · Zasláno: 12. 1. 2016, 20:40:09
Chamurappi: Není, ale v případě že budou dvě funkce v rekurzi (klidně i konečné, "ne-nekonečné"), caller se 'zacyklí'.
|
||
|
Časová prodleva: 10 let
|
|||
0