How to use polygon collision detection with Arcade Physics Engine in Phaser 3

87 Views Asked by At

I'm currently working on a side scrolling game project using Phaser 3 and the Arcade Physics Engine. However, I've encountered a challenge regarding collision detection with polygon shapes. I'd like to incorporate polygon collision support into my game without having to switch to another physics engine like Matter.js. Is there a way to achieve this within the confines of the Arcade Physics Engine?

I understand that the Arcade Physics Engine primarily supports basic shapes like rectangles and circles for collision detection. However, my game requires more complex polygon shapes for collisions.

I've explored various resources and documentation but haven't found a straightforward solution. Can anyone provide guidance or share insights on how to implement polygon collision detection while still utilizing the Arcade Physics Engine? Any tips, code snippets, or recommended practices would be greatly appreciated.

To reiterate, the goal is to integrate polygon collision detection seamlessly into a Phaser 3 game that relies on the Arcade Physics Engine, avoiding the need for a complete overhaul or migration to a different physics engine.

1

There are 1 best solutions below

8
winner_joiner On

The first thing that comes to mind is to use the processCallback function of the collide or the overlap function. (link to the documentation)
In this callback function you could calculate if an object has collided with an other object, if so return true and than the collideCallback is called, if not return falseand no collision has occured.

With other words you would have to do all the heavy lifting of checking for collision between the objects, polygons or ..., that are passed to the processCallback function.

Apart from this I don't know easy way out-of-the-box to achieve this with arcade physics, but I'm by all means no expert.

And this would still use the "normal" phaser Arcade physics system, since this callback is perfect for more granular/specific collision detection.

Btw.: you could check if there are some plugins, that add this functionality (you could checkout https://phaserplugins.com/, https://rexrainbow.github.io/phaser3-rex-notes/docs/site/plugin-list/ , but you have to be careful some plugins out there are for phaser 2/CE )

Here a very basic example, how this could work:
(I'm not sure, if this is the most efficient way to do it, but it only a demo)

document.body.style = 'margin:0;';
console.clear();

var config = {
    width: 536,
    height: 183,
    physics: {
        default: 'arcade',
        arcade: {            
            gravity:{ y: 20 },
            debug: true
        }
    },
    scene: { create },
}; 

function create () {
    this.add.text(10,10, 'Wait for the collision')
        .setScale(1.5)
        .setOrigin(0)
        .setStyle({fontStyle: 'bold', fontFamily: 'Arial'});

    let graphics  = this.make.graphics();
    graphics.fillStyle(0xffffff);
    graphics.fillRect(0, 0, 10, 10);
    graphics.generateTexture('img', 10, 10);
    
    const points = [ 10,10, 30,0, 50,10, 70,50, 20,40, 0,80 ];

    const object1 = this.add.polygon(170, 10, points, 0x6666ff).setOrigin(0);
    
    this.physics.add.existing( object1 );
    
    const object2 = this.physics.add.staticImage(200, 100, 'img')
    
    this.physics.add.collider(object1, object2, 
      // collideCallback to indicate collision
      (obj1, obj2) => {
          obj2.setTint(0xff0000);
      }, 
      // processCallback decides when it counts as a real collisio 
      (obj1, obj2) => {
          // move helper polyon to the correct position
          let poly = Phaser.Geom.Polygon.Translate(new Phaser.Geom.Polygon(points), obj1.x, obj1.y)

          // check other Points
          let topLeft = obj2.getTopLeft();
          let topRight = obj2.getTopRight();

          // some other Tests
          return Phaser.Geom.Polygon.Contains( poly, topLeft.x, topLeft.y) || Phaser.Geom.Polygon.Contains( poly, topRight.x, topRight.y);
      });
}


new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>