我有一個簡單的游戲回圈,如下所示:
function update(progress){
//do something each second
//do something else twice per second
//do something else each two seconds
}
function draw() {
//code here...
}
function gameLoop(timestamp) {
update(progress)
draw()
var progress = (timestamp - lastRender)
lastRender = timestamp
window.requestAnimationFrame(gameLoop)
}
var lastRender = 0
window.requestAnimationFrame(gameLoop)
如何確保每隔半秒、一秒或兩秒對更新函式執行一些操作?
謝謝
uj5u.com熱心網友回復:
如果要定義間隔,則需要使用setInterval. requestAnimationFrame只會根據螢屏的重繪 率進行更新,因此您無法以此定義自己的時間間隔。setInterval雖然有很多缺點,所以建議使用這樣的方法將時間間隔與重繪 率同步:
let doUpdate = false
setInterval(() => doUpdate = true), 1000)
const render = () => {
if (doUpdate) {
// your code
doUpdate = false
}
}
window.requestAnimationFrame(render)
uj5u.com熱心網友回復:
如果您想在使用基于增量時間的游戲回圈時定期執行一個動作,基本的想法是讓您保持一個經過時間的計數器。然后,對于每次迭代,您添加時間差,直到它達到預期的時間段。
應用于您的代碼,它看起來像這樣:
let oneSecondCounter = 0
let twoSecondCounter = 0
function update(progress){
oneSecondCounter = progress
if (oneSecondCounter >= 1000) {
// Code here will be executed every 1000ms
oneSecondCounter = 0
}
twoSecondCounter = progress
if (twoSecondCounter >= 2000) {
// Code here will be executed every 2000ms
twoSecondCounter = 0
}
}
function draw() {}
function gameLoop(timestamp) {
var progress = (timestamp - lastRender)
update(progress)
draw()
lastRender = timestamp
window.requestAnimationFrame(gameLoop)
}
var lastRender = performance.now()
window.requestAnimationFrame(gameLoop)
但是,這意味著您必須為要執行的每個周期性操作創建一個計數器變數。我們可以使用閉包將計數器與函式捆綁在一起,而不是創建單獨的變數。閉包讓每個函式都有自己獨立的計數器。
我們將要使用的閉包如??下所示:
function initPeriodicFunction(fn, runEvery) {
let counter = 0
return function (deltaTime) {
counter = deltaTime
if (counter >= runEvery) {
fn()
counter = 0
}
}
}
現在,不必為每個動作創建一個計數器變數,我們只需將一個函式傳遞給initPeriodicFunction并獲得一個只會定期運行的新函式。
// You can use an arrow function
const runEverySecond = initPeriodicFunction(() => console.log('One second'), 1000)
// Or you can pass a function
function runThis() {
console.log('Two seconds')
}
const runEveryTwoSeconds = initPeriodicFunction(runThis, 2000)
function update(progress){
runEverySecond(progress)
runEveryTwoSeconds(progress)
}
根據您的用例,上述方法可能就足夠了。如果您要執行更準確的任務(例如物理引擎),最好將幀速率與更新速率分開。這類似于 Unity 的FixedUpdate作業方式。
Imagine you want to perform a physics update every 100ms. If somehow the update call was delayed, for example 600ms after the last update, instead of performing a single update, we perform 6 updates, each with 100ms chunk. This results in more precise step-by-step calculation.
To perform this kind of fixed update, the initialization function need to be modified as follows:
function initPeriodicFunction(fn, runEvery) {
let counter = 0
return function (deltaTime) {
counter = deltaTime
while (counter >= runEvery) {
fn()
counter -= runEvery
}
}
}
Now, the function will be run either once or multiple times depending on how long has elapsed since the last update call.
uj5u.com熱心網友回復:
setInterval(function {
//code that happends every second goes here
}, 1000);
使用 setInterval()。
這將創建一個計時器,并將每 x 秒呼叫一次該函式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/454295.html
標籤:javascript 循环 游戏循环
上一篇:PythonFor回圈不遍歷目錄
下一篇:回圈時自動分配變數
