以相同速度运行的Javascript游戏循环?

以相同速度运行的Javascript游戏循环?,javascript,loops,frame-rate,Javascript,Loops,Frame Rate,我有一个javascript游戏,在某些计算机上运行得非常快,而在其他计算机上运行得非常慢。我一直在做一些研究,我发现我需要根据时间更新我的循环,但我似乎找不到任何javascript的好例子。有人能告诉我如何在任何硬件上以30fps的速度运行游戏的正确方向吗 谢谢像EaselJS这样的框架通常有每x毫秒运行一次的计时器 JavaScript游戏框架列表: 如果硬件无法实现,则无法强制游戏以每秒30帧的速度运行。如果它所做的事情花费了超过30分之一秒的时间,那么你就不走运了 您可以使用requ

我有一个javascript游戏,在某些计算机上运行得非常快,而在其他计算机上运行得非常慢。我一直在做一些研究,我发现我需要根据时间更新我的循环,但我似乎找不到任何javascript的好例子。有人能告诉我如何在任何硬件上以30fps的速度运行游戏的正确方向吗


谢谢

像EaselJS这样的框架通常有每x毫秒运行一次的计时器

JavaScript游戏框架列表:

如果硬件无法实现,则无法强制游戏以每秒30帧的速度运行。如果它所做的事情花费了超过30分之一秒的时间,那么你就不走运了


您可以使用requestAnimationFrame让它尽可能快地运行。请参见此处:

您可以有一个计时器函数,您可以测量执行的时间,然后以伪代码的形式在((所需的间隔)-(执行时间))调用自己

function timer(){
    var timeStart = new Date();
    // Your stuff
    setTimeout (timer, (1000/30) - (new Date() - timeStart));
}

JavaScript中唯一可用的计时机制是setTimeout和setInterval。但是,计时器的精度无法保证。事实上,由于浏览器中的JavaScript是单线程的,如果已经有JS在其他地方运行,则无法保证计时器会在您需要时启动

一般来说,如果您希望某件事情在指定的时间间隔内有规律地发生,可以使用setInterval。您必须确保回调的运行时间不会超过间隔的持续时间,否则您的下一个间隔将延迟触发。如果这种情况发生得太晚,那么下一个遗嘱也很有可能发生,你的死刑执行就会越来越落后

许多现代浏览器确实支持WebWorkers,这本质上是一种后台JS执行(除了我们都熟悉的主UI阻塞线程之外)。我还没有使用过网络工作者,所以我不能以任何权威或专业知识与他们交谈

如果是我,我会采取以下初始方法():


通常,游戏从增量时间开始工作,也就是说,从最后一帧渲染开始的时间量

伪代码(大致为C#):


使用增量时间可以防止所有对CPU功率或帧绘制频率的依赖。

JavaScript的唯一选项是使用
setTimeout
setInterval
模拟其他语言中的游戏循环

你不能强迫你的游戏在每个硬件上以期望的速度运行(即使你的游戏在必要条件上真的很低,也会因为web浏览器JavaScript引擎而出现口吃),但是你仍然可以使用增量计时来避免在每一帧之间浪费时间


这是一个用于JavaScript游戏的简单代码。这是一个在一秒钟内被调用FPS次的函数。在本例中,每秒执行30次。

您需要的是JavaScript中的一个简单实现。在JavaScript中实现它是一项相对简单的任务。事实上,它非常简单,只需不到25行即可实现(去掉空行和注释):

使用它更简单。让我们通过示例学习:

var timer = new DeltaTimer(render, 1000 / 30);
var start = timer.start();
var body = document.body;
var frame = 0;

function render(time) {
    time -= start;
    body.innerHTML += (frame++) + ". " + time + " ms<br/>";

    if (time >= 1000) {
        var stop = timer.stop() - start;
        body.innerHTML += "<br/>" + stop + " ms (stopped)";
    }
}
var定时器=新的增量定时器(渲染,1000/30);
var start=timer.start();
var body=document.body;
var帧=0;
函数渲染(时间){
时间-=开始;
body.innerHTML++=(frame++++“+time++”ms
”; 如果(时间>=1000){ var stop=timer.stop()-start; body.innerHTML+=“
”+stop+“ms(stopped)”; } }

我认为这段代码很容易解释。对于实时演示,请单击此按钮。

我的蜘蛛侠意识告诉我,虽然您可以稍微缩小差距,但您的循环速度总是会根据客户端配置、硬件、网络延迟等而有所变化。@Dave-哇,这已经是一段时间了。我真的认为你应该接受一个答案。你也应该看看这个链接:从那篇文章中,它从游戏开发的角度来探讨这个问题。
DateTime lastFrameTimeStamp = DateTime.Now;
void Draw()
{
    TimeSpan timeSinceLastFrame = DateTime.Now.Subtract(lastFrameTimeStamp);
    float deltaTime = timeSinceLastFrame.TotalSeconds;

    // Do all of your movement and other time-based math based on the deltaTime, Like:
    float x = x + (MovementPerSecond * deltaTime);


    lastFrameTimeStamp = DateTime.Now;
}
function DeltaTimer(render, interval) {
    var timeout;
    var lastTime;

    this.start = start;
    this.stop = stop;

    function start() {
        timeout = setTimeout(loop, 0);
        lastTime = Date.now();
        return lastTime;
    }

    function stop() {
        clearTimeout(timeout);
        return lastTime;
    }

    function loop() {
        var thisTime = Date.now();
        var deltaTime = thisTime - lastTime;
        var delay = Math.max(interval - deltaTime, 0);
        timeout = setTimeout(loop, delay);
        lastTime = thisTime + delay;
        render(thisTime);
    }
}
var timer = new DeltaTimer(render, 1000 / 30);
var start = timer.start();
var body = document.body;
var frame = 0;

function render(time) {
    time -= start;
    body.innerHTML += (frame++) + ". " + time + " ms<br/>";

    if (time >= 1000) {
        var stop = timer.stop() - start;
        body.innerHTML += "<br/>" + stop + " ms (stopped)";
    }
}