Different game speed depending on monitor refresh rate

I’m working on a grid based snake game and I’ve put the movement updates in the update() event.
similar to this game.

The gamelogic boils down to something like this (simplified for the example):

update () {
	// move down one pixel
	this._player.y++;

	// move left one pixel
	this._fox[0].x--;

	// after each tile move, check eat apple, move fox etc.
	this._tilestep++;
	if (this._tilestep > 32) {
		// check game logic
	}
}

This all works fine, except I’ve recently found out that this is can result in different speeds on different devices.

The Phaser update() event is aligned with the requestAnimationFrame, so it’s synchronized with the frame rate of the monitor. On most computers and tablets it’s 60 FPS, however certain graphics cards run at 120 or 144 FPS and some tablet browers seem to run at 30 FPS. So this will make the snake and enemies move either too fast or too slow.

The player and the enemies have to move at the same speed, so for example one tile per 500 ms, or per 300 ms on a later level to move faster. I was looking at tween for each move but that makes it difficult to coordinate. You’d have to use tween.onComplete on each individual move, but the game logic only has to be checked after all the moves are completed, not each individual move.

The game doesn’t use physics, and simply updating everything in one function works really well for the rest of the game logic, except for the speed issue.

What would be the best way to do this? Does anyone have some tips?

time = now();
delta = time - previousTime;
previousTime = time;
fps = 1000/delta;

increment = 60/fps;

Now use increment instead of ++, e.g… y += increment.

2 Likes

Hi,
Can you try this?

  this.physics.world.setFPS(60);

Seems to force the update loop but doesn’t affect the rendering fps
https://photonstorm.github.io/phaser3-docs/Phaser.Physics.Arcade.World.html#setFPS__anchor

1 Like

@BlunT76 @Milton thanks for the replies :+1: I’m not using physics and enabling it just for this is not very cpu efficient I think. So I was looking into the idea of using delta, and just realised that scene.update() comes with two parameters time, delta by default, see docs.

So I’ve changes my code to something like this:

update: function(time, delta) {
	// at 60FPS value of delta will be around 16.666
	console.log("update -- time=" + time + " delta=" + delta);
	
	// pixel steps 0..2..4..6..8../..32 in fixed time of 1/60 sec per step
	var f = (delta / (1000 / 60)); // 1000 ms / 60fps
	this._increment = this._increment + (2 * f); // 2 pixels, adjusted for time delta

	// increment of 32 pixels completed, move snake and fox one tile
	if (this._increment > 32) {
		this._increment = this._increment - 32;
		this.moveSnakeAndFoxes();
	};
	// use `this._increment` to animate sprites positions
	//etc.

The game should now run at the same speed regardless of the monitor frames-per-second. So if it runs on for example 144fps then the value of delta will become around 6.944 and f will become proportionally lower.

My laptop browser always runs at 60FPS, so I will have to test it on different devices, but it seems to work.

2 Likes

hm, i never actually considered, maybe enough reason for a setting in the game config itself (optional ofcourse) … mister Davey ? :stuck_out_tongue: or maybe that’s already inthere, the thing has gotten so complex it just keeps popping up new stuff every time i look at it.
I’m not much of a pro, something like euhm, in most games, AAA and other you get this screen at config where you have to “adjust slider so the middle bit is barely visible” b/c every monitor/card config is somewhat different and they can’t buy it (not even microsoft/obsidian) so maybe something like that can be worked out regarding to “unit motion” or whatever newtonian distance over time sh-tuff (as you can read i am not a pro heh) , maybe one of the elder gods who live on phaser discord could manage that before breakfast, some relative factoring that can be included and put it on the examples list page
or something … something something ( :stuck_out_tongue: thats me <- chaos)

Remember

distance = speed * time

so

function update (time, deltaTime) {
  // `speed` in px/ms
  sprite.x += speed * deltaTime;
}

or

function update (time, deltaTime) {
  // `speed` in px/s
  sprite.x += speed * 0.001 * deltaTime;
}

If you were doing, for example,

function update () {
  sprite.x += 2;
}

assuming the game ran at about 60fps, 2px per update is 120px per second.

function update (time, deltaTime) {
  sprite.x += 120 * 0.001 * deltaTime;
}
3 Likes