2012-08-05 103 views
3

我簡化了我的遊戲循環,只是一個在屏幕上移動的框,Click Here。出於某種原因,盒子似乎並不平穩。我做了一個video of it here帶遊戲循環的JavaScript流暢動畫

遊戲循環被稱爲像這樣:

var game = function() { 
    var now = Date.now(); 
    var delta = now - then; 

    update(delta/1000); 
    draw(); 

    then = now; 
}; 

setInterval(game, 1000/50); 

我試圖分離主遊戲循環的draw電話,把他們在​​,但問題仍然存在。我看過一些看起來運行順利的教程。我甚至嘗試過使用fixed time-step game loop,但這讓我的遊戲運行速度難以控制。

我該如何改進上述邏輯,或許利用​​和維護deltaTime來調用update

+0

我完全沒有看到它,它也一直說'59'。那是fps嗎? – Esailija 2012-08-05 20:38:09

+0

嗯,是的59是我每秒顯示更新次數的嘗試。在我的Mac和Safari瀏覽器中,我看到槳和球向前跳一點,而不是平穩移動。我想我應該在其他一些電腦上檢查它。 – Quantastical 2012-08-05 20:44:49

+0

如果我仔細觀察球的話,我猜球有點不舒服......這是因爲在某些幀中,球一次移動超過1px。 – Esailija 2012-08-05 20:45:38

回答

3

我相信在使用畫布時,您的位置變量應該是整數值,因爲它們表示像素和浮點值沒有意義。如果你打開控制檯並輸入sceneManager.currentScene.GameplayLayer.ball.position.x,那麼你會得到一個非常長的小數。我認爲對OP的評論表明,有時球移動2px而不是1px可能會對某事產生影響。當你更新你的位置時,你最終得到一個浮點值。

我相信它有時會舍入到下一個最高像素位置,有時會下降。我會嘗試採取在地面或天花板上,像這樣:

this.position.x += Math.floor(this.speed * 100 * deltaTime * Math.cos(directionInRadians)); 
this.position.y += Math.floor(this.speed * 100 * deltaTime * Math.sin(directionInRadians)); 

我會做這些改變的,看看它是如何工作。

編輯:由於你編輯你的問題來簡化邏輯。我可以建議一些嘗試,即使用我創建的Clock對象,這是我一直使用的。它給了我流暢的動畫,而且非常簡單。它基於clock that Three.JS uses,因此您可能也想檢查一下。即使你想使用你自己的代碼,你至少可以嘗試這個現成的解決方案,看看它是否給你相同的結果。它似乎對我來說工作得很好。另外,您嘗試使用墊片,因此您在遊戲功能中的呼叫應該是requestAnimFrame(game);

var Clock = function() { 

    /** Member startTime will remain fixed at its integer 
     millisecond value returned by Date.now(). Will always 
     be equal to the time the clock was started */ 
    this.startTime = Date.now(); 

    /** Member ms is updated by tick() to a integer value reprsenting 
     the number of milliseconds between the epoch (January 1, 1970) 
     and the current date and time of the system. */ 
    this.ms = this.startTime; 
    this.last = this.startTime; /** millis at last call to tick() */ 
    this.time = 0;    /** ms in floating point seconds not millis */ 

    /** Member dt is updated by tick() to an integer value representing 
     the number of milliseconds since the last call to tick(). */ 
    this.dt = 0; 
    this.delta = 0; /** dt in floating point seconds not millis */ 

    /** Member fps is updated by tick() to a floating point value representing 
     frames per second, updated and averaged approximately once per second */ 
    this.fps = 0.0; 

    /** Member frameCount is updated to an integer value representing the 
     total number of calls to tick() since the clock was created. */ 
    this.frameCount = 0; 

    /** The frameCounter member is a flag you can turn off if you don't need to 
     calculate the frameCount or do the average FPS calculation every second */ 
    this.frameCounter = true; 

    /** Private globals needed to calculcate/average fps over eachs second */ 
    var timeToUpdate = 0; 
    var framesToUpdate = 0; 

    /************************************************************************************ 
     The tick() method updates ALL the Clock members, which should only 
     be read from and never written to manually. It is recommended that 
     tick() is called from a callback loop using requestAnimationFrame 

     Learn more: http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 
    *************************************************************************************/ 
    this.tick = function() { 
     /** This is a new frame with it's very own unique number */ 

     if (this.frameCounter) this.frameCount++; 

     /** Set the private currentTime variable */ 
     this.ms = Date.now(); 

     /** Update time delta and immediately set last time to 
      be as accurate as possible in our timings. */ 
     this.dt = this.ms - this.last; 
     this.last = this.ms; 

     /** Calculate floating-point delta and increment time member */ 
     this.delta = 0.001 * this.dt; 
     this.time += this.delta; 

     /** Calculate private temp variables for fps calculation */ 
     if (this.frameCounter) { 
      timeToUpdate += this.dt; 
      framesToUpdate++; 
      if (timeToUpdate > 1000) { 
       this.fps = Math.round((framesToUpdate * 1000)/timeToUpdate); 
       framesToUpdate = 0; 
       timeToUpdate = 0; 
      } 
     } 
    } 
} 

如果你使用這個對象,那麼所有你需要做在你的初始化函數創建一個新的時鐘對象,像這樣clock = new Clock();。然後在每個動畫調用中調用clock.tick()。然後,您可以訪問成員clock.deltaclock.time,它們會以秒爲單位給出delta和time作爲浮點值。 clock.dtclock.ms會給你相同的毫秒整數。您也可以使用clock.fps訪問fps,或者通過設置clock.frameCounter = false來禁用它。

+0

嗯,我嘗試了你的建議,它仍然呈現相同的問題。我認爲我的遊戲循環邏輯出於某種原因是不正確的,我嘗試的一切似乎都以同樣的方式作出反應。我拿了別人的代碼,並且能夠在我的電腦上製作一個流暢的動畫,所以我可能不得不將我的遊戲重新加入主循環,看看會發生什麼。再次感謝您的幫助。我希望有一個全部用於JavaScript的遊戲循環邏輯。 – Quantastical 2012-08-06 12:39:29

+0

這聽起來像是一個好主意,你在這個應用程序中的結構執行得很好,但對於你到目前爲止看起來確實很複雜。我將從3個函數init,animate和render開始。儘可能以最簡單的方式使其運行良好,並在您爲遊戲增加複雜性時建立抽象。到目前爲止,所有不同的文件和類似乎有點矯枉過正。儘管如此,它確實看起來不錯。一些小東西可能不正確,而且很難將程序流盡可能簡單地視覺化。 – 2012-08-06 19:26:52

+0

單挑:我簡化了邏輯並更新了我的問題。這個答案可能不再相關。 – Quantastical 2012-08-07 03:36:47

1

使用three.js時鐘平滑了我的動畫。我強烈推薦它。其他好的代碼也在那裏。

+0

'clock.js'使用'Date.now()'來實現它。我想知道它如何比OP中的代碼更流暢。 – tigrou 2015-05-14 16:31:10