提问人:ThisNameTagPasses 提问时间:7/19/2023 最后编辑:ThisNameTagPasses 更新时间:7/19/2023 访问量:59
如何使循环延迟随每个周期而变化的时间量?
How can I make a loop be delayed by an amount of time that changes with every cycle?
问:
我正在尝试在 javascript 中制作一个游戏循环,其中每 x 次发生一次事件,并且每个循环的时间会变短。
这是我尝试使用的代码:
const begin = document.getElementById("startbtn")
begin.onclick = start;
//Game loop
function start() {
console.log("test");
let i = 1000;
while (i>0) {
loop(i);
i = i - 100;
}
function loop(i){
setTimeout(function(){
console.log("adsafsd");
}, 5 * i);
}
}
但它只是以相同的间隔重复,并在 5 次循环后大约 10 秒内完成。 我想象循环函数中的 setTimeout 会变得更短,因为它需要 i 变量的 5 倍,每个循环减去 100。
答:
4赞
Alexander Nenashev
7/19/2023
#1
您可以使用并包装成一个 promise 来使代码更易于管理:async/await
setTimeout
let game;
const timeout = (delay = 0) => new Promise(resolve => setTimeout(resolve, delay));
const restart = () => stop() + start(game = {running: true});
const stop = () => game && delete game.running;
async function start(game) {
console.log('game started');
let delay = 500; // start delay
while (delay > 0) {
await timeout(delay);
if(!game.running){
break;
}
console.log(`delay ${delay}`);
delay -= 50; // your interval decrement
}
}
button{
background: lightgray;
border:none;
border-radius:50%;
padding: 10px 20px;
cursor:pointer;
}
button:hover{
background:#ddd;
box-shadow: 0 0 10px rgba(0,0,0,.2);
}
<button onclick="restart()">Start</button> <button onclick="stop()">Stop</button>
评论
0赞
Roko C. Buljan
7/19/2023
有时会很好,不是吗?另外 - 最好改用 addEventListener。clearTimeout
begin.onclick
0赞
Alexander Nenashev
7/19/2023
@RokoC.Buljan 添加了
0赞
Alexander Nenashev
7/19/2023
@RokoC.Buljan 没有必要清除超时,只需打破while
1赞
Ryan McDonough
7/19/2023
#2
如果您不想像其他(非常好的)答案那样切换到异步:
当前代码几乎同时创建所有超时,每个超时的延迟都会随着每次迭代而减少 100 毫秒。但是,setTimeout 是异步工作的,因此它不会等待上一个超时完成再设置下一个超时,这意味着所有超时几乎同时设置。因此,它们几乎一起结束,只是彼此之间有轻微的延迟。
您应该在上一个超时完成后设置下一个超时。您可以通过在循环函数中使用递归来实现此目的:
const begin = document.getElementById("startbtn");
begin.onclick = start;
function start() {
console.log("test");
loop(1000);
}
function loop(i) {
setTimeout(function() {
console.log("Looping...");
if (i > 100) {
loop(i - 100);
}
}, 5 * i);
}
1赞
Wanderson Santos
7/19/2023
#3
以您的示例为例:
const begin = document.getElementById("startbtn");
begin.onclick = start;
// Game loop
function start() {
console.log("test");
let delay = 1000;
function loop() {
setTimeout(function () {
console.log("adsafsd");
delay -= 100;
if (delay > 0) {
loop();
}
}, delay);
}
loop();
}
但我认为这个问题的最佳模型是:
const begin = document.getElementById("startbtn");
begin.onclick = start;
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// Game loop
async function start() {
console.log('game started');
for (let delay = 1000; delay > 0; delay -= 100) {
await sleep(delay);
console.log("adsafsd");
}
}
评论