Jump to content

P2 Physics: Adding Shape Displaces Sprite


Recommended Posts

I was tinkering this morning with a very simple testbed program to try and help myself get a better handle on P2 physics. The only game objects are a player sprite, a flat platform, and a platform with a 45 degree.slope. With the default body shape for the plaforms, I get this:




That works as expected, but of course the rectangular physics shape for the sloped platform doesn't create the intended effect. So I tried clearing the default shape and adding a polygon to reflect the right triangular geometry. I couldn't find anywhere that documented the coordinate system used by P2.Body.addPolygon, so I using the center of the sprite as the origin. Based on the debug outline of the shape, that worked, but it resulted in the sprite itself being displaced down and to the right:




Can anyone tell me what is going on here and how to fix it? I'm pretty sure it has something to do with the new shape moving the body's center of mass, but it seems a little odd for the coordinate system to both be based on the center of mass and capable of changing it.






This is the version of the code with the custom right triangle body. Commenting out the lines in the marked block gives the default (i.e. rectangular shape) behavior.

window.onload = function () {    var game = new Phaser.Game(800, 600, Phaser.AUTO, 'main',        {preload: preload, create: create, update: update});    var cursors;    var text;    var alien;    var oldX, oldY, then;    function preload () {        game.load.image('ground', 'assets/castleMid.png');        game.load.image('slope', 'assets/castleHillLeft.png');        game.load.image('alien', 'assets/p1_stand.png');    }    function create () {        var ground, slope;        game.physics.startSystem(Phaser.Physics.P2JS);        game.physics.p2.gravity.y = 300;        cursors = game.input.keyboard.createCursorKeys();        text = game.add.text(20, 20, 'Placeholder',            {font: '18px Arial', fill: '#0000ff', align: 'center'});        alien = game.add.sprite(100, 100, 'alien');        alien.anchor.setTo(0.5, 0.5);        alien.scale.setTo(0.5, 0.5);        game.physics.p2.enable(alien);        alien.body.setCircle(alien.height/2, 0, 0);        alien.body.fixedRotation = true;        alien.body.debug = true;        ground = game.add.sprite(300, game.world.centerY+35, 'ground');        ground.width = 600;        game.physics.p2.enable(ground);        ground.body.static = true;        ground.body.debug = true;        slope = game.add.sprite(650, game.world.centerY-150, 'slope');        slope.width = 300;        slope.height = 300;        game.physics.p2.enable(slope);        slope.body.static = true;        // BEGIN custom body code        slope.body.clearShapes();        var polygon = [[-150, 150], [150, -150], [150, 150]];        slope.body.addPolygon({}, polygon);        // END custom body code        slope.body.debug = true;        oldX = alien.x;        oldY = alien.y;        then = game.time.now;    }    function update () {        var now = game.time.now;        if (cursors.left.isDown) {            alien.body.velocity.x = -250;        } else if (cursors.right.isDown) {            alien.body.velocity.x = 250;        } else {            alien.body.velocity.x = 0;        }        text.setText('X speed = ' + 1000*(alien.x - oldX) / (now - then + Number.EPSILON));        oldX = alien.x;        oldY = alien.y;        then = now;    }};
Link to comment
Share on other sites

Thanks, but setting the anchor doesn't work; in fact, the anchor is automatically set to (0.5, 0.5) when you enable P2 on a body.


Using loadPolygon with external JSON does work, so at this point I'm pretty sure it's a bug in addPolygon.

Link to comment
Share on other sites

  • 1 year later...

Sorry to bump such an old topic, but this is the first result on Google when you search for this problem, and the solution/workaround is nowhere near obvious:


The reason this is happening isn't a bug.  It's the intended behavior:


addPolygon is literally just an interface to the P2 method fromPolygon, so everything that this method expects you to handle on your own (such as adjusting the center of mass) you still need to do.

But there's good news!


However I've updated loadPolygon to make it more flexible, so you can now pass the actual data in directly rather than pull it from the cache, which should help matters out.

But there's bad news:  The actual format that loadPolygon is expecting is not documented anywhere.  The phaser docs say "see the format of the Lime / Corona Physics Editor export" but googling that doesn't reveal a whole lot.  The physics editor export format is only documented source code form, in the loaders for that format.


Thankfully there's an example of just such a loader readily available and already in the language we need it to be:  The phaser source itself!

(Incidentally, I've found it very useful to be able to navigate the Phaser source.  The API docs are, 90% of the time, sufficient to answer the question I have, but when you need to know exactly what a function is going to do with the data you give it, nothing beats going to the source itself).

So, that second argument to loadPolygon is expected to be an array of dictionaries, each of which has a 'shape' attribute, and that attribute has a flat list of vertices (e.g. [x0, y0, x1, y1, x2, y2]).  The source mentions that it's expecting these to be in counter-clockwise order, but I'm not sure how much that actually matters.


TL;DR: (plus an example)

My code originally:

tile.body.addPolygon({},[[0, 0], [70, 0], [70, 70], [0, 0]]);

(Note this isn't exactly the same as OP's example, my triangle is pointing to the upper-right)

And after converting to loadPolygon:

var obj = [{ "shape": [ 70,70, 0,0, 70,0 ] }];
tile.body.loadPolygon(null, obj);


Link to comment
Share on other sites


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...