簡體   English   中英

javascript - 使用 requestAnimationFrame 的簡單 30fps 游戲循環?

[英]A simple 30fps game loop in javascript using requestAnimationFrame?

我正在編寫一個紙牌游戲,所以我需要使用 window.requestAnimationFrame 設置一個基本的游戲循環。 我需要將 fps 設置為 30fps,因為它是一個慢節奏的紙牌游戲,我只需要一個簡單可行的游戲循環。 我的游戲循環如下。

function loop(timestamp) {
          var progress = timestamp - lastRender

          update(progress)
          draw()

          lastRender = timestamp
          window.requestAnimationFrame(loop)
        }
        var lastRender = 0
        window.requestAnimationFrame(loop)

我如何才能將 fps 設置為 30fps? 我感謝任何幫助! 謝謝!

FPS 代表每秒幀數。

1000 / 30 = 30 幀/秒

試試這個基本功能:

function animate() {
  setTimeout(function() {
    requestAnimationFrame(animate);
  }, 1000 / 30);
}

您應該將simulatingdrawing分開。

下面是我每毫秒(每秒 1000 次)進行一次simulation的示例。 每次模擬都會取消先前對動畫幀的請求。

如果瀏覽器刷新“勾選”,它將drawn我們的更新(增加我們的計數器)。

1 秒后我停止,我們應該看到大約你的顯示器刷新率作為我們的count

 //counter var count = 0; //draw function function draw() { count++; } //Animation frame handle var animationFramHandle; //Run every millisecond var interval = setInterval(function() { //Cancel requestAnimationFrame cancelAnimationFrame(animationFramHandle); //request new requestAnimationFrame animationFramHandle = requestAnimationFrame(draw); }, 1); //Wait 1 second setTimeout(function() { //Stop simulation clearInterval(interval); cancelAnimationFrame(animationFramHandle); console.log("ticks in a second:", count); }, 1000);

編輯 - 為什么關注點分離

在畫布上繪圖是一項昂貴的操作,如果可以避免的話,您通常不會希望在每一幀上都運行。

基本上只在發生變化時調用重繪。

在下面的示例中,我創建了大量的框,模擬它們並繪制它們:

 //DOM elements var canvas = document.createElement("canvas"); canvas.width = 400; canvas.height = 400; document.body.appendChild(canvas); var ctx = canvas.getContext("2d"); ctx.fillStyle = "rgba(0,0,0,0.1)"; var drawNode = document.createElement("p"); document.body.appendChild(drawNode); //Variables var simulations = 0; var simulationTime = 0; var requestAnimationFrameHandle; //Boxes to simulate and draw var boxes = []; while (boxes.length < 10000) { boxes.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, s: 5 }); } //Draw function function draw() { var t = Date.now(); //Clear ctx.clearRect(0, 0, canvas.width, canvas.height); //Draw for (var bIndex = 0; bIndex < boxes.length; bIndex++) { var box = boxes[bIndex]; ctx.fillRect(box.x, box.y, box.s, box.s); } //Log drawNode.innerHTML = ("New draw after " + simulations + " simulations<br>Drawing took " + (Date.now() - t) + " ms<br>Simulation time is " + simulationTime + " ms"); simulations = 0; } //Simulate function function simulate(force) { if (force === void 0) { force = false; } simulations++; if (Math.random() * 1000 > 800) { var t = Date.now(); for (var bIndex = 0; bIndex < boxes.length; bIndex++) { var box = boxes[bIndex]; box.x = Math.abs(box.x + (Math.random() * 3 - 1)) % canvas.width; box.y = Math.abs(box.y + (Math.random() * 3 - 1)) % canvas.height; } simulationTime = Date.now() - t; cancelAnimationFrame(requestAnimationFrameHandle); requestAnimationFrameHandle = requestAnimationFrame(draw); } } setInterval(simulate, 1000 / 120);

請注意模擬它們比繪制它們要快得多。

根據經驗,每幀之間只有1000/60 ~ 16毫秒,所以如果我們可以1000/60 ~ 16繪制所需的毫秒,那么我們很樂意這樣做並將這樣的幀計算時間集中在更大的操作上(例如尋路或碰撞檢測或任何在您的游戲中很重的東西)。

通過這種方式,我們還可以以不同於繪制速率的其他速率運行我們的模擬,這在處理異步任務時很方便。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM