UNPKG

ecspresso

Version:

A minimal Entity-Component-System library for typescript and javascript.

231 lines (230 loc) 7.54 kB
/** * Tilemap plugin for ECSpresso. * * Two ingestion paths share a common `LoadedTilemap` shape: * - `registerAsset` — load a Tiled `.tmj` file via the asset manager * - `registerRuntime` — pass a pre-built tile-id array (procedural) * * Query methods (`isSolid`, `isOpaque`, `isWalkable`) read from `tileMetadata` * regardless of source. */ import { type BasePluginOptions } from 'ecspresso'; import type { ComponentsConfig, ResourcesConfig } from '../../type-utils'; import { type NavGrid } from '../ai/pathfinding'; import type { Vector2D } from '../../utils/math'; export declare const TILE_FLIP_HORIZONTAL = 2147483648; export declare const TILE_FLIP_VERTICAL = 1073741824; export declare const TILE_FLIP_DIAGONAL = 536870912; export declare const TILE_GID_MASK = 536870911; export interface DecodedGid { id: number; flipH: boolean; flipV: boolean; flipD: boolean; } export declare function decodeGid(gid: number): DecodedGid; /** The three tile flag keys the query API understands. Custom keys flow through unchanged. */ export type TileFlag = 'solid' | 'blocksSight' | 'walkable'; /** Tile metadata. Known flag keys drive query methods; arbitrary custom keys are preserved. */ export interface TileMetadata { solid?: boolean; blocksSight?: boolean; walkable?: boolean; [key: string]: unknown; } export interface ObjectDef { name: string; type: string; x: number; y: number; width: number; height: number; rotation: number; properties: Record<string, string | number | boolean>; } export interface RuntimeTileset { textureKey: string; columns: number; tileWidth: number; tileHeight: number; firstgid?: number; } export interface RuntimeLayer { name: string; tiles: Uint32Array | Uint8Array | readonly number[]; parallax?: Vector2D; opacity?: number; visible?: boolean; } export interface TilemapRuntimeData { width: number; height: number; tileSize: number; layers: readonly RuntimeLayer[]; tilesets: readonly RuntimeTileset[]; tileMetadata?: Record<number, TileMetadata>; objectLayers?: readonly { name: string; objects: readonly ObjectDef[]; }[]; } export interface LoadedLayer { name: string; tiles: Uint32Array; parallax: Vector2D; opacity: number; visible: boolean; } export interface LoadedTileset { textureKey: string; columns: number; tileWidth: number; tileHeight: number; firstgid: number; } export interface LoadedObjectLayer { name: string; objects: readonly ObjectDef[]; } export interface LoadedTilemap { readonly width: number; readonly height: number; readonly tileWidth: number; readonly tileHeight: number; readonly layers: readonly LoadedLayer[]; readonly tilesets: readonly LoadedTileset[]; readonly tileMetadata: ReadonlyMap<number, TileMetadata>; readonly objectLayers: readonly LoadedObjectLayer[]; tileToWorld(tx: number, ty: number): Vector2D; worldToTile(wx: number, wy: number): { tx: number; ty: number; }; getTile(layerIndex: number, tx: number, ty: number): number; isSolid(tx: number, ty: number): boolean; isOpaque(tx: number, ty: number): boolean; isWalkable(tx: number, ty: number): boolean; buildNavGrid(layerIndex: number, costFn?: (tileId: number) => number): NavGrid; getObjectLayer(name: string): readonly ObjectDef[]; getObjects(type: string): readonly ObjectDef[]; } /** Subset of a Tiled `.tmj` (JSON) document we consume in v1. */ export interface TiledMap { width: number; height: number; tilewidth: number; tileheight: number; tilesets: readonly TiledTileset[]; layers: readonly TiledLayer[]; } export interface TiledTileset { firstgid: number; columns: number; tilewidth: number; tileheight: number; image: string; imagewidth: number; imageheight: number; tiles?: readonly TiledTileDef[]; } export interface TiledTileDef { id: number; properties?: readonly TiledProperty[]; animation?: readonly { tileid: number; duration: number; }[]; } export interface TiledProperty { name: string; type: 'bool' | 'int' | 'float' | 'string' | 'color' | 'file' | 'object'; value: string | number | boolean; } export type TiledLayer = TiledTileLayer | TiledObjectLayer; export interface TiledTileLayer { type: 'tilelayer'; name: string; width: number; height: number; data: readonly number[]; opacity: number; visible: boolean; parallaxx?: number; parallaxy?: number; } export interface TiledObjectLayer { type: 'objectgroup'; name: string; objects: readonly TiledObject[]; } export interface TiledObject { id: number; name?: string; type?: string; x: number; y: number; width?: number; height?: number; rotation?: number; properties?: readonly TiledProperty[]; } export interface ParseTiledOptions { tilesetTextures: Record<string, string>; } export type TilemapCullingMode = 'viewport' | 'none'; export interface TilemapLayerComponent { dataKey: string; tilesetKey?: string; layerIndex: number; opacity: number; parallax: Vector2D; cullingMode: TilemapCullingMode; cameraRef?: number; tintFn?: (tx: number, ty: number) => number | null; } export interface TilemapColliderTag { dataKey: string; } export interface TilemapComponentTypes { tilemap: TilemapLayerComponent; tilemapCollider: TilemapColliderTag; } export interface TilemapRegistry { registerRuntime(dataKey: string, data: TilemapRuntimeData): LoadedTilemap; registerAsset(dataKey: string, assetKey: string, options?: ParseTiledOptions): Promise<LoadedTilemap>; get(dataKey: string): LoadedTilemap | undefined; has(dataKey: string): boolean; readonly entries: ReadonlyMap<string, LoadedTilemap>; } export interface TilemapResourceTypes { tilemaps: TilemapRegistry; } export type TilemapWorldConfig = ComponentsConfig<TilemapComponentTypes> & ResourcesConfig<TilemapResourceTypes>; export interface TilemapPluginOptions<G extends string = 'rendering'> extends BasePluginOptions<G> { /** Optional collision layer name. When set, solid tiles auto-spawn `aabbCollider` strips. */ collisionLayer?: string; /** Layers the auto-generated tile bodies collide with. */ collidesWith?: readonly string[]; } export declare function createLoadedTilemap(data: TilemapRuntimeData): LoadedTilemap; export declare function parseTiledJSON(map: TiledMap, options: ParseTiledOptions): LoadedTilemap; export declare function createTilemapPlugin<G extends string = 'rendering'>(options?: TilemapPluginOptions<G>): import("ecspresso").Plugin<import("ecspresso").WithResources<import("ecspresso").WithComponents<import("ecspresso").EmptyConfig, TilemapComponentTypes>, TilemapResourceTypes>, import("ecspresso").EmptyConfig, never, G, never, never>; /** * Create a `tilemap` layer component for spreading into `spawn()`. * * @example * ```typescript * ecs.spawn({ * ...createTilemapLayer('dungeon', 0), * ...createLocalTransform(0, 0), * }); * ``` */ export declare function createTilemapLayer(dataKey: string, layerIndex: number, options?: { tilesetKey?: string; opacity?: number; parallax?: Vector2D; cullingMode?: TilemapCullingMode; cameraRef?: number; tintFn?: (tx: number, ty: number) => number | null; }): Pick<TilemapComponentTypes, 'tilemap'>;