UNPKG

kaplay-plugin-tiled

Version:
1 lines 19.5 kB
{"version":3,"file":"plugin.cjs","names":[],"sources":["../src/utils.ts","../src/plugin.ts"],"sourcesContent":["import type { CompList, GameObj, KAPLAYCtx, Quad } from 'kaplay';\n\nimport type {\n ParsedTiledLayer,\n ParsedTiledMap,\n ParsedTiledObjectLayer,\n ParsedTiledTile,\n ParsedTiledTileLayer,\n TiledLayer,\n TiledLayerComp,\n TiledMap,\n TiledMapData,\n TiledMapOpt,\n TiledObjectContext,\n TiledObjectLayer,\n TiledObjectMatch,\n TiledProperty,\n TiledPropertyValue,\n TiledTileContext,\n TiledTileLayer,\n TiledTileMatch,\n} from './types';\n\nconst FLIPPED_HORIZONTALLY_FLAG = 0x80000000;\nconst FLIPPED_VERTICALLY_FLAG = 0x40000000;\nconst FLIPPED_DIAGONALLY_FLAG = 0x20000000;\nconst FLIP_FLAGS =\n FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG;\n\ninterface ParsedTileGid {\n gid: number;\n flip: {\n diagonal: boolean;\n horizontal: boolean;\n vertical: boolean;\n };\n}\n\nexport function resolveTiledMap(k: KAPLAYCtx, map: TiledMap): TiledMapData {\n if (typeof map !== 'string') {\n return map;\n }\n\n const asset = k.getAsset(map);\n\n if (!asset) {\n throw new Error(`Tiled map asset \"${map}\" is not loaded.`);\n }\n\n if (!asset.data) {\n throw new Error(`Tiled map asset \"${map}\" is not ready yet.`);\n }\n\n return asset.data as TiledMapData;\n}\n\nfunction getPropertyRecord(\n properties: TiledProperty[] | undefined,\n): Record<string, TiledPropertyValue> {\n const record: Record<string, TiledPropertyValue> = {};\n\n properties?.forEach((property) => {\n record[property.name] = property.value;\n });\n\n return record;\n}\n\nfunction isObjectLayer(layer: TiledLayer): layer is TiledObjectLayer {\n return layer.type === 'objectgroup';\n}\n\nfunction isTileLayer(layer: TiledLayer): layer is TiledTileLayer {\n return layer.type === 'tilelayer';\n}\n\nfunction normalizeTileLayer(layer: TiledTileLayer): ParsedTiledLayer {\n return {\n data: layer.data,\n height: layer.height,\n name: layer.name,\n opacity: layer.opacity ?? 1,\n type: 'tilelayer',\n visible: layer.visible ?? true,\n width: layer.width,\n x: layer.x ?? 0,\n y: layer.y ?? 0,\n zIndex: 0,\n };\n}\n\nfunction normalizeObjectLayer(layer: TiledObjectLayer): ParsedTiledObjectLayer {\n return {\n name: layer.name,\n objects: layer.objects,\n type: 'objectgroup',\n visible: layer.visible ?? true,\n zIndex: 0,\n };\n}\n\nexport function parseTileGid(rawGid: number): ParsedTileGid | null {\n if (rawGid === 0) {\n return null;\n }\n\n return {\n gid: (rawGid & ~FLIP_FLAGS) >>> 0,\n flip: {\n diagonal: (rawGid & FLIPPED_DIAGONALLY_FLAG) !== 0,\n horizontal: (rawGid & FLIPPED_HORIZONTALLY_FLAG) !== 0,\n vertical: (rawGid & FLIPPED_VERTICALLY_FLAG) !== 0,\n },\n };\n}\n\nfunction getTileDrawTransform(flip: ParsedTileGid['flip']): {\n angle: number;\n flipX: boolean;\n flipY: boolean;\n} {\n if (!flip.diagonal) {\n return {\n angle: 0,\n flipX: flip.horizontal,\n flipY: flip.vertical,\n };\n }\n\n if (flip.horizontal && flip.vertical) {\n return {\n angle: 270,\n flipX: true,\n flipY: false,\n };\n }\n\n if (flip.horizontal) {\n return {\n angle: 270,\n flipX: false,\n flipY: false,\n };\n }\n\n if (flip.vertical) {\n return {\n angle: 90,\n flipX: false,\n flipY: false,\n };\n }\n\n return {\n angle: 270,\n flipX: false,\n flipY: true,\n };\n}\n\nfunction getTileQuad(k: KAPLAYCtx, map: ParsedTiledMap, gid: number): Quad {\n const localTileId = gid - map.tileset.firstGid;\n const column = localTileId % map.tileset.columns;\n const row = Math.floor(localTileId / map.tileset.columns);\n const x =\n map.tileset.margin + column * (map.tileset.tileWidth + map.tileset.spacing);\n const y =\n map.tileset.margin + row * (map.tileset.tileHeight + map.tileset.spacing);\n\n return k.quad(\n x / map.tileset.imageWidth,\n y / map.tileset.imageHeight,\n map.tileset.tileWidth / map.tileset.imageWidth,\n map.tileset.tileHeight / map.tileset.imageHeight,\n );\n}\n\nexport function getLayerNames(options: TiledMapOpt): Set<string> | null {\n if (!options.layerNames?.length) {\n return null;\n }\n\n return new Set(options.layerNames);\n}\n\nfunction getParsedTile(\n map: ParsedTiledMap,\n gid: number,\n): ParsedTiledTile | undefined {\n return map.tileset.tiles[gid];\n}\n\nfunction matchesProperties(\n expected: Record<string, TiledPropertyValue> | undefined,\n actual: Record<string, TiledPropertyValue>,\n): boolean {\n if (!expected) {\n return true;\n }\n\n return Object.entries(expected).every(\n ([name, value]) => actual[name] === value,\n );\n}\n\nfunction matchesTileRule(\n match: TiledTileMatch,\n tile: TiledTileContext,\n): boolean {\n if (match.gid !== undefined && match.gid !== tile.gid) {\n return false;\n }\n\n if (match.tileId !== undefined && match.tileId !== tile.tileId) {\n return false;\n }\n\n if (match.layer !== undefined && match.layer !== tile.layer) {\n return false;\n }\n\n return matchesProperties(match.properties, tile.properties);\n}\n\nfunction matchesObjectRule(\n match: TiledObjectMatch,\n object: TiledObjectContext,\n): boolean {\n if (match.layer !== undefined && match.layer !== object.layer) {\n return false;\n }\n\n if (match.name !== undefined && match.name !== object.name) {\n return false;\n }\n\n if (match.type !== undefined && match.type !== object.type) {\n return false;\n }\n\n return matchesProperties(match.properties, object.properties);\n}\n\nexport function createLayerRenderer(\n k: KAPLAYCtx,\n layer: ParsedTiledTileLayer,\n map: ParsedTiledMap,\n sprite: string,\n): GameObj {\n return k.add([\n k.pos(0, 0),\n k.z(layer.zIndex),\n {\n draw: () => {\n layer.data.forEach((rawGid, index) => {\n const parsedGid = parseTileGid(rawGid);\n\n if (!parsedGid) {\n return;\n }\n\n const column = index % layer.width;\n const row = Math.floor(index / layer.width);\n const drawTransform = getTileDrawTransform(parsedGid.flip);\n\n k.drawSprite({\n anchor: 'center',\n angle: drawTransform.angle,\n flipX: drawTransform.flipX,\n flipY: drawTransform.flipY,\n opacity: layer.opacity,\n pos: k.vec2(\n (column + layer.x) * map.tileWidth + map.tileset.tileWidth / 2,\n (row + layer.y) * map.tileHeight + map.tileset.tileHeight / 2,\n ),\n quad: getTileQuad(k, map, parsedGid.gid),\n sprite,\n });\n });\n },\n id: 'tiled-layer',\n },\n ] as CompList<TiledLayerComp>);\n}\n\nexport function createMatchedTileObjects(\n k: KAPLAYCtx,\n layer: ParsedTiledTileLayer,\n map: ParsedTiledMap,\n options: TiledMapOpt,\n): GameObj[] {\n const rules = options.tiles;\n\n if (!rules?.length) {\n return [];\n }\n\n const tiles: GameObj[] = [];\n\n layer.data.forEach((rawGid, index) => {\n const parsedGid = parseTileGid(rawGid);\n\n if (!parsedGid) {\n return;\n }\n\n const parsedTile = getParsedTile(map, parsedGid.gid);\n const column = index % layer.width;\n const row = Math.floor(index / layer.width);\n const tile = {\n flip: parsedGid.flip,\n gid: parsedGid.gid,\n height: map.tileHeight,\n layer: layer.name,\n tileHeight: map.tileHeight,\n tileWidth: map.tileWidth,\n tileX: column + layer.x,\n tileY: row + layer.y,\n width: map.tileWidth,\n x: (column + layer.x) * map.tileWidth,\n y: (row + layer.y) * map.tileHeight,\n properties: parsedTile?.properties ?? {},\n tileId: parsedTile?.tileId ?? parsedGid.gid - map.tileset.firstGid,\n };\n\n rules.forEach((rule) => {\n if (!matchesTileRule(rule.match, tile)) {\n return;\n }\n\n tiles.push(\n k.add([\n k.pos(tile.x, tile.y),\n k.anchor('topleft'),\n k.z(layer.zIndex),\n ...rule.comps(tile),\n ] as CompList<unknown>),\n );\n });\n });\n\n return tiles;\n}\n\nexport function createMatchedObjectObjects(\n k: KAPLAYCtx,\n layer: ParsedTiledObjectLayer,\n options: TiledMapOpt,\n): GameObj[] {\n const rules = options.objects;\n\n if (!rules?.length) {\n return [];\n }\n\n const objects: GameObj[] = [];\n\n if (!layer.visible) {\n return objects;\n }\n\n layer.objects.forEach((object) => {\n if (!object.visible) {\n return;\n }\n\n const context: TiledObjectContext = {\n height: object.height,\n id: object.id,\n layer: layer.name,\n name: object.name,\n width: object.width,\n x: object.x,\n y: object.y,\n point: object.point ?? false,\n properties: getPropertyRecord(object.properties),\n rotation: object.rotation,\n type: object.type,\n };\n\n rules.forEach((rule) => {\n if (!matchesObjectRule(rule.match, context)) {\n return;\n }\n\n objects.push(\n k.add([\n k.pos(context.x, context.y),\n k.anchor('topleft'),\n k.z(layer.zIndex),\n ...rule.comps(context),\n ] as CompList<unknown>),\n );\n });\n });\n\n return objects;\n}\n\nexport function parseTiledMap(data: TiledMapData): ParsedTiledMap {\n if (data.orientation !== 'orthogonal') {\n throw new Error(\n `Unsupported Tiled orientation \"${data.orientation}\". Expected \"orthogonal\".`,\n );\n }\n\n if (data.infinite) {\n throw new Error('Infinite Tiled maps are not supported.');\n }\n\n if (data.tilesets.length !== 1) {\n throw new Error('Exactly one Tiled tileset is required.');\n }\n\n const [tileset] = data.tilesets;\n\n if (tileset.columns <= 0) {\n throw new Error('Tiled tileset columns must be greater than 0.');\n }\n\n const layers = data.layers.map((layer, zIndex) => {\n if (isTileLayer(layer)) {\n if (layer.data.length !== layer.width * layer.height) {\n throw new Error(\n `Layer \"${layer.name}\" data length does not match its dimensions.`,\n );\n }\n\n return {\n ...normalizeTileLayer(layer),\n zIndex,\n };\n }\n\n if (isObjectLayer(layer)) {\n return {\n ...normalizeObjectLayer(layer),\n zIndex,\n };\n }\n\n throw new Error('Unsupported Tiled layer type.');\n });\n\n return {\n height: data.height,\n layers,\n orientation: 'orthogonal',\n tileHeight: data.tileheight,\n tileWidth: data.tilewidth,\n tileset: {\n columns: tileset.columns,\n firstGid: tileset.firstgid,\n image: tileset.image,\n imageHeight: tileset.imageheight,\n imageWidth: tileset.imagewidth,\n lastGid: tileset.firstgid + tileset.tilecount - 1,\n margin: tileset.margin ?? 0,\n name: tileset.name,\n spacing: tileset.spacing ?? 0,\n tileCount: tileset.tilecount,\n tileHeight: tileset.tileheight,\n tiles: Object.fromEntries(\n (tileset.tiles ?? []).map((tile) => [\n tile.id + tileset.firstgid,\n {\n gid: tile.id + tileset.firstgid,\n properties: getPropertyRecord(tile.properties),\n tileId: tile.id,\n },\n ]),\n ),\n tileWidth: tileset.tilewidth,\n },\n width: data.width,\n };\n}\n","import type { KAPLAYCtx } from 'kaplay';\n\nimport type { AddTiledMap, TiledMap, TiledMapOpt } from './types';\nimport {\n createLayerRenderer,\n createMatchedObjectObjects,\n createMatchedTileObjects,\n getLayerNames,\n parseTiledMap,\n parseTileGid,\n resolveTiledMap,\n} from './utils';\n\nexport type { AddTiledMap, TiledMap, TiledMapOpt } from './types';\n\ndeclare module 'kaplay' {\n interface KAPLAYCtx {\n addTiledMap: (map: TiledMap, options: TiledMapOpt) => void;\n }\n}\n\n/**\n * Add a Tiled map to the current KAPLAY context.\n *\n * The `map` argument can either be:\n * - parsed map JSON, or\n * - the asset key of a map loaded with `loadJSON()`.\n *\n * @param k - The active KAPLAY context.\n * @param map - The Tiled map data.\n * @param opt - The Tiled map options.\n */\nfunction addTiledMap(k: KAPLAYCtx, map: TiledMap, opt: TiledMapOpt): void {\n const parsedMap = parseTiledMap(resolveTiledMap(k, map));\n const allowedLayerNames = getLayerNames(opt);\n\n parsedMap.layers.forEach((layer) => {\n if (!layer.visible) {\n return;\n }\n\n if (allowedLayerNames && !allowedLayerNames.has(layer.name)) {\n return;\n }\n\n if (layer.type === 'tilelayer') {\n layer.data.forEach((rawGid) => {\n const parsedGid = parseTileGid(rawGid);\n\n if (\n parsedGid &&\n (parsedGid.gid < parsedMap.tileset.firstGid ||\n parsedGid.gid > parsedMap.tileset.lastGid)\n ) {\n throw new Error(\n `Tile gid ${String(rawGid)} is outside the supported tileset range.`,\n );\n }\n });\n\n createLayerRenderer(k, layer, parsedMap, opt.sprite);\n createMatchedTileObjects(k, layer, parsedMap, opt);\n return;\n }\n\n createMatchedObjectObjects(k, layer, opt);\n });\n}\n\n/**\n * KAPLAY plugin that adds `addTiledMap()` to the context.\n *\n * @param k - The active KAPLAY context.\n * @returns - The plugin API.\n */\nexport function tiledPlugin(k: KAPLAYCtx) {\n const boundAddTiledMap: AddTiledMap = (map, options) => {\n addTiledMap(k, map, options);\n };\n\n return { addTiledMap: boundAddTiledMap };\n}\n"],"mappings":"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"}