[英]Canvas game frame rate drop (30fps), also randomly stuttering/janking
[英]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);
}
您應該將simulating
和drawing
分開。
下面是我每毫秒(每秒 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.