ecspresso
Version:
A minimal Entity-Component-System library for typescript and javascript.
231 lines (230 loc) • 7.54 kB
TypeScript
/**
* 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'>;