Skip to content
Advertisement

Change collision width and height of individual tiles in a tilemap

I’m working on a game in Phaser 3, and need to be able to change the collision width and height of the wall tiles to something other than the width of the images, but I can’t find anything that doesn’t involve Tiled, which I can’t use as it’s a procedurally generated game.

I found a method to change the size of a tile, and I know how to get and individual tile, but nothing to change the collision size, and the few leads I found involved the differenced between the deprecated createDynamicLayer and createStaticLayer methods. The physics property of the tile object is empty, and doesn’t contain the physics body of the tile, even though I set up collision between the wall tiles and the player (arcade physics). Any suggestions? thanks!

Advertisement

Answer

If you don’t want to use the greate application “Tiled”, the easiest option would be to set the tiles that should have a partial collision to not collide, and than iterate over the Map tiles and place invisible static physics bodies ontop.

It is maybe not very elegant, but it works well, and if you don’t have > 1000 partial tiles on Screen, this should not be a performance issue.

Here is a Demo:

document.body.style = 'margin:0;';

var config = {
    type: Phaser.AUTO,
    width: 536 /8,
    height: 42,
    zoom: 4.5,
    physics: {
        default: 'arcade',
        arcade: {            
            gravity:{ y: 0 },
            debug: false
        }
    },
    scene: {
        create,
        update
    },
    banner: false
}; 

function create () {

    let graphics  = this.make.graphics();
    graphics.fillStyle(0x00ff00);
    graphics.fillRect(8, 0, 8, 8);
    graphics.fillStyle(0xff0000);
    graphics.fillRect(16, 0, 8, 8);
    graphics.fillStyle(0xff0000);
    graphics.fillRect(24, 0, 8, 8);
    graphics.generateTexture('tiles', 8*4, 8);

    var level = [
      [1,1,1,1,1],
      [1,0,0,0,1],
      [1,0,3,0,1],
      [1,0,0,0,1],
      [1,1,1,1,1],
    ]

    // Map for the first level
    var map = this.make.tilemap({ data: level, tileWidth: 8, tileHeight: 8 });
    var tiles = map.addTilesetImage('tiles');
    var layer = map.createLayer(0, tiles, 0, 0);
    layer.setCollision(1);
    
    this.player = this.add.circle(16,16,4, 0xffffff)
      .setDepth(2);
    
    this.physics.add.existing(this.player);
    this.physics.add.collider(layer, this.player);
    
    let partialCollisions = [];
    
    map.forEachTile((tile) => {
      if(tile.index == 3){
        let partialCollition = this.add.circle(tile.pixelX + 4, tile.pixelY + 4, 1)
        this.physics.add.existing(partialCollition, true);
        partialCollisions.push(partialCollition)
      }
    });
    
    this.physics.add.collider(partialCollisions, this.player);
    
    this.keys = this.input.keyboard.createCursorKeys();
}

function update(){
  let speed = 20;
  
  this.player.body.setVelocity(0)
  if(this.keys.up.isDown){
    this.player.body.setVelocityY(-speed)
  }
  
  if(this.keys.down.isDown){
    this.player.body.setVelocityY(speed)
  }
  
  if(this.keys.left.isDown){
    this.player.body.setVelocityX(-speed)
  }
  
  if(this.keys.right.isDown){
    this.player.body.setVelocityX(speed)
  }
}

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