liabru / matter-js

a 2D rigid body physics engine for the web ▲● ■
MIT License
16.36k stars 1.95k forks source link

How to keep consistent bodies speed on different screen resolutions? #1204

Open ProgrammingLife opened 1 year ago

ProgrammingLife commented 1 year ago

I try to keep consistent speed of bodies on different screen resolutions. Now I test two resolutions:

I precalculate ScreenHeight and create an object with a mass: screenHeight / 130.0. So the mass is depends on screen height. Then I apply some horizontal force in a 60-fps loop (each iteration) with applyForce(), calculated as: const forceX = screenHeight / 60000. Gravity of the world I set as: screenHeight / 1080. And I get absolutely different speed on different resolutions. Objects on screen: 844x390 moves 10-20x faster than they move on 1920x1080. Both cases I test on the same device, the same browser, so there's no any problem with different FPS or a performance value.

Why does it happen? How to keep consistent speed? For example, I wanna move my object horizontally by distance: screenHeight * 2.0, spending exactly 1.0 second on different screen resolutions.

I think it should behaive proportionally equals if I set proportionally equal forces, sizes, all those things... Look I've found the same issue here: https://github.com/liabru/matter-js/issues/889 but I change the sizes as well so it doesn't look different from one screen size to another to my mind.

UPD: So, the best approach when working with physics is to use fixed coordinates without using relative values adjusting to current screen resolution? For example, creating a physics world with a size of 1920x1080 and then adjust the graphics to current screen resolution remapping those fixed physics coordinates to current screen resolution each loop step?

But it's very uncomfortable to work when the collider is placed not above the object but in some another place in the world. It's crazy to work with. Or are there any ways to scale the physics to get the similar behaviour on different scales?

ProgrammingLife commented 1 year ago

Tried to use substeps on devices with 30fps:

public update( time: number, dt: number ) {
    this.matter.world.step( dt / 2 );
    this.matter.world.step( dt / 2 );
}

But it's not a solution since it moves very glitchy. Looking for another solution to use Phaser/MatterJS with 30fps.

LexSerest commented 1 year ago

https://github.com/liabru/matter-js/issues/1152#issuecomment-1512045724

maybe this solution will help