Skip to content
Advertisement

How do you prevent player from jumping up walls using the matter physics engine with a tilemap in Phaser 3

Im trying to create a platformer game in phaser 3 using the matter physics engine, currently im trying to create levels using tiled, I have gotten to a point where the player can’t infinitely jump however they can still jump up walls.

Im currently trying to make it so they can only jump if they are colliding with a specific layer called floor.

When I try to use the code below I get an error saying:

Uncaught TypeError: Cannot set properties of null (setting ‘label’)

game.js (create function):

create() {

    //External function to create player
    player(this,'test',300,200,'player')
    pawn.setScale(1.5)
    pawn.setDepth(2)
    pawn.setBounce(0.1)
    pawn.setFriction(0,0,1)
    pawn.setCircle(20)
    pawn.setMass(1)

    this.touchingGround = false;

    this.jumpForce = 0.05

    this.map = this.make.tilemap({key: 'lv3'})
    this.tileset = this.map.addTilesetImage('tiles','tile', 32, 32)

    this.walls = this.map.createLayer('walls', this.tileset)
    this.walls.setCollisionByExclusion(-1, true);

    this.floor = this.map.createLayer('floor', this.tileset)
    this.floor.setCollisionByExclusion(-1, true);

    this.matter.world.convertTilemapLayer(this.walls);
    this.matter.world.convertTilemapLayer(this.floor);



     pawn.body.label = 'player'
     this.floor.body.label = 'floor'

     
    this.matter.world.on("collisionactive", (e,o1, o2) => {
        if(o1.label == 'player' && o2.label == 'floor')
        {
            this.touchingGround = true;
        }
    });

};

Sorry if this is a really easy fix or just doesn’t work and I’m being stupid.

Advertisement

Answer

I’m no matter.js-engine expert, but I assume the error happens on the line this.floor.body.label = 'floor'. A easy solution would be to use the options parameter, from the convertTilemapLayer method (Documentation).

Here a working Demo:
(code based on this phaser.io example )

var config = {
    type: Phaser.AUTO,
    width: 11 * 16, 
    height: 6 * 16,
    zoom: 2,
    pixelArt: true,
    scene: {
        preload: preload,
        create: create
    },
    physics: {
        default: 'matter',
        matter: {
            gravity: {
                y:.3
            },
        }
    },
    banner: false
};

function preload (){
    this.load.image('mario-tiles', 'https://labs.phaser.io/assets/tilemaps/tiles/super-mario.png');
}

function create (){
    var level = [
      [  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 ],
      [  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 ],
      [  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 ],
      [  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 ],
      [  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 ],
      [  0,  0, 14, 14, 14, 14, 14,  0,  0,  0,  0 ],
    ]

    var map = this.make.tilemap({ data: level, tileWidth: 16, tileHeight: 16 });
    var tiles = map.addTilesetImage('mario-tiles');
    var layer = map.createLayer(0, tiles, 0, 0);

    let player = this.add.rectangle(40, 10, 8, 8, 0xffffff)

    layer.setCollision([14]);

    this.matter.add.gameObject(player);
    this.matter.world.convertTilemapLayer(layer, {label:'floor'});
    
    let info = this.add.text(4, 4, 'Waiting for collision', {color:'#ffffff', fontSize:10})
        .setOrigin(0);

    player.body.label = 'player';

    this.matter.world.on("collisionactive", (e, o1, o2) => {
        if(o1.label == 'player' && o2.label == 'floor') {
            info.setText('touching');
        }
    });
}

new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement