UNPKG

ecspresso

Version:

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

136 lines (135 loc) 4.76 kB
/** * Detection Plugin for ECSpresso * * Provides automatic proximity detection for entities. Entities with a * `detector` component get their `detectedEntities` populated each frame * with nearby entities that match the configured collision layer filter, * sorted by distance ascending (nearest first). * * Uses the spatial-index plugin for efficient range queries. */ import { type BasePluginOptions } from 'ecspresso'; import type { ComponentsConfig, EventsConfig, ResourcesConfig } from 'ecspresso'; import type { TransformWorldConfig } from '../spatial/transform'; import type { SpatialIndexResourceTypes } from '../spatial/spatial-index'; import type { CollisionComponentTypes } from '../physics/collision'; /** * Configures proximity detection for an entity. */ export interface Detector { /** Detection radius in world units */ range: number; /** Only detect entities on these collision layers */ layerFilter: readonly string[]; /** Maximum number of results to track (default: 32) */ maxResults: number; } /** * A detected entity with its squared distance from the detector. */ export interface DetectedEntry { entityId: number; distanceSq: number; } /** * Auto-populated list of detected entities, sorted by distance ascending. */ export interface DetectedEntities { entities: readonly DetectedEntry[]; } /** * Component types provided by the detection plugin. */ export interface DetectionComponentTypes { detector: Detector; detectedEntities: DetectedEntities; } /** * Event fired when a new entity enters detection range. */ export interface DetectionGainedEvent { /** The entity doing the detecting */ entityId: number; /** The entity that was detected */ detectedId: number; } /** * Event fired when an entity leaves detection range. */ export interface DetectionLostEvent { /** The entity doing the detecting */ entityId: number; /** The entity that was lost */ lostId: number; } /** * Event types provided by the detection plugin. */ export interface DetectionEventTypes { detectionGained: DetectionGainedEvent; detectionLost: DetectionLostEvent; } /** * WorldConfig representing the detection plugin's provided types. */ export type DetectionWorldConfig = ComponentsConfig<DetectionComponentTypes> & EventsConfig<DetectionEventTypes>; export interface DetectionPluginOptions<G extends string = 'ai'> extends BasePluginOptions<G> { } /** * Create a detector component. * * @param range Detection radius in world units * @param layerFilter Only detect entities on these collision layers * @param maxResults Maximum results to track (default: 32) * @returns Component object suitable for spreading into spawn() * * @example * ```typescript * ecs.spawn({ * ...createDetector(300, ['enemy']), * ...createLocalTransform(400, 400), * }); * ``` */ export declare function createDetector(range: number, layerFilter: readonly string[], maxResults?: number): Pick<DetectionComponentTypes, 'detector'>; /** * Check whether an entity has any detected targets. * * @param ecs ECS world instance * @param entityId Entity with a detector component * @returns true if detectedEntities contains at least one entry * * @example * ```typescript * if (hasDetectedTargets(ecs, guardId)) { * // transition to chase * } * ``` */ export declare function hasDetectedTargets(ecs: { getComponent(entityId: number, name: 'detectedEntities'): DetectedEntities | undefined; }, entityId: number): boolean; /** * Create a detection plugin for ECSpresso. * * Populates `detectedEntities` each frame with nearby entities matching * the detector's layer filter, sorted by distance (nearest first). * Publishes `detectionGained`/`detectionLost` events on transitions. * * Requires the spatial-index and transform plugins to be installed. * * @example * ```typescript * const ecs = ECSpresso.create() * .withPlugin(createTransformPlugin()) * .withPlugin(createCollisionPlugin({ layers })) * .withPlugin(createSpatialIndexPlugin()) * .withPlugin(createDetectionPlugin()) * .build(); * * // Read nearest detected entity: * const detected = ecs.getComponent(turretId, 'detectedEntities'); * const nearest = detected?.entities[0]; * ``` */ export declare function createDetectionPlugin<G extends string = 'ai'>(options?: DetectionPluginOptions<G>): import("ecspresso").Plugin<import("ecspresso").WithEvents<import("ecspresso").WithComponents<import("ecspresso").EmptyConfig, DetectionComponentTypes>, DetectionEventTypes>, TransformWorldConfig & ComponentsConfig<Pick<CollisionComponentTypes<string>, "collisionLayer">> & ResourcesConfig<SpatialIndexResourceTypes>, "detection-scan", G, never, never>;