2011-11-13 201 views
2

我有一些關於JavaScript循環的問題。Javascript遊戲循環

問題:

  • 爲什麼一個JavaScript循環凍結瀏覽器
  • 爲什麼繪製緩慢甚至做它運行在比1逼平每1ms,它的繪製簡單的事情!
  • 解決方案是什麼?閃光正在消逝,我們現在做什麼?

這裏是帆布代碼親自嘗試一下:

<!doctype html> 
<html> 
<head> 
</head> 
<body> 
    <canvas id="c" width="400" height="400"></canvas> 
    <script type="text/javascript"> 

     var c = document.getElementById('c'); 

     ctx = c.getContext('2d'); 

     var x = 100; 

     ctx.fillStyle= '#f00'; 

     function loop() 
     { 
      ctx.fillRect(x, 100, 20, 20); 

      ++x; 
     } 

     setInterval(loop, 1); 
    </script> 
</body> 
</html> 
+1

你的電腦如何成爲野獸?聽起來不太有力 – ExceptionSlayer

+0

閃光燈不會死亡。 –

+2

@AustinHenley它將被替換爲HTML5,因爲它是一個更合適的工具 – Raynos

回答

10

爲什麼一個JavaScript環凍結瀏覽器(在C不會發生++)

JavaScript是單線程的。在javascript代碼正在運行或競態條件發生時,DOM的狀態不能改變。這意味着沒有繪圖/迴流。

爲什麼繪圖速度慢,即使它在每1ms繪製一次,它繪製的是最簡單的東西!

它不在1ms運行,它運行在10ms,因爲瀏覽器不允許你緊密地循環。

什麼是解決方案?閃光正在消逝,我們現在做什麼?

使用requestAnimationFrame並以60 FPS運行您的遊戲,爲什麼需要更多?

Example using (webkit) requestAnimationFrame它對我來說順利運行。

+0

(webkit/mozilla)RequestAnimationFrame不會真正與刷新率同步,它是僅僅是基於刷新率的時間間隔回調。通過這種估算,以兩倍的幀速率渲染可以看到渲染平滑度的改善,如果它完全計時,則不會如此。問題在於,您在瀏覽器中發現的JavaScript從未設計用於執行我們真正想在瀏覽器中執行的高性能多線程任務。這不是JavaScript的缺點,只是將JavaScript用作瀏覽器中的單線程事件接收器。 「 –

+0

」JavaScript是單線程的。「 不是true javascript是多線程的 https://developer.mozilla.org/zh-CN/docs/Web/Guide/Performance/Using_web_workers –

2

一毫秒是一個非常短的時間間隔。
這段時間很短,您的代碼將幾乎不斷地在UI線程中運行,從而導致瀏覽器無法響應。

您需要暫停以讓用戶有時間與頁面進行交互。

使用至少十個,最好是一百個毫秒的間隔。

+0

這完全不是。 setInterval不會使瀏覽器無響應。 – Raynos

+2

@Raynos:_當間隔runs_中的代碼時,瀏覽器無響應。如果沒有任何時候代碼**沒有運行,瀏覽器將不會響應。 – SLaks

+0

但瀏覽器有一個最小設置超時,以避免這個確切的問題。這個最小值是10.這不是問題。瀏覽器可以在10毫秒內完成大量的迴流渲染 – Raynos

0

幀率下降並最終導致瀏覽器凍結的原因是由於canvas元素佔用的內存。我已經回答了這個問題。你可以找到線程here

每次您將畫布的操作保存到畫布的路徑時畫一些東西。每次您在畫布上繪製某些內容時,此路徑會佔用更多內存。如果你沒有清空畫布的路徑,你將有幀率下降。例如,看看你的javascript和javascript之間的執行時間差,清除畫布路徑,

var c = document.getElementById('c'); 
ctx = c.getContext('2d'); 
var x = 100; 
ctx.fillStyle= '#f00'; 

function loop() 
{ 
    ctx.beginPath(); 
    ctx.fillRect(x, 100, 20, 20); 

    ++x; 
} 
setInterval(loop, 1);