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

问题描述 投票:0回答:8

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

谢谢

javascript loops frame-rate
8个回答
7
投票

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

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


6
投票
如果硬件无法达到 30 fps,您就无法“强制”游戏以 30 fps 运行。如果它正在做的事情花费了超过 1/30 秒,那么你就不走运了。

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

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

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

您正在寻找的是 JavaScript 中 

1
投票
的简单实现。在 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)";
    }
}

我认为代码非常不言自明。如需现场演示,请点击此

链接

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


0
投票
http://easeljs.com/docs/Ticker.html

JavaScript 游戏框架列表:

https://gist.github.com/768272

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


0
投票

许多现代浏览器确实支持 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);

JavaScript 的唯一选择是使用 
setTimeout

0
投票
setInterval

来模拟其他语言中的游戏循环。


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

Here

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

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


0
投票

© www.soinside.com 2019 - 2024. All rights reserved.