函数PS.Tick()每100毫秒调用一次,其工作是调用NPC的AI函数,以便它们可以移动:
PS.Tick = function ()
{
"use strict";
for (NPCid = 0; NPCid < NPCnumber; NPCid++)
{
NPCAI(NPCid);
};
};
但是我希望NPC不会每100毫秒同时移动一次,但是按照自己的频率进行移动,所以我尝试了这段代码:
PS.Tick = function ()
{
"use strict";
for (NPCid = 0; NPCid < NPCnumber; NPCid++)
{
var timeout = 0;
timeout = PS.Random (1000);
setTimeout("NPCAI(NPCid)",timeout);
};
};
现在,他们根本不动。为什么?如何让它们以不同的时间间隔移动?
答案 0 :(得分:2)
制作
for (NPCid = 0; NPCid < NPCnumber; NPCid++) {
var timeout = 0;
timeout = PS.Random (1000);
(function (id) {
setTimeout(function(){NPCAI(id)},timeout);
})(NPCid); };
需要额外的功能来捕获闭包中的ID。没有它,只会在每个实例中传递循环的最后一个ID。
答案 1 :(得分:0)
现在,他们根本不动。为什么呢?
有几个可能的原因:
如果NPCid
未在任何地方声明:您的代码正在抛出ReferenceError
。
如果NPCid
在某处声明但它不是全局的:当您将字符串传递给setTimeout
时,它不会在当前执行上下文中得到评估,也无法访问到NPCid
。通常,不要将字符串传递给setTimeout
。
如果NPCid
是全局的:当执行延迟代码时,它们都会看到NPCid
的相同值,这是结束时的值强烈的循环。
相反:如果你在NodeJS上做这个(我只是从你正在做的事情推断这个),你可以这样做):
PS.Tick = function ()
{
"use strict";
// (I'm assuming NPCid is defined somewhere; if not, add `var NPCid;` here)
for (NPCid = 0; NPCid < NPCnumber; NPCid++)
{
var timeout = 0;
timeout = PS.Random (1000);
setTimeout(NPCAI, timeout, NPCid); // NodeJS (and Firefox) ONLY!!
}
};
这是有效的,因为在NodeJS(和Firefox)上,setTimeout
可以接受传递给要调用的函数的参数。
如果您没有使用NodeJS或Firefox,但您可以访问ES5的Function#bind
,则可以执行以下操作:
PS.Tick = function ()
{
"use strict";
// (I'm assuming NPCid is defined somewhere; if not, add `var NPCid;` here)
for (NPCid = 0; NPCid < NPCnumber; NPCid++)
{
var timeout = 0;
timeout = PS.Random (1000);
setTimeout(NPCAI.bind(undefined, NPCid), timeout);
}
};
Function#bind
返回一个函数,该函数在调用时将使用特定的this
值和您提供的参数调用原始函数。
如果没有,您可以编写自己的bind
,或者这样做:
PS.Tick = function ()
{
"use strict";
// (I'm assuming NPCid is defined somewhere; if not, add `var NPCid;` here)
for (NPCid = 0; NPCid < NPCnumber; NPCid++)
{
var timeout = 0;
timeout = PS.Random (1000);
setTimeout(makeHandler(NPCid), timeout);
}
function makeHandler(id) {
return function() {
NPCAI(id);
};
}
};
这可以通过创建一个函数来实现,该函数在被调用时转身并使用我们传入其中的值调用NPCAI。
答案 2 :(得分:-1)
你的setTimeout不会调用任何函数,
试试这个:
setTimeout(function(){ NPCAI(NPCid); }, timeout);
或者更好地使用每个NPC的设置间隔,但是使用大量的超时和间隔是非常低效的,所以要注意并准备好延迟。