Player pushes objects through walls

I have a crate object and I don’t set crate.body.immovable = true, so the player can push it. When it reaches a wall, it goes through. I put the following in the update (only trying from the left side for now)

if (crate.body.touching.left || crate.body.blocked.left){
  crate.setVelocityX(0)
  crate.body.immovable = true}

It still passes through the wall. How should I check whether the crate has touched a wall?

Add a collider for wall/crate?

The wall is made of tiles from the world layer. It already has a collision

With what? Not with the crate it seems. You should be able to add as many colliders as you want.

They have a collider because otherwise the crate would fall through the floor. The floor and wall are the same thing, both made from tiles in the map.

Interesting. Can you create an example?

You could try increasing TILE_BIAS, but I can’t imagine you pushing that hard :slight_smile:

Perhaps this, not tried:

scene.physics.add.collider(player, crate, undefined, (player, crate) =>
{
  if (crate.body.touching.left || crate.body.blocked.left) {
    crate.body.immovable = true;
    return true;
  }
}, scene)

That was a good suggestion, but it still goes thru the wall

You should set crate.body.immovable = true in the callback for this collider.

If I do that, it can’t move at all because it’s always touching the floor.

At this point, my idea is to just manually plug in a property on the crate with an x coordinate it can’t move past.

This makes no sense. You’re trying to work around a problem that shouldn’t be there. You should not be able to push through the tile. Focus on that.
I notice the floor and wall are different tiles and sizes, so different layers?

Only for blocked.left, blocked.right.

Well, maybe you should check block.body.blocked in the player–block collider callback instead. Must run after the block–tiles collider.

That was one of the first things I tried. I logged crate.body.blocked.left in the update and it’s always false, even as it passes thru the wall.

I just tested with phaser 3 sandbox, seems to works with nothing special.

Here the code, based on this code: Phaser 3 Examples

var config = {
    type: Phaser.WEBGL,
    width: 800,
    height: 576,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    pixelArt: true,
    physics: {
        default: 'arcade',
        arcade: { gravity: { y: 300 } }
    },
    scene: {
        preload: preload,
        create: create,
        update: update
    }
};

var game = new Phaser.Game(config);
var map;
var cursors;
var player;
var crate;
var groundLayer;

function preload ()
{
    this.load.image('ground_1x1', 'assets/tilemaps/tiles/ground_1x1.png');
    this.load.spritesheet('coin', 'assets/sprites/coin.png', { frameWidth: 32, frameHeight: 32 });
    this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/tile-collision-test.json');
    this.load.image('player', 'assets/sprites/phaser-dude.png');
}

function create ()
{
    map = this.make.tilemap({ key: 'map' });
    var groundTiles = map.addTilesetImage('ground_1x1');

    map.createLayer('Background Layer', groundTiles, 0, 0);
    groundLayer = map.createLayer('Ground Layer', groundTiles, 0, 0);

    groundLayer.setCollisionBetween(1, 25);

    player = this.physics.add.sprite(120, 520, 'player');

    crate = this.physics.add.sprite(80, 520, 'coin')

    this.physics.add.collider(player, groundLayer);
    this.physics.add.collider(crate, groundLayer);
    this.physics.add.collider(player, crate);

    this.cameras.main.setBounds(0, 0, map.widthInPixels, map.heightInPixels);
    this.cameras.main.startFollow(player);

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

function update (time, delta)
{
    // Horizontal movement
    player.body.setVelocityX(0);

    if (cursors.left.isDown)
    {
        player.body.setVelocityX(-200);
    }
    else if (cursors.right.isDown)
    {
        player.body.setVelocityX(200);
    }

    // Jumping
    if ((cursors.space.isDown || cursors.up.isDown) && player.body.onFloor())
    {
        player.body.setVelocityY(-300);
    }
}