我有一個JavaScript遊戲,在一些計算機上運行速度非常快,而在其他計算機上運行速度非常慢。我一直在做一些研究,我發現我需要根據時間更新我的循環,但我似乎無法找到任何有關JavaScript的好例子。有人能指出我如何讓遊戲在任何硬件上以30fps運行的正確方向嗎?以相同的速度運行的Javascript遊戲循環?
感謝
我有一個JavaScript遊戲,在一些計算機上運行速度非常快,而在其他計算機上運行速度非常慢。我一直在做一些研究,我發現我需要根據時間更新我的循環,但我似乎無法找到任何有關JavaScript的好例子。有人能指出我如何讓遊戲在任何硬件上以30fps運行的正確方向嗎?以相同的速度運行的Javascript遊戲循環?
感謝
不能力遊戲以30fps的運行,如果硬件是無法實現這一目標。如果它正在做的是超過1/30秒,那麼你運氣不好。
您可以使用requestAnimationFrame讓它運行得儘可能快。在這裏看到:http://paulirish.com/2011/requestanimationframe-for-smart-animating/
你也應該看看這個鏈接:http://nokarma.org/2011/02/02/javascript-game-development-the-game-loop/index.html從那篇文章中,開發視角。 – nwellcome
你可以有你可以衡量你多長時間執行,然後在你再打給自己一個定時器功能((需要間隔) - (執行時間)),在僞代碼
function timer(){
var timeStart = new Date();
// Your stuff
setTimeout (timer, (1000/30) - (new Date() - timeStart));
}
JavaScript中可用的唯一計時機制是setTimeout和setInterval。但是,不能保證定時器的精度。事實上,由於瀏覽器中的JavaScript是單線程的,因此如果JS已經在其他地方運行了,則不能保證你的計時器會在需要時觸發。
一般來說,如果您想要以指定的時間間隔定期發生某些事情,請使用setInterval。您必須確保您的回調不會比時間間隔持續時間更長,否則您的下一個時間間隔會延遲。如果這種情況發生得很晚,那麼下一次就會有機會,而且在執行過程中你會越來越落後。
許多現代瀏覽器都支持Web Workers,它實質上是一個後臺JS執行(除了我們熟悉的主UI阻塞線程外)。我還沒有使用網絡工作者,所以我不能用任何權威或專業知識與他們交談。
如果這是我,我會採取以下最初的方法(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);
通常遊戲從增量時間工作,也就是自上一幀被渲染的時間量。
僞碼(約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功率或多久幀拿得出的所有依賴。
您在JavaScript中使用的唯一選項是使用setTimeout
和setInterval
來模擬在其他語言中找到的遊戲循環。
你不能強迫你的遊戲在每個硬件中以所需的速度運行(即使你的遊戲真的需求量很低,因爲網絡瀏覽器JavaScript引擎總是會出現口吃),但是你仍然可以使用Delta Timing而不是在每一幀之間浪費時間。
Here是我用於我的JavaScript遊戲的簡單代碼。這是一秒鐘內被稱爲FPS時間的功能。在這個例子中是每秒30次。
用示例小提琴編輯 –
您正在尋找的是在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。
我的spidey感覺告訴我,儘管你可能能夠縮小差距,但基於客戶端配置,硬件,網絡延遲等等,你的迴路速度總是會有所不同。 –
@Dave - 哇已經有些了是時候了。我真的覺得你應該接受一個答案。 –