Строго говоря, вы можете использовать таймер в вашем loop()
, поэтому он больше связан с игровой логикой и рендерингом. Просто сохраните время начала снаружи, и всякий раз, когда вы перерисовываете, вычисляете разницу:
let start=Date.now();
function reset() {
start=Date.now();
}
let x=0,y=0,dx=0,dy=0;
function loop() {
let seconds=Math.floor((Date.now()-start)/1000);
let minutes=Math.floor(seconds/60);
seconds%=60;
dx+=x<cnv.width/2?1:-1;
dy+=y<cnv.height/2?1:-1;
x+=dx;
y+=dy;
let ctx=cnv.getContext("2d");
ctx.fillStyle="#8080FF";
ctx.beginPath();
ctx.arc(x,y,10,0,Math.PI*2);
ctx.fill();
ctx.stroke();
ctx.clearRect(0,0,30,15);
ctx.strokeText(minutes.toString().padStart(2,"0")+":"+seconds.toString().padStart(2,"0"),0,10);
requestAnimationFrame(loop);
}
loop();
<button onclick="reset()">Reset</button><br>
<canvas id="cnv"></canvas>
Конечно, есть универсальный повторяющийся таймер, setInterval()
. Но тогда у вас могут быть артефакты, если в том же месте нарисовано что-то еще:
let x=0,y=0,dx=0,dy=0;
function loop() {
dx+=x<cnv.width/2?1:-1;
dy+=y<cnv.height/2?1:-1;
x+=dx;
y+=dy;
let ctx=cnv.getContext("2d");
ctx.fillStyle="#8080FF";
ctx.beginPath();
ctx.arc(x,y,10,0,Math.PI*2);
ctx.fill();
ctx.stroke();
requestAnimationFrame(loop);
}
loop();
let start=Date.now();
let counter=0;
function reset() {
start=Date.now();
counter=0;
}
setInterval(()=>{
let ctx=cnv.getContext("2d");
ctx.clearRect(0,0,30,25);
let seconds=Math.floor((Date.now()-start)/1000);
let minutes=Math.floor(seconds/60);
seconds%=60;
ctx.strokeText(minutes.toString().padStart(2,"0")+":"+seconds.toString().padStart(2,"0"),0,10);
counter++;
minutes=Math.floor(counter/60);
seconds=counter%60;
ctx.strokeText(minutes.toString().padStart(2,"0")+":"+seconds.toString().padStart(2,"0"),0,20);
},1000);
function problem() {
let wait=Date.now()+1500;
while(Date.now()<wait);
}
<button onclick="reset()">Reset</button><button onclick="problem()">Problem</button><br>
<canvas id="cnv"></canvas>
Также была добавлена кнопка «Проблема» (нажмите ее пару раз): setInterval()
делает все возможное, но она не пуленепробиваемая, онане компенсирует пропущенные / пропущенные расписания, эта секунда просто не произошла для setInterval()
счетчика (нижний).