Skip to content
Advertisement

Best solution for Phaser 3 pathfinding? [closed]

I have a game and I want to be able to have enemies pathfind to the player across a tilemap, is there a way to do this without programming my own a* algorithm? I’ve seen a couple supposedly still updated libraries for this, but neither of which have worked, they have both been broken with npm and not worked when added as a script.
The libraries I’ve tried are Easystar and Navmesh.
Any suggestions would be great, and while Phaser support would be useful, pathfinding over a 2D array would still be a good solution for me. Thanks!

Advertisement

Answer

I never tried it myself (until now), but https://github.com/mikewesthad/navmesh is a great plugin and is very extensive.

… A JS plugin for fast pathfinding using navigation meshes, with optional wrappers for the Phaser v2 and Phaser v3 game engines. …

p.s.: on this page you can find a list of available plugins for phaser https://phaserplugins.com/

Update:

After testing in on an simple an example it worked fine, just be careful not to miss any steps.

Here the steps needed:

  1. get the latest plugin file phaser-navmesh-plugin.js (currently from https://github.com/mikewesthad/navmesh/releases/tag/2.1.0)

  2. load it from the html file <script src="phaser-navmesh-plugin.js"></script>

  3. configure the plugin, in the config (there are other ways but this is the more convinient)

     var config = {
         ...
         plugins: {
             scene: [
                 {
                     key: "PhaserNavMeshPlugin", // Key to store the plugin class under in cache
                     plugin: PhaserNavMeshPlugin, // Class that constructs plugins
                     mapping: "navMeshPlugin", // Property mapping to use for the scene, e.g. this.navMeshPlugin
                     start: true
                 }
             ]
         },
         scene: {
            ...
         }
     };
    
  4. setup the map and the layer which should collide:

         var map = this.make.tilemap({ data: [[0,1,0],[0,1,0],[0,1,0],[0,0,0]], tileWidth: 8, tileHeight: 8 });
         var tiles = map.addTilesetImage('tile01');
         var layer = map.createLayer(0, tiles, 0, 0);
    
         // this is important, can also be multiple indices
         layer.setCollision(1);
    
  5. create navMesh, pass the map and the created layer with should have to collisions.

         const navMesh = this.navMeshPlugin.buildMeshFromTilemap("mesh", map, [layer]);
    
  6. when needed execute pathfinding (x/y positions are in pixels, not tilesId):

         const path = navMesh.findPath({ x: 4, y: 4 }, { x: 17, y: 4 });
    

You can load the plugin in also in the preload function like this

        this.load.scenePlugin({
            key: 'PhaserNavMeshPlugin',
            url: PhaserNavMeshPlugin,
            sceneKey: 'navMeshPlugin'
        });

Here the demo code with a mini path trace when done:

    var config = {
        scene: {
            preload,
            create,
        }
    };

    var game = new Phaser.Game(config);

    function preload() {
        this.load.image('tile01', 'tile01.png');
        this.load.scenePlugin({
            key: 'PhaserNavMeshPlugin',
            url: PhaserNavMeshPlugin,
            sceneKey: 'navMeshPlugin'
        });
    }

    function create() {
        var map = this.make.tilemap({ data: [[0,1,0],[0,1,0],[0,1,0],[0,0,0]], tileWidth: 8, tileHeight: 8 });
        var tiles = map.addTilesetImage('tile01');
        var layer = map.createLayer(0, tiles, 0, 0);

        layer.setCollision(1);

        const navMesh = this.navMeshPlugin.buildMeshFromTilemap("mesh", map, [layer]);
        const path = navMesh.findPath({ x: 4, y: 4 }, { x: 17, y: 4 });

        if (!path) {
            return;
        }

        let graphics = this.add.graphics();

        graphics.lineStyle(2, 0xff0000, 1);
        graphics.beginPath();
        graphics.moveTo(path[0].x, path[0].y);

        for (let idx = 1; idx < path.length; idx++) {
            graphics.lineTo(path[idx].x, path[idx].y);
        }

        graphics.strokePath();
    }
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement