UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

499 lines (409 loc) 15.1 kB
var IsometricCullTiles = require('../../../src/tilemaps/components/IsometricCullTiles'); /** * Build a minimal tile object. */ function makeTile (index, visible, alpha) { return { index: index !== undefined ? index : 1, visible: visible !== undefined ? visible : true, alpha: alpha !== undefined ? alpha : 1 }; } /** * Build a minimal layer with skipCull=true (bypasses CheckIsoBounds). */ function makeLayer (mapData, width, height, skipCull) { return { data: mapData, width: width, height: height, tileWidth: 64, tileHeight: 32, tilemapLayer: { skipCull: skipCull !== undefined ? skipCull : true, tilesDrawn: 0, tilesTotal: 0 } }; } /** * Build a layer where CheckIsoBounds will return true for all tiles — * uses a giant camera worldView and a tileToWorldXY that returns the tile * coords scaled to pixels. */ function makeLayerWithCull (mapData, width, height) { return { data: mapData, width: width, height: height, tileWidth: 64, tileHeight: 32, tilemapLayer: { skipCull: false, tilesDrawn: 0, tilesTotal: 0, cullPaddingX: 0, cullPaddingY: 0, scaleX: 1, scaleY: 1, tilemap: { tileToWorldXY: function (tileX, tileY, point) { point.x = tileX * 64; point.y = tileY * 32; return point; } } } }; } /** * A camera worldView that encompasses all tile positions in a small map. * With 0 cullPadding, a tile at (0,0) maps to world (0,0). * The condition checks: pos.x > camX + scaleX*tileWidth*(-0-0.5) * => 0 > camX - 32 => camX < 32 => use camX=-100 * etc. A large worldView (-10000 to 10000) covers everything. */ function makeCamera () { return { worldView: { x: -10000, right: 10000, y: -10000, bottom: 10000 } }; } /** * A camera whose worldView is far away so every tile is outside bounds. */ function makeCameraOutOfRange () { return { worldView: { x: 999999, right: 1000000, y: 999999, bottom: 1000000 } }; } describe('Phaser.Tilemaps.Components.IsometricCullTiles', function () { describe('return value and output array', function () { it('should return the outputArray', function () { var layer = makeLayer([[makeTile()]], 1, 1); var camera = makeCamera(); var output = []; var result = IsometricCullTiles(layer, camera, output, 0); expect(result).toBe(output); }); it('should return an array when no outputArray is provided', function () { var layer = makeLayer([[makeTile()]], 1, 1); var camera = makeCamera(); var result = IsometricCullTiles(layer, camera, undefined, 0); expect(Array.isArray(result)).toBe(true); }); it('should clear the outputArray before filling it', function () { var layer = makeLayer([[null]], 1, 1); var camera = makeCamera(); var output = [{ stale: true }, { stale: true }]; IsometricCullTiles(layer, camera, output, 0); expect(output.length).toBe(0); }); it('should use renderOrder 0 by default', function () { var t00 = makeTile(); var t01 = makeTile(); var layer = makeLayer([[t00, t01]], 2, 1); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output); expect(output[0]).toBe(t00); expect(output[1]).toBe(t01); }); }); describe('tile filtering', function () { it('should skip null tiles', function () { var layer = makeLayer([[null]], 1, 1); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output, 0); expect(output.length).toBe(0); }); it('should skip tiles with index -1', function () { var layer = makeLayer([[makeTile(-1)]], 1, 1); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output, 0); expect(output.length).toBe(0); }); it('should skip tiles where visible is false', function () { var layer = makeLayer([[makeTile(1, false)]], 1, 1); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output, 0); expect(output.length).toBe(0); }); it('should skip tiles where alpha is 0', function () { var layer = makeLayer([[makeTile(1, true, 0)]], 1, 1); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output, 0); expect(output.length).toBe(0); }); it('should include tiles with valid index, visible true, and non-zero alpha', function () { var tile = makeTile(1, true, 1); var layer = makeLayer([[tile]], 1, 1); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output, 0); expect(output.length).toBe(1); expect(output[0]).toBe(tile); }); it('should include tiles with partial alpha (non-zero)', function () { var tile = makeTile(1, true, 0.5); var layer = makeLayer([[tile]], 1, 1); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output, 0); expect(output.length).toBe(1); }); it('should include only valid tiles among a mix', function () { var good = makeTile(1, true, 1); var badIndex = makeTile(-1); var badVisible = makeTile(1, false); var badAlpha = makeTile(1, true, 0); var layer = makeLayer([[good, badIndex, badVisible, badAlpha]], 4, 1); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output, 0); expect(output.length).toBe(1); expect(output[0]).toBe(good); }); }); describe('cull behaviour (skipCull = true)', function () { it('should include all valid tiles when skipCull is true regardless of position', function () { var t0 = makeTile(); var t1 = makeTile(); var layer = makeLayer([[t0, t1]], 2, 1, true); var camera = makeCameraOutOfRange(); var output = []; IsometricCullTiles(layer, camera, output, 0); expect(output.length).toBe(2); }); }); describe('cull behaviour (skipCull = false)', function () { it('should include tiles that are within camera bounds', function () { var tile = makeTile(); var layer = makeLayerWithCull([[tile]], 1, 1); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output, 0); expect(output.length).toBe(1); }); it('should exclude tiles that are outside camera bounds', function () { var tile = makeTile(); var layer = makeLayerWithCull([[tile]], 1, 1); var camera = makeCameraOutOfRange(); var output = []; IsometricCullTiles(layer, camera, output, 0); expect(output.length).toBe(0); }); it('should apply culling per tile independently', function () { // tile at (0,0) maps to world (0,0). // The x check: pos.x > camX + scaleX*tileWidth*(-0-0.5) // => 0 > 500 + 64*(-0.5) = 500 - 32 = 468 => FALSE → tile culled. var tile = makeTile(); var layer = makeLayerWithCull([[tile]], 1, 1); var narrowCamera = { worldView: { x: 500, right: 1000, y: 500, bottom: 1000 } }; var output = []; IsometricCullTiles(layer, narrowCamera, output, 0); // tile at world(0,0) is to the left of camera.worldView.x=500 → culled expect(output.length).toBe(0); }); }); describe('tilemapLayer statistics', function () { it('should set tilesDrawn to the count of tiles added to outputArray', function () { var t0 = makeTile(); var t1 = makeTile(-1); var layer = makeLayer([[t0, t1]], 2, 1); var camera = makeCamera(); IsometricCullTiles(layer, camera, [], 0); expect(layer.tilemapLayer.tilesDrawn).toBe(1); }); it('should set tilesTotal to mapWidth * mapHeight', function () { var row0 = [makeTile(), makeTile(), makeTile()]; var row1 = [makeTile(), makeTile(), makeTile()]; var layer = makeLayer([row0, row1], 3, 2); var camera = makeCamera(); IsometricCullTiles(layer, camera, [], 0); expect(layer.tilemapLayer.tilesTotal).toBe(6); }); it('should set tilesDrawn to 0 when all tiles are filtered', function () { var layer = makeLayer([[null, null]], 2, 1); var camera = makeCamera(); IsometricCullTiles(layer, camera, [], 0); expect(layer.tilemapLayer.tilesDrawn).toBe(0); }); it('should set tilesDrawn equal to output length', function () { var tiles = [makeTile(), makeTile(), makeTile()]; var layer = makeLayer([tiles], 3, 1); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output, 0); expect(layer.tilemapLayer.tilesDrawn).toBe(output.length); }); }); describe('renderOrder 0 - right-down', function () { it('should iterate x left-to-right within each row', function () { var t00 = makeTile(); var t01 = makeTile(); var t10 = makeTile(); var t11 = makeTile(); var layer = makeLayer([[t00, t01], [t10, t11]], 2, 2); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output, 0); expect(output[0]).toBe(t00); expect(output[1]).toBe(t01); expect(output[2]).toBe(t10); expect(output[3]).toBe(t11); }); }); describe('renderOrder 1 - left-down', function () { it('should iterate x right-to-left within each row', function () { var t00 = makeTile(); var t01 = makeTile(); var t10 = makeTile(); var t11 = makeTile(); // x starts at drawRight=mapWidth=2 → mapData[y][2] is undefined (skipped) // then x=1, x=0 var layer = makeLayer([[t00, t01], [t10, t11]], 2, 2); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output, 1); expect(output[0]).toBe(t01); expect(output[1]).toBe(t00); expect(output[2]).toBe(t11); expect(output[3]).toBe(t10); }); }); describe('renderOrder 2 - right-up', function () { it('should iterate rows bottom-to-top, x left-to-right', function () { var t00 = makeTile(); var t01 = makeTile(); var t10 = makeTile(); var t11 = makeTile(); // The loop starts at y=drawBottom=mapHeight=2. // mapData must have a row at index 2 (null entries are skipped by !tile). // Then y=1, y=0. var layer = makeLayer([[t00, t01], [t10, t11], [null, null]], 2, 2); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output, 2); expect(output[0]).toBe(t10); expect(output[1]).toBe(t11); expect(output[2]).toBe(t00); expect(output[3]).toBe(t01); }); }); describe('renderOrder 3 - left-up', function () { it('should iterate rows bottom-to-top, x right-to-left', function () { var t00 = makeTile(); var t01 = makeTile(); var t10 = makeTile(); var t11 = makeTile(); // The loop starts at y=mapHeight=2 (needs a row) and x=mapWidth=2 (needs a column). // Extra null entries at those indices are skipped by !tile. var layer = makeLayer([[t00, t01, null], [t10, t11, null], [null, null, null]], 2, 2); var camera = makeCamera(); var output = []; IsometricCullTiles(layer, camera, output, 3); expect(output[0]).toBe(t11); expect(output[1]).toBe(t10); expect(output[2]).toBe(t01); expect(output[3]).toBe(t00); }); }); describe('unknown renderOrder', function () { it('should return an empty array for an unrecognised render order', function () { var tile = makeTile(); var layer = makeLayer([[tile]], 1, 1); var camera = makeCamera(); var output = []; var result = IsometricCullTiles(layer, camera, output, 99); expect(result).toBe(output); expect(output.length).toBe(0); }); it('should still set tilesTotal correctly for an unrecognised render order', function () { var layer = makeLayer([[makeTile(), makeTile()]], 2, 1); var camera = makeCamera(); IsometricCullTiles(layer, camera, [], 99); expect(layer.tilemapLayer.tilesTotal).toBe(2); }); }); describe('empty map', function () { it('should return an empty array for a 0x0 map', function () { var layer = makeLayer([], 0, 0); var camera = makeCamera(); var output = []; var result = IsometricCullTiles(layer, camera, output, 0); expect(result.length).toBe(0); }); it('should set tilesTotal to 0 for a 0x0 map', function () { var layer = makeLayer([], 0, 0); var camera = makeCamera(); IsometricCullTiles(layer, camera, [], 0); expect(layer.tilemapLayer.tilesTotal).toBe(0); }); }); });