为什么这个计算导致NaN?

时间:2015-09-01 03:20:59

标签: javascript html5 web

var player = {
    x : 10.0,
    y : 10.0,
    color : "blue",
    v : 5.0,
    size : 10,
    render : function (c) {
        c.fillStyle = this.color;
        c.fillRect(Math.round(this.x), Math.round(this.y), this.size, this.size);
    }
};

function update(delta) {
    player.x += player.v * (delta / 1000);
    console.log("px = " + player.x);
}

function mainLoop(timeStamp) {
    delta = timeStamp - lastFrameTime;
    lastFrameTime = timeStamp;
    /* measure frame rate */
    curFps = Math.round((1/delta)*1000);

    /* game logic */
    update(delta);
    render();

    requestAnimationFrame(mainLoop);
}

当玩家的位置需要更新时,每帧都会调用update()函数。 delta的值是~16.00(以ms为单位的时间)。 为什么player.x的值在打印时显示为NaN?

2 个答案:

答案 0 :(得分:2)

您的第一次循环迭代不会将lastFrameTime初始化为零,它将是未定义的。数字 - undefined = NaN。将程序顶部的lastFrameTime声明为0:

var lastFrameTime = 0;

现在它是一个隐含的全局,意思是因为你从未使用var定义它,它是javascript在循环内创建的偶然全局变量。

答案 1 :(得分:1)

我最好的猜测是代码第一次运行,lastFrameTime未被定义,因此delta = timestamp - < undefined>,这将导致delta为NaN,然后​​将导致player.x通过NaN递增,将其变为NaN,它将永远保持不变,因为我们继续增加它。

我认为您的修复是在代码启动时初始化lastFrameTime(可能是当前时间戳),或者更改主循环

function mainLoop(timeStamp) {
    delta = timeStamp - lastFrameTime;
    lastFrameTime = timeStamp;
    if (!isNaN(delta)) {
        /* measure frame rate */
        curFps = Math.round((1/delta)*1000);

        /* game logic */
        update(delta);
        render();

        requestAnimationFrame(mainLoop);
    }
}

这将跳过第一个错误的游戏循环,其中delta是NaN。在第二次运行时,lastFrameTime不会被定义,delta将被正确创建,一切都应该可以解决。

如果由于某种原因跳过第一个循环并不是一个选项,只需将lastFrameTime初始化为理智的东西,一切都应该没问题。