Search code examples
javascriptphaser-frameworktiledphaserjstilesets

My tileset collision if offset by 1 Phaser JS


I'm making a top-down game in Phaser and am using Tiled for the tilemap. I set some of the blocks to collide with the player but only does 1 block down and to the right.

Picture of where the collision should be and where it actually is

The player should be colliding with the orange highlighted area but is instead stopping at the purple highlighted area.

Here is my tilemap, collision, player, and collision debugger code:

  const map = this.make.tilemap({key: 'map'});
  const tileset = map.addTilesetImage('RPG Nature Tileset', 'tiles')
  const floor = map.createStaticLayer('Tile Layer 1', tileset, 0, 0)
  const collision = map.createStaticLayer('Tile Layer 2', tileset, 0, 0)

  collision.setCollisionByProperty({collides: true});

  player = this.physics.add.sprite(2048, 2048, "player").setScale(0.4); //The size of the map is 4096px x 4096px which i might make smaller later
  this.physics.add.collider(player, collision);

  const debugGraphics = this.add.graphics().setAlpha(0.75);
  collision.renderDebug(debugGraphics, {
    tileColor: null, // Color of non-colliding tiles
    collidingTileColor: new Phaser.Display.Color(243, 134, 48, 255), // Color of colliding tiles
    faceColor: new Phaser.Display.Color(40, 39, 37, 255) // Color of colliding face edges
  });

Solution

  • Without seeting the real code and dimensions of the assets I just can guess, that the problem has to do with the sprite. It is bigger than you think, so the hitbox is also bigger.

    Turn on the debug information to check this (in the config debug: true). If this is the issue fix the image for the sprite, or you can fix the hitbox with the method setSize(width, height).

    document.body.style = 'margin:0;';
    
    var config = {
        width: 536,
        height: 183,
        physics: {
            default: 'arcade',
            arcade: {
                // turn on the debugging information
                debug: true,
            }
        },
        scene: { create },
    }; 
    
    function create () {
        this.add.text(50, 10, 'Normal')
            .setScale(1.5)
            .setOrigin(.5, 0)
            .setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
            
        this.add.text(250, 10, 'Set Size')
            .setScale(1.5)
            .setOrigin(.5, 0)
            .setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
            
        this.add.text(450, 10, 'add Offset')
            .setScale(1.5)
            .setOrigin(.5, 0)
            .setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
    
        // create image with transparent offset
        let graphics  = this.make.graphics();
        graphics.fillStyle(0xffffff);
        graphics.fillRect(10, 10, 10, 10);
        graphics.generateTexture('img', 20, 20);
        
        this.physics.add.image(50, 90, 'img');
        
        this.physics.add.image(250, 90, 'img')
            .setSize(10, 10);
        
        this.physics.add.image(450, 90, 'img')
            .setSize(10, 10)
            .setOffset(10, 10);
    }
    
    new Phaser.Game(config);
    <script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>