Skip "render" if nothing changed on screen

For each requested animation frame (RAF) in Phaser, Phaser calls the "update" method, then the "render" method of each scenes.
The "render" method takes some time (and energy) to perform the rendering.

The fact is we probably don't need to call "render" if nothing changed on the screen (which happens most of the frames in a typical WorkAdventure game).

This commit is therefore overloading the "Game" class of Phaser to add a "dirty" flag.

Scenes can now add a "isDirty()" method. If all displayed scenes are pristine (not dirty), Phaser will skip rendering the frame altogether.

This saves "a lot" of energy, resulting in laptops that are not overheating when using WorkAdventure \o/
This commit is contained in:
David Négrier 2021-04-23 13:29:23 +02:00
parent f9f6abe7b3
commit 0c5e5ef578
5 changed files with 122 additions and 1 deletions

View file

@ -1061,6 +1061,7 @@ ${escapedMessage}
}
createCollisionWithPlayer() {
this.physics.disableUpdate();
//add collision layer
this.Layers.forEach((Layer: Phaser.Tilemaps.TilemapLayer) => {
this.physics.add.collider(this.CurrentPlayer, Layer, (object1: GameObject, object2: GameObject) => {
@ -1186,17 +1187,36 @@ ${escapedMessage}
});
}
private dirty:boolean = true;
/**
* @param time
* @param delta The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
*/
update(time: number, delta: number) : void {
// TODO: add Events.ADDED_TO_SCENE to the scene to track new objects.
// When an object is added, add ANIMATION_UPDATE event on this object (and remove the listener on Events.REMOVE_FROM_SCENE)
// This way, we can set the dirty flag only when an animation is added!!!
this.dirty = false;
mediaManager.setLastUpdateScene();
this.currentTick = time;
if (this.CurrentPlayer.isMoving() === true) {
this.dirty = true;
}
this.CurrentPlayer.moveUser(delta);
if (this.CurrentPlayer.isMoving() === true) {
this.dirty = true;
this.physics.enableUpdate();
} else {
this.physics.disableUpdate();
}
// Let's handle all events
while (this.pendingEvents.length !== 0) {
this.dirty = true;
const event = this.pendingEvents.dequeue();
switch (event.type) {
case "InitUserPositionEvent":
@ -1222,6 +1242,7 @@ ${escapedMessage}
// Let's move all users
const updatedPlayersPositions = this.playersPositionInterpolator.getUpdatedPositions(time);
updatedPlayersPositions.forEach((moveEvent: HasMovedEvent, userId: number) => {
this.dirty = true;
const player: RemotePlayer | undefined = this.MapPlayersByKey.get(userId);
if (player === undefined) {
throw new Error('Cannot find player with ID "' + userId + '"');
@ -1491,4 +1512,8 @@ ${escapedMessage}
message: 'If you want more information, you may contact us at: workadventure@thecodingmachine.com'
});
}
public isDirty(): boolean {
return this.dirty;
}
}