0

函数 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);
};
};

现在,他们根本不动。为什么?如何让它们以不同的时间间隔移动?

4

3 回答 3

2

做那个

for (NPCid = 0; NPCid < NPCnumber; NPCid++) {
    var timeout = 0;
    timeout = PS.Random (1000);
    (function (id) {
        setTimeout(function(){NPCAI(id)},timeout);
    })(NPCid); };

需要这个额外的函数来捕获闭包中的 ID。没有它,每个实例只会传递循环的最后一个 ID。

于 2012-07-09T15:46:40.523 回答
0

现在,他们根本不动。为什么?

几个可能的原因:

  • 如果NPCid未在任何地方声明:您的代码正在抛出ReferenceError.

  • 如果NPCid在某处声明但它不是全局的:当您将字符串传递给 时setTimeout,它不会在当前执行上下文中被评估并且无权访问NPCid. 一般来说,不要将字符串传递到setTimeout.

  • ifNPCid是全局的:当延迟的代码被执行时,他们都会看到相同的值 for 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。

于 2012-07-09T15:50:38.933 回答
-1

您的 setTimeout 不调用任何函数,

试试这个:

setTimeout(function(){ NPCAI(NPCid); }, timeout);

或者更好地为每个 NPC 单独使用设置间隔,但是使用大量超时和间隔非常低效,因此请注意并准备好延迟。

于 2012-07-09T15:48:49.387 回答