Last active
November 27, 2021 22:47
-
-
Save veleek/3be73dc61d5f5a80abc0f72c3ffe390e to your computer and use it in GitHub Desktop.
Phaser Tile/World/Object XY conversions for orthogonal maps.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Get the world XY position of a tile that takes into account the offset of the container with this map in it. | |
* This returns the origin of the tile sprite which is 64x64 whereas the actual tilemap tile size is only 64x32, so | |
* the world position is actually outside of the individual tile bounds. The tiles overlap in the isometric grid | |
* though so we only really care about the specific point. | |
* @param tileX | |
* @param tileY | |
*/ | |
public tileToWorldXY(tileX: number, tileY: number): Phaser.Math.Vector2 { | |
const worldPos = this.map.tileToWorldXY(tileX, tileY, null, null, "floor"); | |
// TODO: Do we need to worry about the map offset anymore since we're not a container? | |
//worldPos.add(new Phaser.Math.Vector2(this.x, this.y)); | |
return worldPos; | |
} | |
/** | |
* Get the tile associated with a world XY position. See above for a bit of info about where the world position is | |
* located with respect to the tile. The tile position is floored so anything 1 pixel to the left or above a tiles | |
* world position will return another tile. | |
* | |
* [World(63,127) => Tile(4,2)] | | |
* \ | | |
* . | [World(64,128) => Tile(5,3)] | |
* ________________________________|/_______________________________ | |
* | | |
* | . | |
* | \ | |
* | [World(65,129) => Tile(5,3)] | |
*/ | |
public worldToTileXY(worldX: number, worldY: number, worldOffset?: Phaser.Math.Vector2): Phaser.Math.Vector2 { | |
// The world's 0,0 position is the top left corner of the top left tile in the map (which for isometric is in the | |
// middle of the map). Our world positions generally refer to the center of the tile so we offset the given | |
// position back to the 0,0 before converting it into a tile position unless an explicit override is provided. | |
if (worldOffset === undefined) { | |
// These were defined in the class initializer where this was used. | |
//this.tilesetName = tilesetName; | |
//this.tileset = this.map.addTilesetImage(tilesetName); | |
//this.tilesetOffset = new Phaser.Math.Vector2(this.tileset.tileWidth * 0.5, this.tileset.tileHeight * 0.5); | |
worldOffset = this.tilesetOffset; | |
} | |
if (worldOffset) { | |
worldX -= worldOffset.x; | |
worldY -= worldOffset.y; | |
} | |
return this.map.worldToTileXY(worldX, worldY, true, null, null, "floor"); | |
} | |
/** | |
* Converts a tile position into a depth | |
* @param tileX | |
* @param tileY | |
* @returns | |
*/ | |
public tileToDepth(tileX: number, tileY: number) { | |
return tileX + tileY; | |
} | |
/** | |
* Converts an orthogonal world position into a tile position. | |
* Tiled provides the orthogonal position for game objects. So for example, if you increase the X position, you are | |
* moving to the right in the orthogonal grid, but you're moving the the right and down in the isometric grid. So in | |
* order to convert this into a tile position, we need to use some different logic. | |
* @param worldX The x coordinate to be converted, in pixels, not tiles. | |
* @param worldY The y coordinate to be converted, in pixels, not tiles. | |
*/ | |
public orthogonalToTileXY(worldX: number, worldY: number): Phaser.Math.Vector2 { | |
return Phaser.Tilemaps.Components.WorldToTileXY( | |
worldX, | |
worldY, | |
/* snapToFloor */ false, | |
null, | |
null, | |
this.conversionLayerData | |
); | |
} | |
/** | |
* Converts an orthogonal world position into an isometric world position. | |
* | |
* @param worldX The x coordinate to be converted, in orthogonal pixels, not tiles. | |
* @param worldY The y coordinate to be converted, in orthogonal pixels, not tiles. | |
*/ | |
public orthogonalToWorldXY(worldX: number, worldY: number): Phaser.Math.Vector2 { | |
const tile = this.orthogonalToTileXY(worldX, worldY); | |
return this.tileToWorldXY(tile.x, tile.y); | |
} | |
/** | |
* Converts a Tiled "object" position into an tile position. | |
* @param objX The x coordinate to be converted, in pixels, not tiles. | |
* @param objY The y coordinate to be converted, in pixels, not tiles. | |
* @param objectOffset An offset to apply to the object position before conversion. Different types of Tiled objects | |
* have different origins that we need to take into account. | |
* * Tile objects use an origin of 1,0.5 it seems (bottom middle) so if the tile object has a position of 0,0 then the | |
* bottom middle of the tile will be at 0,0 on the map (as seen in the tiled editor). | |
* * Non-tile objects (e.g. shapes, text) use an origin of 0,0 so they should not be offset prior to conversion. | |
* FYI: different non-tile objects can be differentiated by aditional child properties like 'ellipse: true'. Tile | |
* objects can be identified by their 'gid' property which is the id of the tile they are based on. | |
*/ | |
public objectToTileXY(objX: number, objY: number, objectOffset?: Phaser.Math.Vector2): Phaser.Math.Vector2 { | |
if (objectOffset === undefined) { | |
objectOffset = this.tilesetOffset; | |
} else if (objectOffset === null) { | |
objectOffset = Phaser.Math.Vector2.ZERO; | |
} | |
return this.orthogonalToTileXY(objX - objectOffset.x, objY - objectOffset.y); | |
} | |
/** | |
* Converts a Tiled "object" position into an isometric world position. | |
* @param objX The x coordinate to be converted, in pixels, not tiles. | |
* @param objY The y coordinate to be converted, in pixels, not tiles. | |
* @param worldOffset An offset to apply to the world position after conversion. | |
* If undefined, offset the result to the middle of the tileset tile. If null, ignore the offset. | |
* @param objectOffset An offset to apply to the object position before conversion. See objectToTileXY for more info. | |
*/ | |
public objectToWorldXY( | |
objX: number, | |
objY: number, | |
worldOffset?: Phaser.Math.Vector2, | |
objectOffset?: Phaser.Math.Vector2 | |
): Phaser.Math.Vector2 { | |
const tile = this.objectToTileXY(objX, objY, objectOffset); | |
const world = this.tileToWorldXY(tile.x, tile.y); | |
// The world's 0,0 position is the top left corner of the top left tile in the map (which for isometric is in the | |
// middle of the map). So, in order to get the actual corner of the isometric map tile we want the center of the | |
// tileset image, so we add back in an offset to get us to the middle of the tileset image. | |
if (worldOffset === undefined) { | |
worldOffset = this.tilesetOffset; | |
} | |
if (worldOffset) { | |
world.add(worldOffset); | |
} | |
return world; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment