Skip to content

Instantly share code, notes, and snippets.

@veleek
Last active November 27, 2021 22:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save veleek/3be73dc61d5f5a80abc0f72c3ffe390e to your computer and use it in GitHub Desktop.
Save veleek/3be73dc61d5f5a80abc0f72c3ffe390e to your computer and use it in GitHub Desktop.
Phaser Tile/World/Object XY conversions for orthogonal maps.
/**
* 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