Jump to content

How to create a sprite with two colliders, where only one triggers callback but doesn't trigger colliision.


Kacper Pietrzak
 Share

Recommended Posts

Hi guys!

I'd like to make a computer object in my game,  such that when player approches to the computer,it triggers onEnter callback ( where I can for example show a message on screen to press certain key ) and when player goes away it triggers onLeave callback ( where I can hide the message ).

In order to achieve that I need  two colliders, one for regular collision ( red one ), and the other to detect if the player entered computer's zone ( green one, this is the one that I want to trigger callback ).

    this.computer = this.game.add.sprite( 9 * TILE_WIDTH + COMPUTER_WIDTH / 2, TILE_HEIGHT + COMPUTER_HEIGHT / 2, 'computer' );
    this.game.physics.p2.enable( this.computer );
    this.computer.body.static = true;
    this.computer.body.addRectangle( TILE_WIDTH, TILE_HEIGHT, COMPUTER_WIDTH / 2, COMPUTER_HEIGHT / 2 );

    this.computersCollisionGroup = this.game.physics.p2.createCollisionGroup( this.computer );
    this.computer.body.collides( this.playerCollisionGroup, () => console.log( 'player in range' ) );

    this.player.body.collides( this.computersCollisionGroup );

My question is: How do I turn off physical collision in green collider and what to do to make green collider trigger onEnter and onLeave callbacks ?

screen1-edited.png

Link to comment
Share on other sites

from the docs:

Quote

Checks for collision between two game objects. You can perform Sprite vs. Sprite, Sprite vs. Group, Group vs. Group, Sprite vs. Tilemap Layer or Group vs. Tilemap Layer collisions.
Both the first and second parameter can be arrays of objects, of differing types.
If two arrays are passed, the contents of the first parameter will be tested against all contents of the 2nd parameter.
The objects are also automatically separated. If you don't require separation then use ArcadePhysics.overlap instead.
An optional processCallback can be provided. If given this function will be called when two sprites are found to be colliding. It is called before any separation takes place,
giving you the chance to perform additional checks. If the function returns true then the collision and separation is carried out. If it returns false it is skipped.
The collideCallback is an optional function that is only called if two sprites collide. If a processCallback has been set then it needs to return true for collideCallback to be called.
NOTE: This function is not recursive, and will not test against children of objects passed (i.e. Groups or Tilemaps within other Groups).

so you probably want to use `overlap` instead of `collide`.

As for 'onEnter' and 'onLeave'... just use velocity of the player and position to see wether it is entering or leaving. Do this in the overlapCallback of the `overlap` function.

Link to comment
Share on other sites

Sorry again but this code doesn't log anything for entering the box collider, it logs only for collision with default sprite collider:

    this.computer = this.game.add.sprite( 9 * TILE_WIDTH + COMPUTER_WIDTH / 2, TILE_HEIGHT + COMPUTER_HEIGHT / 2, 'computer' );
    this.game.physics.p2.enable( this.computer );
    this.computer.body.static = true;

    const rectangleSensor = new p2.Box( { width: TILE_WIDTH, height: TILE_HEIGHT } );
    rectangleSensor.sensor = true;

    this.computer.body.addShape( rectangleSensor, COMPUTER_WIDTH / 2, COMPUTER_HEIGHT / 2 );

    this.computersCollisionGroup = this.game.physics.p2.createCollisionGroup( this.computer );
    this.computer.body.collides( this.playerCollisionGroup, () => console.log( 'player in range' ) );

    this.player.body.collides( this.computersCollisionGroup );

What am I doing wrong ?

Link to comment
Share on other sites

Hi, this miniexample based on your code works. For collisions I am not using collides(), but I am adding listener to onBegbinContact signal.

collides works for me only for non-sensor collisions and only if I first enable impact events (call to this.game.physics.p2.setImpactEvents(true);)

Also, be careful when setting rectangle sensor - p2.Box is in p2 units! So, look into my example (size 12 x 12) and look what is on screen. By defaul 20 pixels is 1 unit. To avoid recalculations, use Phaser's add... methods like addCircle, addRectangle, ... it will change pixels o physical units for you.

function create() {

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

    this.player = this.game.add.sprite( 350, 90, 'pic' );
    this.player.width = this.player.height = 50;
    this.player.tint = 0xFF0000;

    this.computer = this.game.add.sprite( 90, 90, 'pic' );
    this.computer.width = this.computer.height = 50;
    this.player.tint = 0x00FF00;
    

    this.game.physics.p2.enable( this.player, true );

    
    this.game.physics.p2.enable( this.computer, true );
    this.computer.body.static = true;

    var rectangleSensor = new p2.Box( { width: 12, height: 12 } );
    rectangleSensor.sensor = true;
    this.computer.body.addShape( rectangleSensor, 0, 0 );


    this.playerCollisionGroup = this.game.physics.p2.createCollisionGroup( this.player );
    this.computersCollisionGroup = this.game.physics.p2.createCollisionGroup( this.computer );


    this.computer.body.collides( this.playerCollisionGroup );
    this.player.body.collides( this.computersCollisionGroup );


    this.player.body.onBeginContact.add(function(body, bodyB, shapeA, shapeB, equation) {console.log("collision!");}, this);


    this.player.body.moveLeft(100);
}
  

 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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