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

发布于 2024-12-01 07:34:05 字数 157 浏览 2 评论 0原文

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

谢谢

I have a javascript game that will run really fast on some computers and really slow on others. I've been doing some research and I've found that I need to update my loop based on time, but I can't seem to find any good examples of this for javascript. Can someone point me to the right direction on how to get a game to run at 30fps on any hardware?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

小梨窩很甜 2024-12-08 07:34:05

通常游戏按照增量时间运行,即自渲染最后一帧以来的时间量。

伪代码(大致为 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 功率或帧绘制频率的所有依赖。

Normally games work from a Delta Time, that is, the amount of time since the last frame was rendered.

Psuedocode (roughly 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;
}

Using a Delta Time prevents all dependency on CPU power or how often frames get drawn.

溺深海 2024-12-08 07:34:05

如果硬件无法达到 30 fps,您就无法强制游戏以 30 fps 运行。如果它执行的时间超过 1/30 秒,那么你就不走运了。

您可以使用 requestAnimationFrame 让它尽可能快地运行。请参阅此处:http://paulirish.com/2011/requestanimationframe-for-smart-animating/

You can't force a game to run at 30fps if the hardware is unable achieve it. If what it is doing is taking more than 1/30th of a second, you're out of luck.

You can use requestAnimationFrame to let it run as fast as it can though. See here: http://paulirish.com/2011/requestanimationframe-for-smart-animating/

淡看悲欢离合 2024-12-08 07:34:05

您正在寻找的是Deltatiming<的简单实现/a> 在 JavaScript 中。在 JavaScript 中实现它是一项相对简单的任务。事实上,它非常简单,只需不到 25 行 代码即可实现(去掉空行和注释):

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

我认为代码非常不言自明。要观看现场演示,请点击此链接

What you are looking for is a simple implementation of delta timing in JavaScript. Implememting it in JavaScript is a relatively simple task. In fact it's so simple that it can be achieved in less than 25 lines of code (stripping out blank lines and comments):

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

Using it is even more simple. Let's learn by example:

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

I think the code is pretty self explanatory. For the live demo click on this link.

陪你搞怪i 2024-12-08 07:34:05

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

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

You could have a timer function which you can measure how long you are executing for, then call back to yourself at your ((required interval) - (execution time)), in pseudo code

function timer(){
    var timeStart = new Date();
    // Your stuff
    setTimeout (timer, (1000/30) - (new Date() - timeStart));
}
雅心素梦 2024-12-08 07:34:05

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

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

JavaScript 游戏框架列表:

< a href="https://gist.github.com/768272" rel="nofollow">https://gist.github.com/768272

Frameworks like EaselJS often have Tickers/Timers that run every x milliseconds.

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

A list of JavaScript game frameworks:

https://gist.github.com/768272

不乱于心 2024-12-08 07:34:05

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

The only timing mechanisms available to you in JavaScript are setTimeout and setInterval. However, there is no guarantee on the precision of the timers. In fact, since JavaScript in browsers is single threaded there is no guarantee that your timer will fire when you want it to if there is JS running elsewhere already.

Generally speaking, if you want something to occur regularly at a specified interval, you use setInterval. You have to make sure that your callback does not take longer to run than the duration of the interval, otherwise your next interval will fire late. And if that fires late, chances are the next will as well, and you'll just get further and further behind in your executions.

Many modern browsers do support Web Workers, which is essentially a background JS execution (in addition to the primary UI blocking thread we are all familiar with). I have not used Web Workers yet, so I cannot speak to them with any authority or expertise.

If this were me, I would take the following initial approach (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);
策马西风 2024-12-08 07:34:05

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

你不能强迫你的游戏在每个硬件上以所需的速度运行(即使你的游戏的要求非常低,由于网络浏览器的 JavaScript 引擎,总会出现卡顿的情况),但你仍然可以使用 Delta Timing 来避免在不同的硬件之间浪费时间。每一帧。

这里是我用于 JavaScript 游戏的简单代码。这是一个在一秒钟内被调用 FPS 次的函数。示例中为每秒 30 次。

The only option you have with JavaScript is using setTimeout and setInterval to emulate game loops found in other languages.

You cannot force your game to run at the desired speed in each hardware (even if your game is really low on requisites, there will be always stuttering because of web browsers JavaScript engines), but you can still use Delta Timing to not waste time between each frame.

Here is a simple code I use for my JavaScript games. It's a function that gets called FPS times in a second. In the example is 30 times each second.

可爱暴击 2024-12-08 07:34:05

这是创建游戏循环的一种非常简单的方法,该循环将在 javascript 中每秒调用自身 30 次


const fps = 30; // Change this to whatever fps you desire
function gameLoop() {

    // Do something

    setTimeout(gameLoop, 1000 / fps);
}

This is a very simple way of creating a game loop that will call itself 30 times a second in javascript


const fps = 30; // Change this to whatever fps you desire
function gameLoop() {

    // Do something

    setTimeout(gameLoop, 1000 / fps);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文