Weird behaviour with RequestAnimationFrame

Hi everybody, I’m remaking a 1984 arcade kung-fu game with JS. When the time is over I set a variable to false to stop calling RequestAnimationFrame(timestamp). When the death animation is complete, I set the same variable to true to resume the game loop. Here the weird thing happens: the horizontal scrolling is incredibly faster and the time countdown either so that the death animation happens again before the time expire and goes into a loop. Did anyone experienced the same? Even with the developer console I couldn’t find out the cause. I called RequestAnimationFrame with 0 as an argument as for the first time but It didn’t work either. I can upload the code somewhere if anyone is willing to help. The game is Kung Fu Master.

Many thanks
GiuTor

Can you share your code? The argument to the raF function is a timestamp. The same value provided can cause your code to run much faster!

The best way to stop a raF call is to use cancelAnimationFrame :grinning:

1 Like

Thanks for replying. Yep I used CancelAnimationFrame too but it does the same sadly. Please download the zip file below. Wait for the time to reach 0, I set it to 350. Arrow keys move Thomas, CTRL to kick, ALT to punch. Thanks.

https://drive.google.com/file/d/1O2sxR0DWI1tzD0nYhHRMvWQZBIJXrD_P/view?usp=sharing

I am seeing that same behavior! This is strange. What is the behavior you are expecting? When the timer ends, the game stops for a bit and then restarts at the 350 second mark and counts down normally?

The second countdown should run at the same pace of the first one. Instead it goes to zero in a few seconds without respecting the 1 second step. Also the left and right scrolling is abnormal respect to the first game run. Did I find a bug in the way Chrome handle RaF?

I’m making slow progress, but I was able to address the counter speed issue:

	#id = undefined;

	decreaseTimer()
	{
		if (this.id !== undefined) {
			clearInterval(this.id);
		}

		this.id = setInterval( () => 
		{
			this.time--
			this.timediv.innerHTML = this.time
			if (this.time <= 0) {
				console.log("Cleared timer!");
				clearInterval(this.id)
			}
		}, 1000 / 20)
	}

I declare our id variable as a private variable, and that ensures clearInterval works appropriately. This still causes the game itself to be double in speed. I wonder if there is something extra you need to do as part of the timestamp / elapsed time.

I applied the fix thank you for the time spent in this project of mine. It works but the downside is that the time keeps running and goes negative before the game restart. I guess I have to call RaF without timestamp and address the rersulting excessive frame speed animation differently. Thank you again.

I have historically found that mixing setIntervals and requestAnimationFrame calls requires a lot more care. For what you are trying to do, I would probably have a requestAnimationFrame call that runs 24/7. All activities such as your countdowns and game loop would be powered by this single requestAnimationFrame call. Inside it, you’ll have conditionals and counters (a count value of 60 is approximately one second) to determine when some code should run and when some code should start.

The rearchitecting to do this may be a fair amount of work, but it may simplify your code greatly in the long run.

How do you explain it works at the first countdown?