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.12k stars 7.1k forks source link

WorldToTileX not working for Hex Tilesets (TileY and TileXY works) #5608

Closed stonerich closed 1 year ago

stonerich commented 3 years ago

Version

Description

Tilemaplayer.worldToTileX gives undefined in the code below. Expected behavior is to get the X pos

However, both ..ToTileXY and ... ToTileY works

It seems that the GetWorldToTileXFunction (Phaser.Tilemaps.Components.GetWorldToTileXFunction) is not updated in the same way as GetWorldToTileYFunction is.

var GetWorldToTileXFunction = function (orientation)
{
    if (orientation === CONST.ORTHOGONAL)
    {
        return WorldToTileX;
    }
    else
    {
        return NOOP;
    }
};
var GetWorldToTileYFunction = function (orientation)
{
    if (orientation === CONST.ORTHOGONAL)
    {
        return WorldToTileY;
    }
    else if (orientation === CONST.HEXAGONAL)
    {
        return HexagonalWorldToTileY;
    }
    else if (orientation === CONST.STAGGERED)
    {
        return StaggeredWorldToTileY;
    }
    else
    {
        return NOOP;
    }
};

Example Test Code

this.map = this.make.tilemap({key: 'hexmap'});
this.tiles = this.map.addTilesetImage('Hexagons')
this.layer = this.map.createLayer('Map', this.tiles, 20, 30);

this.layer.setInteractive();
this.layer.on('pointerup', (pointer) => {
    console.log("Pointer Up " , pointer, pointer.downX);        
    let tileX = this.layer.worldToTileX(pointer.downX, true);
    let tileXY = this.layer.worldToTileXY(pointer.downX, pointer.downY, true);
    let tileY = this.layer.worldToTileY(pointer.downY, true);
    console.log("Tile", tileXY, tileX, tileY);

});

Additional Information

druerridge commented 2 years ago

I'm also experiencing this, but while the XY function works better than the X function, but still doesn't work for me (seems to have square detection area?). I wonder why it doesn't work for me? Were you using arcade or matter physics? Would that matter? Here's my explanation/repro on the forums.

https://phaser.discourse.group/t/gettileatworldxy-selects-wrong-tile-on-hex-maps-from-tiled/11643/2

innerexception commented 2 years ago

image

photonstorm commented 1 year ago

I'll patch this so it doesn't error, but it's correct that there is no TileToWorldX (or Y) functions for hex or iso maps because it's impossible to get the correct tile from a single coordinate. You have to provide x and y.

photonstorm commented 1 year ago

Damn, this took a complete rewrite of the function (it was totally wrong!), and it now supports any size hexagon (with varying widths / heights) and layer scales without error. Phew, was quite a bit of learning and optimizing. Video showing it:

https://user-images.githubusercontent.com/164476/203874658-31981148-ae79-41c9-bc28-c8596fd1dd02.mp4

Demo here: https://labs.phaser.io/view.html?src=src/bugs/5608%20hex%20tile.js&v=dev

I've no doubt that the opposite function, HexagonalTileToWorldXY, is completely wrong, but at least this one is working properly now.

gsim commented 1 year ago

Wow it took me a long time to find this. Great work thanks.