phaser
Version:
A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.
282 lines (224 loc) • 10.4 kB
JavaScript
var IsometricWorldToTileXY = require('../../../src/tilemaps/components/IsometricWorldToTileXY');
var Vector2 = require('../../../src/math/Vector2');
describe('Phaser.Tilemaps.Components.IsometricWorldToTileXY', function ()
{
// Standard isometric tile: 128 wide, 64 tall
// tileWidthHalf = 64, tileHeightHalf = 32
// Origin (tile 0,0) is at worldX=64, worldY=0
// Tile (1,0) is at worldX=128, worldY=32
// Tile (0,1) is at worldX=0, worldY=32
var layer;
beforeEach(function ()
{
layer = {
baseTileWidth: 128,
baseTileHeight: 64,
tilemapLayer: null
};
});
it('should return a Vector2', function ()
{
var result = IsometricWorldToTileXY(64, 0, false, null, null, layer, true);
expect(result).toBeInstanceOf(Vector2);
});
it('should create a new Vector2 when point is null', function ()
{
var result = IsometricWorldToTileXY(64, 0, false, null, null, layer, true);
expect(result).toBeDefined();
expect(typeof result.x).toBe('number');
expect(typeof result.y).toBe('number');
});
it('should update the provided point object instead of creating a new one', function ()
{
var point = new Vector2();
var result = IsometricWorldToTileXY(64, 0, false, point, null, layer, true);
expect(result).toBe(point);
});
it('should convert origin world position (64, 0) to tile (0, 0) with originTop=true', function ()
{
var result = IsometricWorldToTileXY(64, 0, false, null, null, layer, true);
expect(result.x).toBeCloseTo(0);
expect(result.y).toBeCloseTo(0);
});
it('should convert world (128, 32) to tile (1, 0) with originTop=true', function ()
{
var result = IsometricWorldToTileXY(128, 32, false, null, null, layer, true);
expect(result.x).toBeCloseTo(1);
expect(result.y).toBeCloseTo(0);
});
it('should convert world (0, 32) to tile (0, 1) with originTop=true', function ()
{
var result = IsometricWorldToTileXY(0, 32, false, null, null, layer, true);
expect(result.x).toBeCloseTo(0);
expect(result.y).toBeCloseTo(1);
});
it('should convert world (64, 64) to tile (1, 1) with originTop=true', function ()
{
// adjX = 64 - 64 = 0, worldY = 64
// x = 0.5 * (0/64 + 64/32) = 0.5 * (0 + 2) = 1
// y = 0.5 * (-0/64 + 64/32) = 0.5 * (0 + 2) = 1
var result = IsometricWorldToTileXY(64, 64, false, null, null, layer, true);
expect(result.x).toBeCloseTo(1);
expect(result.y).toBeCloseTo(1);
});
it('should convert world (0, 0) to tile (-0.5, 0.5) with originTop=true', function ()
{
var result = IsometricWorldToTileXY(0, 0, false, null, null, layer, true);
expect(result.x).toBeCloseTo(-0.5);
expect(result.y).toBeCloseTo(0.5);
});
it('should snap to floor when snapToFloor is true', function ()
{
// worldX=100, worldY=20 gives non-integer tile coords
var snapped = IsometricWorldToTileXY(100, 20, true, null, null, layer, true);
var unsnapped = IsometricWorldToTileXY(100, 20, false, null, null, layer, true);
expect(snapped.x).toBe(Math.floor(unsnapped.x));
expect(snapped.y).toBe(Math.floor(unsnapped.y));
});
it('should return integer tile coordinates when snapToFloor is true', function ()
{
var result = IsometricWorldToTileXY(100, 20, true, null, null, layer, true);
expect(result.x).toBe(Math.floor(result.x));
expect(result.y).toBe(Math.floor(result.y));
});
it('should not snap to floor when snapToFloor is false', function ()
{
var result = IsometricWorldToTileXY(100, 20, false, null, null, layer, true);
// result should be fractional
expect(result.x % 1 !== 0 || result.y % 1 !== 0).toBe(true);
});
it('should shift worldY down by tileHeight when originTop is false', function ()
{
var resultTop = IsometricWorldToTileXY(64, 64, false, null, null, layer, true);
var resultBase = IsometricWorldToTileXY(64, 64 + 64, false, null, null, layer, false);
expect(resultBase.x).toBeCloseTo(resultTop.x);
expect(resultBase.y).toBeCloseTo(resultTop.y);
});
it('should treat undefined originTop as falsy (same as originTop=false)', function ()
{
// !undefined is true, so it applies the base-face offset like originTop=false
var resultUndefined = IsometricWorldToTileXY(64, 0, false, null, null, layer, undefined);
var resultFalse = IsometricWorldToTileXY(64, 0, false, null, null, layer, false);
expect(resultUndefined.x).toBeCloseTo(resultFalse.x);
expect(resultUndefined.y).toBeCloseTo(resultFalse.y);
});
it('should handle negative world coordinates', function ()
{
var result = IsometricWorldToTileXY(-64, -32, false, null, null, layer, true);
// adjX = -64 - 64 = -128, worldY = -32
// x = 0.5 * (-128/64 + -32/32) = 0.5 * (-2 + -1) = -1.5
// y = 0.5 * (128/64 + -32/32) = 0.5 * (2 + -1) = 0.5
expect(result.x).toBeCloseTo(-1.5);
expect(result.y).toBeCloseTo(0.5);
});
it('should handle large positive world coordinates', function ()
{
var result = IsometricWorldToTileXY(1344, 320, false, null, null, layer, true);
// adjX = 1344 - 64 = 1280, worldY = 320
// x = 0.5 * (1280/64 + 320/32) = 0.5 * (20 + 10) = 15
// y = 0.5 * (-1280/64 + 320/32) = 0.5 * (-20 + 10) = -5
expect(result.x).toBeCloseTo(15);
expect(result.y).toBeCloseTo(-5);
});
it('should handle world (0, 0) with snapToFloor flooring negative fractional values', function ()
{
var result = IsometricWorldToTileXY(0, 0, true, null, null, layer, true);
// unsnapped: x=-0.5, y=0.5 → floor(-0.5)=-1, floor(0.5)=0
expect(result.x).toBe(-1);
expect(result.y).toBe(0);
});
describe('with tilemapLayer', function ()
{
var layerWithTilemapLayer;
var camera;
beforeEach(function ()
{
camera = {
scrollX: 0,
scrollY: 0
};
layerWithTilemapLayer = {
baseTileWidth: 128,
baseTileHeight: 64,
tilemapLayer: {
x: 0,
y: 0,
scaleX: 1,
scaleY: 1,
scrollFactorX: 1,
scrollFactorY: 1,
scene: {
cameras: {
main: camera
}
}
}
};
});
it('should produce the same result as no tilemapLayer when all transforms are identity', function ()
{
var resultPlain = IsometricWorldToTileXY(128, 32, false, null, null, layer, true);
var resultLayer = IsometricWorldToTileXY(128, 32, false, null, camera, layerWithTilemapLayer, true);
expect(resultLayer.x).toBeCloseTo(resultPlain.x);
expect(resultLayer.y).toBeCloseTo(resultPlain.y);
});
it('should use the provided camera when given', function ()
{
var explicitCamera = { scrollX: 0, scrollY: 0 };
var result = IsometricWorldToTileXY(128, 32, false, null, explicitCamera, layerWithTilemapLayer, true);
expect(result.x).toBeCloseTo(1);
expect(result.y).toBeCloseTo(0);
});
it('should fall back to scene main camera when no camera is provided', function ()
{
var result = IsometricWorldToTileXY(128, 32, false, null, null, layerWithTilemapLayer, true);
expect(result.x).toBeCloseTo(1);
expect(result.y).toBeCloseTo(0);
});
it('should offset world position by tilemapLayer x/y', function ()
{
layerWithTilemapLayer.tilemapLayer.x = 64;
layerWithTilemapLayer.tilemapLayer.y = 32;
// worldX adjusted: 192 - (64 + 0) = 128, worldY adjusted: 64 - (32 + 0) = 32
var result = IsometricWorldToTileXY(192, 64, false, null, camera, layerWithTilemapLayer, true);
expect(result.x).toBeCloseTo(1);
expect(result.y).toBeCloseTo(0);
});
it('should account for camera scroll with scrollFactor < 1', function ()
{
camera.scrollX = 100;
camera.scrollY = 50;
layerWithTilemapLayer.tilemapLayer.scrollFactorX = 0.5;
layerWithTilemapLayer.tilemapLayer.scrollFactorY = 0.5;
// worldY adjusted: worldY - (0 + 50 * (1 - 0.5)) = worldY - 25
// worldX adjusted: worldX - (0 + 100 * (1 - 0.5)) = worldX - 50
var worldX = 128 + 50;
var worldY = 32 + 25;
var result = IsometricWorldToTileXY(worldX, worldY, false, null, camera, layerWithTilemapLayer, true);
expect(result.x).toBeCloseTo(1);
expect(result.y).toBeCloseTo(0);
});
it('should scale tile dimensions by tilemapLayer scale', function ()
{
layerWithTilemapLayer.tilemapLayer.scaleX = 2;
layerWithTilemapLayer.tilemapLayer.scaleY = 2;
// tileWidth becomes 256, tileHeight becomes 128
// tileWidthHalf=128, tileHeightHalf=64
// For tile (1,0): adjX=128, worldY=64
// x = 0.5 * (128/128 + 64/64) = 0.5 * (1 + 1) = 1
// y = 0.5 * (-128/128 + 64/64) = 0.5 * (-1 + 1) = 0
var result = IsometricWorldToTileXY(256, 64, false, null, camera, layerWithTilemapLayer, true);
expect(result.x).toBeCloseTo(1);
expect(result.y).toBeCloseTo(0);
});
it('should handle scrollFactorY of 1 (no parallax adjustment)', function ()
{
camera.scrollY = 200;
layerWithTilemapLayer.tilemapLayer.scrollFactorY = 1;
// scrollFactor=1: worldY adjusted by worldY - (0 + 200*(1-1)) = worldY - 0
var result = IsometricWorldToTileXY(128, 32, false, null, camera, layerWithTilemapLayer, true);
expect(result.x).toBeCloseTo(1);
expect(result.y).toBeCloseTo(0);
});
});
});