2011-08-25 55 views
4

我有一個JavaScript遊戲,在一些計算機上運行速度非常快,而在其他計算機上運行速度非常慢。我一直在做一些研究,我發現我需要根據時間更新我的循環,但我似乎無法找到任何有關JavaScript的好例子。有人能指出我如何讓​​遊戲在任何硬件上以30fps運行的正確方向嗎?以相同的速度運行的Javascript遊戲循環?

感謝

+2

我的spidey感覺告訴我,儘管你可能能夠縮小差距,但基於客戶端配置,硬件,網絡延遲等等,你的迴路速度總是會有所不同。 –

+0

@Dave - 哇已經有些了是時候了。我真的覺得你應該接受一個答案。 –

回答

6

不能遊戲以30fps的運行,如果硬件是無法實現這一目標。如果它正在做的是超過1/30秒,那麼你運氣不好。

您可以使用requestAnimationFrame讓它運行得儘可能快。在這裏看到:http://paulirish.com/2011/requestanimationframe-for-smart-animating/

+4

你也應該看看這個鏈接:http://nokarma.org/2011/02/02/javascript-game-development-the-game-loop/index.html從那篇文章中,開發視角。 – nwellcome

1

你可以有你可以衡量你多長時間執行,然後在你再打給自己一個定時器功能((需要間隔) - (執行時間)),在僞代碼

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

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

通常遊戲從增量時間工作,也就是自上一幀被渲染的時間量。

僞碼(約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功率或多久幀拿得出的所有依賴。

0

您在JavaScript中使用的唯一選項是使用setTimeoutsetInterval來模擬在其他語言中找到的遊戲循環。

你不能強迫你的遊戲在每個硬件中以所需的速度運行(即使你的遊戲真的需求量很低,因爲網絡瀏覽器JavaScript引擎總是會出現口吃),但是你仍然可以使用Delta Timing而不是在每一幀之間浪費時間。

Here是我用於我的JavaScript遊戲的簡單代碼。這是一秒鐘內被稱爲FPS時間的功能。在這個例子中是每秒30次。

+0

用示例小提琴編輯 –

0

您正在尋找的是在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