Jump to content

P2 physics, collision groups, and world bounds collision


stvrbbns
 Share

Recommended Posts

Is there a way to suggest new examples?

I've created collision groups using P2 physics such that the Tilemap and the player's ship collide, the player's ship and the panda collide, and the Tilemap and the panda do not collide. However, I had trouble getting either the player's ship or the panda to collide with the world boundary.

My understanding was that:

  • Since I called "layer.resizeWorld()", I must call "game.physics.p2.setBoundsToWorld(true, true, true, true, ???)" to reset the P2 physics' world bounds. [reason: example lines 48-54]
  • Since I called "this.physics.p2.createCollisionGroup()", I must call "game.physics.p2.setBoundsToWorld(true, true, true, true, true)" to reset the P2 physics' world bounds *with/as a collision group*, -or- call "game.physics.p2.updateBoundsCollisionGroup()" to update the world bounds to be their own collision group, so that other collision groups can collide with the world bounds. [reason: example lines 30-32]. Setting the 5th parameter to setBoundsToWorld() to "true", for "If true the Bounds will be set to use its own Collision Group." (source in documentation) makes calling "updateBoundsCollisionGroup()" extraneous.

It seemed like I should be able to call "ship.body.collideWorldBounds = true" somewhere and have it work (or maybe not? ...), but it didn't, and leaving it out entirely didn't work either. Finally I found [this comment] which clarified the order which functions had to be called in. I now have the below example working with:

  • tilemap and ship collide
  • tilemap and panda do not collide
  • world boundary and ship do not collide
  • world boundary and panda collide
  • ship and panda collide

CODE:

var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update, render: render });

function preload() {

    game.load.tilemap('map', 'assets/tilemaps/maps/collision_test.json', null, Phaser.Tilemap.TILED_JSON);
    game.load.image('ground_1x1', 'assets/tilemaps/tiles/ground_1x1.png');
    game.load.image('walls_1x2', 'assets/tilemaps/tiles/walls_1x2.png');
    game.load.image('tiles2', 'assets/tilemaps/tiles/tiles2.png');
    game.load.image('ship', 'assets/sprites/thrust_ship2.png');
    game.load.image('panda', 'assets/sprites/spinObj_01.png');

}

var ship;
var map;
var layer;
var cursors;
var panda;
var tilesCollisionGroup;
var shipCollisionGroup;
var pandaCollisionGroup;

function create() {

    game.stage.backgroundColor = '#2d2d2d';

    game.physics.startSystem(Phaser.Physics.P2JS);

    map = game.add.tilemap('map');

    map.addTilesetImage('ground_1x1');
    map.addTilesetImage('walls_1x2');
    map.addTilesetImage('tiles2');
    
    layer = map.createLayer('Tile Layer 1');
    layer.resizeWorld();

    //  Set the tiles for collision.
    //  Do this BEFORE generating the p2 bodies below.
    map.setCollisionBetween(1, 12);

    //  Convert the tilemap layer into bodies. Only tiles that collide (see above) are created.
    //  This call returns an array of body objects which you can perform addition actions on if
    //  required. There is also a parameter to control optimising the map build.
    game.physics.p2.convertTilemap(map, layer);

    //  By default the ship will collide with the World bounds,
    //  however because you have changed the size of the world (via layer.resizeWorld) to match the tilemap
    //  you need to rebuild the physics world boundary as well. The following
    //  line does that. The first 4 parameters control if you need a boundary on the left, right, top and bottom of your world.
    //  The final parameter controls if the boundary should use its own collision group or not. In this case we do require
    //  that because custom collision groups have been set up for the ship and panda.
    game.physics.p2.setBoundsToWorld(true, true, true, true, true);

    // collision groups must be created after world boundaries have been finalized/fixed for the groups to collide with the boundaries
    tilesCollisionGroup = this.physics.p2.createCollisionGroup();
    shipCollisionGroup = this.physics.p2.createCollisionGroup();
    pandaCollisionGroup = this.physics.p2.createCollisionGroup();

    for (var bodyIndex = 0; bodyIndex < map.layer.bodies.length; bodyIndex++) {
        var tileBody = map.layer.bodies[bodyIndex];
        tileBody.setCollisionGroup(tilesCollisionGroup);
        tileBody.collides([shipCollisionGroup]);
    }

    ship = game.add.sprite(400, 200, 'ship');
    game.physics.p2.enable(ship);
    ship.body.setCollisionGroup(shipCollisionGroup);
    ship.body.collides([tilesCollisionGroup, pandaCollisionGroup]);
    //  Even after the world boundary is set-up you can still toggle if the ship collides or not with this:
    ship.body.collideWorldBounds = false;

    panda = game.add.sprite(200, 200, 'panda');
    game.physics.p2.enable(panda);
    panda.body.setRectangle(40, 40);
    panda.body.setCollisionGroup(pandaCollisionGroup);
    panda.body.collides([pandaCollisionGroup, shipCollisionGroup]);

    game.camera.follow(ship);

    cursors = game.input.keyboard.createCursorKeys();
}

function update() {

    if (cursors.left.isDown)
    {
        ship.body.rotateLeft(100);
    }
    else if (cursors.right.isDown)
    {
        ship.body.rotateRight(100);
    }
    else
    {
        ship.body.setZeroRotation();
    }

    if (cursors.up.isDown)
    {
        ship.body.thrust(400);
    }
    else if (cursors.down.isDown)
    {
        ship.body.reverse(400);
    }

}

function render() {

}

Lesson: These functions MUST be called in order:

  1. map.createLayer()
  2. layer.resizeWorld()
  3. game.physics.p2.setBoundsToWorld()
  4. game.physics.p2.createCollisionGroup()

 

Link to comment
Share on other sites

  • 3 weeks later...
 Share

  • Recently Browsing   0 members

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