UNPKG

phaser

Version:

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

649 lines (528 loc) 20.3 kB
var ParseTilesets = require('../../../../src/tilemaps/parsers/tiled/ParseTilesets'); describe('Phaser.Tilemaps.Parsers.Tiled.ParseTilesets', function () { var warnSpy; beforeEach(function () { warnSpy = vi.spyOn(console, 'warn').mockImplementation(function () {}); }); afterEach(function () { warnSpy.mockRestore(); }); // --------------------------------------------------------------------------- // Helpers // --------------------------------------------------------------------------- function makeImageTilesetJSON(overrides) { var base = { name: 'TestTileset', firstgid: 1, tilewidth: 32, tileheight: 32, margin: 0, spacing: 0, image: 'tileset.png', imagewidth: 128, imageheight: 128, tileoffset: { x: 0, y: 0 } }; return Object.assign({}, base, overrides); } function makeCollectionTilesetJSON(overrides) { var base = { name: 'TestCollection', firstgid: 1, tilewidth: 32, tileheight: 32, margin: 0, spacing: 0, properties: {}, tiles: [ { id: 0, image: 'tile0.png', imagewidth: 32, imageheight: 32 }, { id: 1, image: 'tile1.png', imagewidth: 64, imageheight: 64 } ] }; return Object.assign({}, base, overrides); } // --------------------------------------------------------------------------- // Empty input // --------------------------------------------------------------------------- it('should return empty arrays when tilesets array is empty', function () { var result = ParseTilesets({ tilesets: [], version: 1 }); expect(result.tilesets).toEqual([]); expect(result.imageCollections).toEqual([]); }); it('should return an object with tilesets and imageCollections properties', function () { var result = ParseTilesets({ tilesets: [], version: 1 }); expect(result).toHaveProperty('tilesets'); expect(result).toHaveProperty('imageCollections'); }); // --------------------------------------------------------------------------- // External tileset warning // --------------------------------------------------------------------------- it('should warn when a tileset has a source property (external tileset)', function () { var json = { version: 1, tilesets: [ { source: 'external.tsx', firstgid: 1 } ] }; ParseTilesets(json); expect(warnSpy).toHaveBeenCalledWith( 'External tilesets unsupported. Use Embed Tileset and re-export' ); }); it('should not add anything to tilesets or imageCollections for an external tileset', function () { var json = { version: 1, tilesets: [ { source: 'external.tsx', firstgid: 1 } ] }; var result = ParseTilesets(json); expect(result.tilesets).toHaveLength(0); expect(result.imageCollections).toHaveLength(0); }); // --------------------------------------------------------------------------- // Image-based tileset (Tileset instances) // --------------------------------------------------------------------------- it('should create a Tileset instance for an image-based tileset entry', function () { var json = { version: 1, tilesets: [ makeImageTilesetJSON() ] }; var result = ParseTilesets(json); expect(result.tilesets).toHaveLength(1); expect(result.imageCollections).toHaveLength(0); }); it('should set the correct name on a created Tileset', function () { var json = { version: 1, tilesets: [ makeImageTilesetJSON({ name: 'MyTiles' }) ] }; var result = ParseTilesets(json); expect(result.tilesets[0].name).toBe('MyTiles'); }); it('should set the correct firstgid on a created Tileset', function () { var json = { version: 1, tilesets: [ makeImageTilesetJSON({ firstgid: 5 }) ] }; var result = ParseTilesets(json); expect(result.tilesets[0].firstgid).toBe(5); }); it('should set correct tile dimensions on a created Tileset', function () { var json = { version: 1, tilesets: [ makeImageTilesetJSON({ tilewidth: 16, tileheight: 16 }) ] }; var result = ParseTilesets(json); expect(result.tilesets[0].tileWidth).toBe(16); expect(result.tilesets[0].tileHeight).toBe(16); }); it('should set correct margin and spacing on a created Tileset', function () { var json = { version: 1, tilesets: [ makeImageTilesetJSON({ margin: 2, spacing: 4 }) ] }; var result = ParseTilesets(json); expect(result.tilesets[0].tileMargin).toBe(2); expect(result.tilesets[0].tileSpacing).toBe(4); }); it('should call updateTileData with imagewidth and imageheight', function () { var json = { version: 1, tilesets: [ makeImageTilesetJSON({ imagewidth: 64, imageheight: 64, tilewidth: 32, tileheight: 32 }) ] }; var result = ParseTilesets(json); var tileset = result.tilesets[0]; // 64px wide / 32px tile = 2 columns, 2 rows expect(tileset.columns).toBe(2); expect(tileset.rows).toBe(2); expect(tileset.total).toBe(4); }); // --------------------------------------------------------------------------- // lastgid propagation // --------------------------------------------------------------------------- it('should set lastgid on the previous raw set object when multiple tilesets are present', function () { var first = makeImageTilesetJSON({ name: 'First', firstgid: 1 }); var second = makeImageTilesetJSON({ name: 'Second', firstgid: 10 }); var json = { version: 1, tilesets: [ first, second ] }; ParseTilesets(json); // lastgid is written back onto the raw JSON set objects, not the Tileset instances expect(first.lastgid).toBe(9); }); it('should not set lastgid when there is only one tileset', function () { var only = makeImageTilesetJSON({ firstgid: 1 }); var json = { version: 1, tilesets: [ only ] }; ParseTilesets(json); expect(only.lastgid).toBeUndefined(); }); it('should set lastgid correctly across three tilesets', function () { var setA = makeImageTilesetJSON({ name: 'A', firstgid: 1 }); var setB = makeImageTilesetJSON({ name: 'B', firstgid: 11 }); var setC = makeImageTilesetJSON({ name: 'C', firstgid: 21 }); var json = { version: 1, tilesets: [ setA, setB, setC ] }; ParseTilesets(json); expect(setA.lastgid).toBe(10); expect(setB.lastgid).toBe(20); expect(setC.lastgid).toBeUndefined(); }); // --------------------------------------------------------------------------- // Tiled v1 format (json.version <= 1) // --------------------------------------------------------------------------- it('should assign tileproperties directly in Tiled v1 format', function () { var tileProps = { '0': { collides: true }, '1': { damage: 5 } }; var json = { version: 1, tilesets: [ makeImageTilesetJSON({ tileproperties: tileProps }) ] }; var result = ParseTilesets(json); expect(result.tilesets[0].tileProperties).toBe(tileProps); }); it('should assign tiles data directly in Tiled v1 format', function () { var tileData = { '0': { terrain: [0, 1, 0, 1] } }; var json = { version: 1, tilesets: [ makeImageTilesetJSON({ tiles: tileData }) ] }; var result = ParseTilesets(json); expect(result.tilesets[0].tileData).toBe(tileData); }); it('should parse objectgroup objects in Tiled v1 tile data', function () { var json = { version: 1, tilesets: [ makeImageTilesetJSON({ tiles: { '0': { objectgroup: { objects: [ { id: 1, name: 'collision', type: '', x: 0, y: 0, width: 32, height: 32, rotation: 0, visible: true, properties: [] } ] } } } }) ] }; var result = ParseTilesets(json); var obj = result.tilesets[0].tileData['0'].objectgroup.objects[0]; expect(obj).toBeDefined(); expect(obj.id).toBe(1); expect(obj.name).toBe('collision'); }); it('should not set tileProperties when tileproperties is absent in Tiled v1', function () { var json = { version: 1, tilesets: [ makeImageTilesetJSON() ] }; var result = ParseTilesets(json); // Default from Tileset constructor is {} expect(result.tilesets[0].tileProperties).toEqual({}); }); // --------------------------------------------------------------------------- // Tiled v2+ format (json.version > 1) // --------------------------------------------------------------------------- it('should convert tile properties array to keyed object in Tiled v2 format', function () { var json = { version: 2, tilesets: [ makeImageTilesetJSON({ tiles: [ { id: 0, properties: [ { name: 'collides', value: true }, { name: 'damage', value: 10 } ] } ] }) ] }; var result = ParseTilesets(json); expect(result.tilesets[0].tileProperties[0]).toEqual({ collides: true, damage: 10 }); }); it('should store animation data on tiles in Tiled v2 format', function () { var animation = [ { tileid: 0, duration: 100 }, { tileid: 1, duration: 200 } ]; var json = { version: 2, tilesets: [ makeImageTilesetJSON({ tiles: [ { id: 0, animation: animation } ] }) ] }; var result = ParseTilesets(json); expect(result.tilesets[0].tileData[0].animation).toBeDefined(); expect(result.tilesets[0].tileData[0].animation).toHaveLength(2); }); it('should calculate animation startTime and animationDuration in Tiled v2 format', function () { var json = { version: 2, tilesets: [ makeImageTilesetJSON({ tiles: [ { id: 0, animation: [ { tileid: 0, duration: 100 }, { tileid: 1, duration: 200 }, { tileid: 2, duration: 150 } ] } ] }) ] }; var result = ParseTilesets(json); var tileData = result.tilesets[0].tileData[0]; expect(tileData.animation[0].startTime).toBe(0); expect(tileData.animation[1].startTime).toBe(100); expect(tileData.animation[2].startTime).toBe(300); expect(tileData.animationDuration).toBe(450); }); it('should store tile type in Tiled v2 format', function () { var json = { version: 2, tilesets: [ makeImageTilesetJSON({ tiles: [ { id: 3, type: 'SpawnPoint' } ] }) ] }; var result = ParseTilesets(json); expect(result.tilesets[0].tileData[3].type).toBe('SpawnPoint'); }); it('should store objectgroup on tile data in Tiled v2 format', function () { var json = { version: 2, tilesets: [ makeImageTilesetJSON({ tiles: [ { id: 2, objectgroup: { objects: [ { id: 1, name: 'hit', type: '', x: 0, y: 0, width: 16, height: 16, rotation: 0, visible: true, properties: [] } ] } } ] }) ] }; var result = ParseTilesets(json); expect(result.tilesets[0].tileData[2].objectgroup).toBeDefined(); expect(result.tilesets[0].tileData[2].objectgroup.objects).toHaveLength(1); }); it('should parse objectgroup objects through ParseObject in Tiled v2 format', function () { var json = { version: 2, tilesets: [ makeImageTilesetJSON({ tiles: [ { id: 0, objectgroup: { objects: [ { id: 5, name: 'zone', type: '', x: 4, y: 8, width: 20, height: 20, rotation: 0, visible: true, properties: [] } ] } } ] }) ] }; var result = ParseTilesets(json); var obj = result.tilesets[0].tileData[0].objectgroup.objects[0]; expect(obj.id).toBe(5); expect(obj.name).toBe('zone'); expect(obj.x).toBe(4); expect(obj.y).toBe(8); }); it('should not set tileData or tileProperties when tiles array is absent in Tiled v2', function () { var json = { version: 2, tilesets: [ makeImageTilesetJSON() ] }; var result = ParseTilesets(json); // Should remain at default empty objects from Tileset constructor expect(result.tilesets[0].tileData).toEqual({}); expect(result.tilesets[0].tileProperties).toEqual({}); }); it('should handle a tile with multiple data fields simultaneously in Tiled v2', function () { var json = { version: 2, tilesets: [ makeImageTilesetJSON({ tiles: [ { id: 0, properties: [{ name: 'key', value: 'val' }], animation: [{ tileid: 0, duration: 50 }], type: 'Door' } ] }) ] }; var result = ParseTilesets(json); var td = result.tilesets[0].tileData; var tp = result.tilesets[0].tileProperties; expect(td[0].animation).toBeDefined(); expect(td[0].type).toBe('Door'); expect(tp[0]).toEqual({ key: 'val' }); }); // --------------------------------------------------------------------------- // ImageCollection // --------------------------------------------------------------------------- it('should create an ImageCollection for a tileset without an image property', function () { var json = { version: 1, tilesets: [ makeCollectionTilesetJSON() ] }; var result = ParseTilesets(json); expect(result.imageCollections).toHaveLength(1); expect(result.tilesets).toHaveLength(0); }); it('should set the correct name on an ImageCollection', function () { var json = { version: 1, tilesets: [ makeCollectionTilesetJSON({ name: 'MyCollection' }) ] }; var result = ParseTilesets(json); expect(result.imageCollections[0].name).toBe('MyCollection'); }); it('should set the correct firstgid on an ImageCollection', function () { var json = { version: 1, tilesets: [ makeCollectionTilesetJSON({ firstgid: 7 }) ] }; var result = ParseTilesets(json); expect(result.imageCollections[0].firstgid).toBe(7); }); it('should add all images to an ImageCollection', function () { var json = { version: 1, tilesets: [ makeCollectionTilesetJSON({ firstgid: 1, tiles: [ { id: 0, image: 'a.png', imagewidth: 32, imageheight: 32 }, { id: 1, image: 'b.png', imagewidth: 64, imageheight: 64 }, { id: 2, image: 'c.png', imagewidth: 16, imageheight: 16 } ] }) ] }; var result = ParseTilesets(json); expect(result.imageCollections[0].images).toHaveLength(3); }); it('should compute the correct maxId on an ImageCollection', function () { var json = { version: 1, tilesets: [ makeCollectionTilesetJSON({ tiles: [ { id: 0, image: 'a.png', imagewidth: 32, imageheight: 32 }, { id: 5, image: 'b.png', imagewidth: 32, imageheight: 32 }, { id: 3, image: 'c.png', imagewidth: 32, imageheight: 32 } ] }) ] }; var result = ParseTilesets(json); expect(result.imageCollections[0].maxId).toBe(5); }); it('should add images with gid equal to firstgid plus tileId', function () { var json = { version: 1, tilesets: [ makeCollectionTilesetJSON({ firstgid: 10, tiles: [ { id: 0, image: 'first.png', imagewidth: 32, imageheight: 32 }, { id: 2, image: 'third.png', imagewidth: 32, imageheight: 32 } ] }) ] }; var result = ParseTilesets(json); var images = result.imageCollections[0].images; // GID = firstgid + id expect(images[0].gid).toBe(10); expect(images[1].gid).toBe(12); }); // --------------------------------------------------------------------------- // Mixed tilesets // --------------------------------------------------------------------------- it('should handle a mix of image tilesets and image collections', function () { var json = { version: 1, tilesets: [ makeImageTilesetJSON({ name: 'Sheet', firstgid: 1 }), makeCollectionTilesetJSON({ name: 'Collection', firstgid: 100 }) ] }; var result = ParseTilesets(json); expect(result.tilesets).toHaveLength(1); expect(result.imageCollections).toHaveLength(1); expect(result.tilesets[0].name).toBe('Sheet'); expect(result.imageCollections[0].name).toBe('Collection'); }); it('should set lastgid on the raw set object at the image tileset to collection boundary', function () { var sheet = makeImageTilesetJSON({ name: 'Sheet', firstgid: 1 }); var collection = makeCollectionTilesetJSON({ name: 'Collection', firstgid: 50 }); var json = { version: 1, tilesets: [ sheet, collection ] }; ParseTilesets(json); expect(sheet.lastgid).toBe(49); }); });