schteppe / p2.js

JavaScript 2D physics library
Other
2.64k stars 330 forks source link

Scaling factor #180

Closed Cristy94 closed 8 years ago

Cristy94 commented 9 years ago

Is it possible to change the scaling factor between p2js meters and pixels?

I am using Phaser to create a game and want a sprite that falls from the top of the screen to the bottom to reach it in the same time, at the same velocity, even when the game is scaled for retina displays.

So, when the screen resolution is 800x600 , my sprite would be at the top (600px) and have a width of (60px). When the game resolution is 1600x1200, my sprite would be at the top(1200px) and have twice the width (120px).

Even though, graphically, they look the same (on retina the screen sizes, thus the game size, looks the same), the physics act differently because my sprite falls from a higher distance. When it reaches ground, on the retina display, it will have a higher velocity.

Being able to set a scale factor so that 1P2JS meter = 2x number of pixels would fix this issue. Is this something I can do directly in Phaser? Does P2JS support this?

Thanks!

schteppe commented 9 years ago

Hi! You can set the pixels-to-physics scaling in Phaser. Not sure how it's done in proper Phaser code (I'm not a Phaser pro), but there is a scale parameter in the p2 object: https://github.com/photonstorm/phaser/blob/v2.3.0/src/physics/p2/World.js#L151

photonstorm commented 9 years ago

You can do this in Phaser by passing in a physics configuration object to your Phaser game instance that contains 4 functions: mpx, pxm, mpxi and pxmi. The functions should return the scaled values like this: https://github.com/photonstorm/phaser/blob/master/src/physics/p2/World.js#L1802

Alternatively instead of a conf object, just replace those methods on the World prototype with your own. It's the same end result really - just do it before creating any objects.

Cristy94 commented 9 years ago

Ok, thanks.

I've done something like this:

    var heightScale = gameHeight / 900;
    var _mpx = 20 * heightScale;
    var _pxm = 1/_mpx;
    var physicsConf = {
        mpx: function (v) {
            return v * _mpx;
        },
        mpxi: function (v) {
            return -v * _mpx;
        },
        pxm: function (v) {
            return v * _pxm;
        },
        pxmi: function (v) {
            return -v * _pxm;
        }
    };

The sprites were still dropping different so I thought that gravity might also be somehow scaled.

If I set the gravity value using mpx(value) instead the absolute value, things seem to work as expected.

        game.physics.p2.gravity.y = game.physics.p2.mpx(60);
        game.physics.p2.friction = game.physics.p2.mpx(100);

Why does it work with mpx instead of pxm? Am I doing something wrong? So, the gravity has to be specified in meters? What about friction, does it too? And I guess that other variables, such as damping or restitution are still the same, being in [0,1] interval.

LE: At a closer look, it still doesn't work as expected. Even though the bodies fall the same distance in the same time, the end velocity (velocity when sprite hits the ground) is much larger on larger game height. I'll edit again with actual numbers.

Normal game scale:

Drop time 1131
Drop distance -35.04452133178711
FPS 60
Hit velocity 614.3079997592502

Game scaled x4:

Drop time 1125
Drop distance -35.04452133178711
FPS 60
Hit velocity 2457.2319990370006

So, it seems like even though the time and distance are the same, the velocity is 4 times larger when the game is scaled x4.

LLE: I think the velocity is given in pixels, and I should convert it back to meters for computations.

schteppe commented 8 years ago

I think this is a pure Phaser question and the discussion should continue in that repo. Read more about scaling physics here.