UNPKG

blob2d

Version:

Typed Modular 2D Game Engine for Web

141 lines (114 loc) 3.34 kB
import { ITiledFiniteTileLayer, ITiledInfiniteTileLayer, ITiledMapJSON, } from './types'; type ITiledLayer = ITiledFiniteTileLayer | ITiledInfiniteTileLayer; type SpritesIteratee<T> = (tileGID: number, x: number, y: number) => T; type TilesIteratee<T> = ( tileGIDs: number[], columns: number, x: number, y: number ) => T; export class TiledMapper { public readonly tileSize: number; protected layers: Map<string, ITiledLayer>; constructor(map: ITiledMapJSON) { this.layers = new Map(); this.tileSize = map.tilewidth; for (let i = 0; i < map.layers.length; i++) { const layer = map.layers[i]; if (layer.type === 'tilelayer') { this.layers.set(layer.name, layer); } } } public querySprite<T>(name: string, iteratee: SpritesIteratee<T>): T { const [result] = this.queryAllSprites<T>(name, iteratee, true); if (result === undefined) { throw new Error(`No sprite named "${name}" was found.`); } return result; } public queryAllSprites<T>( name: string, iteratee: SpritesIteratee<T>, first?: boolean ): T[] { const layer = this.layers.get(name); const results: T[] = []; // skip processing wrong layer if (layer === undefined) { return results; } // process infinite tilelayer if ('chunks' in layer) { for (let j = 0; j < layer.chunks.length; j++) { const chunk = layer.chunks[j]; for (let index = 0; index < chunk.data.length; index++) { const tileGID = chunk.data[index]; if (tileGID > 0) { const col = (index % chunk.width) + chunk.x; const row = Math.floor(index / chunk.width) + chunk.y; results.push( iteratee(tileGID, col * this.tileSize, row * this.tileSize) ); if (first && results.length > 0) { return results; } } } } } else { // process finite tilelayer for (let index = 0; index < layer.data.length; index++) { const tileGID = layer.data[index]; if (tileGID > 0) { const col = (index % layer.width) + layer.x; const row = Math.floor(index / layer.width) + layer.y; results.push( iteratee(tileGID, col * this.tileSize, row * this.tileSize) ); if (first && results.length > 0) { return results; } } } } return results; } public queryAllTiles<T>(name: string, iteratee: TilesIteratee<T>): T[] { const layer = this.layers.get(name); const results: T[] = []; // skip processing wrong layer if (layer === undefined) { return results; } // process infinite tilelayer if ('chunks' in layer) { for (let j = 0; j < layer.chunks.length; j++) { const chunk = layer.chunks[j]; results.push( iteratee( chunk.data, chunk.width, chunk.x * this.tileSize, chunk.y * this.tileSize ) ); } } else { // process finite tilelayer results.push( iteratee( layer.data, layer.width, layer.x * this.tileSize, layer.y * this.tileSize ) ); } return results; } }