Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/89.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
重力与长时间步长(使用javascript)_Javascript_Html_Canvas - Fatal编程技术网

重力与长时间步长(使用javascript)

重力与长时间步长(使用javascript),javascript,html,canvas,Javascript,Html,Canvas,我想用gravity创建一个简单的动画(在chrome和firefox中测试)。我正在用Javascript和canvas做这件事。重力和速度通过使用(:46)的可变时间步长计算: 每个球都有计算速度和位置的代码(:148): 现在,当您查看窗口时,这个原型可以正常工作 但是,如果隐藏当前窗口(切换到浏览器的另一个选项卡),window.requestAnimationFrame将停止。如果等待5秒钟,然后打开窗口,window.requestAnimationFrame将继续。问题是realD

我想用gravity创建一个简单的动画(在chrome和firefox中测试)。我正在用Javascript和canvas做这件事。重力和速度通过使用(:46)的可变时间步长计算:

每个球都有计算速度和位置的代码(:148):

现在,当您查看窗口时,这个原型可以正常工作

但是,如果隐藏当前窗口(切换到浏览器的另一个选项卡),window.requestAnimationFrame将停止。如果等待5秒钟,然后打开窗口,window.requestAnimationFrame将继续。问题是realDelta现在是5秒,速度太大了

我可以添加一个不允许realDelta大于一秒的检查(:46):

但这并不能真正解决问题

现在我不明白如何真正解决这个问题。我应该检查窗口是否隐藏并暂停计时器(当窗口再次可见时恢复计时器)。还是我的速度计算有误?其他html5游戏如何解决“dt”太大的问题


感谢使用这些jQuery事件来启动/停止帧计算:

(你可以尝试不用jQuery——纯javascript,但是X浏览器的东西会让你发疯的!)


唯一的问题是在某些浏览器中,这些事件会被多次触发,因此您可能还需要设置一个开/关标志,以便只对第一次触发作出反应。

在draw函数中,您可以通过多次运行函数来弥补错过的帧:

var TIME_INTERVAL = 1000/60;
var timeElapsed = 0;
requestAnimFrame(draw, TIME_INTERVAL);

function draw() { 
    timeElapsed += now - this.prevTime;
    this.prevTime = now;
    while(timeElapsed > TIME_INTERVAL)
    {
        timeElapsed -= TIME_INTERVAL;
        // Run Draw
    }

    requestAnimFrame(draw, TIME_INTERVAL);
}
当然,如果用户在选项卡上停留的时间太长,他们可能会返回大量计算。还可以考虑在RequestAnimFrame不可用的情况下运行备份:

var TIME_INTERVAL = 1000/60;
var timeElapsed = 0;
var backup = setInterval(draw, TIME_INTERVAL*5);
requestAnimFrame(draw, TIME_INTERVAL);

function draw() {
    clearInterval(backup);

    timeElapsed += now - this.prevTime;
    this.prevTime = now;
    while(timeElapsed > TIME_INTERVAL)
    {
        timeElapsed -= TIME_INTERVAL;
        // Run Draw
    }

    backup = setInterval(draw, TIME_INTERVAL*5);
    requestAnimFrame(draw, TIME_INTERVAL);
}

选择一些最大(或固定)时间步长。如果实际经过的时间间隔大于最大时间步长,请多次运行物理函数。我还不太熟悉canvas,但我想可能会有类似于on_resume事件的情况。如果继续,只需将时间设置为上次使用的增量。你认为这样的事情是可能的吗?谢谢,这是一个快速和简单的黑客来修复问题,这是一个很好的方式来处理这个问题!对不起,我不能投你一票,我的声望很低:D
this.realDelta = (now - this.prevTime) / 1000;
if (this.realDelta > 1) {
    this.realDelta = 1;
}
this.realTime += this.realDelta;
$(window).blur(function(e) {
    // User has changed tabs away from your window
    // So freeze your incrementing until the user returns 
});


$(window).focus(function(e) {
    // User has returned to your tab
    // So begin your incrementing again
});
var TIME_INTERVAL = 1000/60;
var timeElapsed = 0;
requestAnimFrame(draw, TIME_INTERVAL);

function draw() { 
    timeElapsed += now - this.prevTime;
    this.prevTime = now;
    while(timeElapsed > TIME_INTERVAL)
    {
        timeElapsed -= TIME_INTERVAL;
        // Run Draw
    }

    requestAnimFrame(draw, TIME_INTERVAL);
}
var TIME_INTERVAL = 1000/60;
var timeElapsed = 0;
var backup = setInterval(draw, TIME_INTERVAL*5);
requestAnimFrame(draw, TIME_INTERVAL);

function draw() {
    clearInterval(backup);

    timeElapsed += now - this.prevTime;
    this.prevTime = now;
    while(timeElapsed > TIME_INTERVAL)
    {
        timeElapsed -= TIME_INTERVAL;
        // Run Draw
    }

    backup = setInterval(draw, TIME_INTERVAL*5);
    requestAnimFrame(draw, TIME_INTERVAL);
}