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

时间:2011-08-25 15:24:20

标签: javascript loops frame-rate

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

由于

7 个答案:

答案 0 :(得分:7)

正常情况下,游戏的工作时间是增量时间,即自上一帧渲染以来的时间量。

Psuedocode(大致是C#):

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;
}

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

答案 1 :(得分:6)

如果硬件无法实现,则不能强制游戏以30fps运行。如果它正在做的事情超过1/30秒,那你就不走运了。

您可以使用requestAnimationFrame让它尽可能快地运行。见这里:http://paulirish.com/2011/requestanimationframe-for-smart-animating/

答案 2 :(得分:1)

你可以有一个计时器功能,你可以测量你执行的时间,然后在你的((所需的间隔) - (执行时间)),伪代码回电给你自己

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

答案 3 :(得分:1)

您正在寻找的是JavaScript中delta timing的简单实现。在JavaScript中实现它是一项相对简单的任务。实际上它非常简单,可以在不到25行code中实现(删除空行和注释):

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)";
    }
}

我认为代码非常自我解释。对于现场演示,请单击此link

答案 4 :(得分:0)

像EaselJS这样的框架通常每隔x毫秒运行一次Tickers / Timers。

http://easeljs.com/docs/Ticker.html

JavaScript游戏框架列表:

https://gist.github.com/768272

答案 5 :(得分:0)

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

一般来说,如果您希望以指定的间隔定期发生某些事情,请使用setInterval。您必须确保回调的运行时间不会超过间隔的持续时间,否则您的下一个时间间隔将会延迟。如果事情发生得很晚,那么接下来的意愿也是可能的,而且你的处决也会越来越远。

许多现代浏览器都支持Web Workers,它本质上是一个后台JS执行(除了我们都熟悉的主UI阻塞线程)。我还没有使用Web Workers,所以我不能以任何权威或专业知识与他们交谈。

如果这是我,我会采取以下初步方法(http://jsfiddle.net/Ce3wq/):

var GameTimer = (function () {
    var gameTimer = function (opts) {
        var self = this;
        opts = opts || {};
        opts.stepInterval = opts.stepInterval || 30;

        var callbacks = {};
        var stepInterval= opts.stepInterval; // ms

        this.domReady = function () {
            setInterval(step, stepInterval);
        };

        this.registerService = function(callback){
            callbacks[callback] = callback;
        };

        this.removeService = function(){
            delete callbacks[callback];
        };

        var step = function () {
            for(var id in callbacks){
                callbacks[id]();
            }
        };
    };

    return new gameTimer;
})();

var eachTick = function(){
    console.log(new Date().getTime());
};

GameTimer.registerService (eachTick);

jQuery(document).ready(GameTimer.domReady);

答案 6 :(得分:0)

您使用JavaScript的唯一选择是使用setTimeoutsetInterval来模拟其他语言中的游戏循环。

你不能强迫你的游戏在每个硬件中以所需的速度运行(即使你的游戏在必备条件上非常低,因为网页浏览器JavaScript引擎会一直存在口吃),但你仍然可以使用Delta Timing每帧之间浪费时间。

Here是我用于JavaScript游戏的简单代码。这是一个在一秒钟内被称为FPS时间的函数。在这个例子中,每秒30次。