phaserjs / phaser

Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
https://phaser.io
MIT License
37.22k stars 7.1k forks source link

Phaser not drawing tilesets of multiple sizes correctly as reflected in tiled. #4324

Closed jestarray closed 9 months ago

jestarray commented 5 years ago

image

The tilemap size is 32x32 and the ninja is a 32x64 sprite (imported in tiled as 32x64 also). In tiled I place it on the bottom left but when rendered in phaser, it is an index off.

mappy.json

{ "height":5,
 "infinite":false,
 "layers":[
        {
         "data":[17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17],
         "height":5,
         "id":3,
         "name":"Tile Layer 1",
         "opacity":1,
         "type":"tilelayer",
         "visible":true,
         "width":5,
         "x":0,
         "y":0
        }, 
        {
         "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 0, 0, 0, 0],
         "height":5,
         "id":4,
         "name":"Tile Layer 2",
         "opacity":1,
         "type":"tilelayer",
         "visible":true,
         "width":5,
         "x":0,
         "y":0
        }],
 "nextlayerid":5,
 "nextobjectid":1,
 "orientation":"orthogonal",
 "renderorder":"right-down",
 "tiledversion":"1.2.1",
 "tileheight":32,
 "tilesets":[
        {
         "columns":15,
         "firstgid":1,
         "image":"..\/..\/32x32Tileset_gardenTheme.png",
         "imageheight":480,
         "imagewidth":480,
         "margin":0,
         "name":"32x32Tileset_gardenTheme",
         "spacing":0,
         "tilecount":225,
         "tileheight":32,
         "tilewidth":32
        }, 
        {
         "columns":1,
         "firstgid":226,
         "image":"..\/..\/32x64.png",
         "imageheight":64,
         "imagewidth":32,
         "margin":0,
         "name":"32x64",
         "spacing":0,
         "tilecount":1,
         "tileheight":64,
         "tilewidth":32
        }],
 "tilewidth":32,
 "type":"map",
 "version":1.2,
 "width":5
}

//code

class PlayScene extends Phaser.Scene {
    constructor(){
        super({key: "PlayScene"});
    }
    preload(){
        this.load.image("set32x32", "./32x32Tileset_gardenTheme.png");
        this.load.image("ninja32x64", "./32x64.png");

        this.load.tilemapTiledJSON("mappy", "./mappy.json");

    }
    create(){
        let mappy = this.make.tilemap({
            key: "mappy"
        });

        let tilesets = [
        mappy.addTilesetImage("32x32Tileset_gardenTheme", "set32x32", 32,32),
        mappy.addTilesetImage("32x64", "ninja32x64", 32, 64)
        ]
        mappy.layers.map((value)=>{
            mappy.createStaticLayer(value.name, tilesets).setScale(2);
        })
    }
}
gon777 commented 2 years ago

Hey, I have a workaround in our project to fix this issue, we use Isometric and our tiles are oversized (256 192 compare to tile size 256 128) Note that the position of rotated tile is still a bit off because I have no idea where the anchor point of the tile image is in Tiled. So I chose (0.5, 0.5) as anchor point.

replace pipeline.batchTexture() in Phaser.Tilemaps.TilemapLayer.prototype.renderWebGL with:

pipeline.batchTexture(
            src,  //gameObject
            texture, //texture

            texture.width, texture.height,  //textureWidth, textureHeight

            // x + ((tw + tile.pixelX) * sx), y + ((th + tile.pixelY) * sy), 
             tile.pixelX + 0.5 * tile.baseWidth, tile.pixelY - (tile.height * 0.5 - tile.baseHeight),

            tile.width, tile.height,  //    srcWidth, srcHeight,
            sx, sy,  //scaleX, scaleY,
            tile.rotation, //rotation
            tile.flipX, tile.flipY,  //flipX, flipY,
            scrollFactorX, scrollFactorY,  //scrollFactorX, scrollFactorY,

            // tw, th, //displayOriginX, displayOriginY,
            tile.width * 0.5, tile.height * 0.5,

            frameX, frameY, frameWidth, frameHeight,  //     frameX, frameY, frameWidth, frameHeight,
            tint, tint, tint, tint, false,  //tintTL, tintTR, tintBL, tintBR, tintEffect,
            0, 0,  //uOffset, vOffset,
            camera,  //camera
            null,  //parentTransformMatrix
            true, //skipFlip
            textureUnit  //textureUnit
        );
ciekawy commented 11 months ago

It seems most of the time the tiles should be aligned to bottom-left by default - I think its pretty common to have tiles of variable height where baseline always will be the bottom. Possibly an option to provide top alignment.

Interesting to know how others are dealing with this as it seems very common.

photonstorm commented 9 months ago

Pretty sure this was (finally) resolved via https://github.com/phaserjs/phaser/commit/d855fa73d33e28ee539f15df14de04a0e02ca711