我有一个 JavaScript 游戏,它在某些计算机上运行得非常快,但在其他计算机上运行得非常慢。我一直在做一些研究,我发现我需要根据时间更新我的循环,但我似乎找不到任何关于 javascript 的好例子。有人能给我指出如何让游戏在任何硬件上以 30fps 运行的正确方向吗?
谢谢
通常游戏按照增量时间运行,即自渲染最后一帧以来的时间量。
伪代码(大致为 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 功率或帧绘制频率的所有依赖。
function timer(){
var timeStart = new Date();
// Your stuff
setTimeout (timer, (1000/30) - (new Date() - timeStart));
}
您正在寻找的是 JavaScript 中
即可实现(去掉空行和注释):
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)";
}
}
我认为代码非常不言自明。如需现场演示,请点击此
链接。
许多现代浏览器确实支持 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