Files
feuerwerk/src/core/graph/NodeContext.ts
T

92 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { PropertyBag } from '../model/Properties';
import { sumAlongChain } from '../model/walk';
import { enabledAlongChain } from '../properties/enabled';
/**
* What a graph sees of a running entity. The runtime's Entity satisfies this shape; unit
* tests use plain objects. Mutating `x`/`y`/`props` is how actions take effect.
*/
export interface EntityHandle {
id: string;
/** Asset this entity was instantiated from (what `Is asset` compares against). */
assetId: string;
name: string;
/** Position local to `parent` (world position for top-level entities). */
x: number;
y: number;
z: number;
props: PropertyBag;
/** The entity this one is parented to; children move with their parent. */
parent: EntityHandle | null;
}
/** World position of a handle: its local position plus those of all ancestors. */
export function worldPositionOf(handle: EntityHandle): { x: number; y: number; z: number } {
return sumAlongChain(handle, (h) => h.parent, (h) => h);
}
/** Whether a handle and every ancestor of it are switched on (see `properties/enabled.ts`). */
export function isHandleEnabled(handle: EntityHandle): boolean {
return enabledAlongChain(handle, (h) => h.props, (h) => h.parent);
}
/** Where the mouse is (world units) and what it did this frame. */
export interface PointerState {
x: number;
y: number;
/** Whether the pointer is over the game view at all. */
inside: boolean;
down: boolean;
/** Went down / up during this frame. */
pressed: boolean;
released: boolean;
}
/**
* Services a graph may use while running. Implemented by the runtime (BehaviorSystem) and
* by test doubles. Everything the graph does to the world goes through here, so the core
* stays free of runtime imports.
*/
export interface NodeContext {
/** The behavior entity itself. */
self: EntityHandle;
/** The behavior's parent object (the one the graph acts on), if any. */
owner: EntityHandle | null;
/** Mutable variable state of this behavior instance. */
variables: PropertyBag;
/** Seconds since the world started and since the last tick. */
time: number;
dt: number;
findByName(name: string): EntityHandle | null;
isKeyDown(key: string): boolean;
/** Mouse state of this frame, in world units. */
pointer: PointerState;
/**
* Whether a world point lies on `target` – on its colliders when it has any, otherwise on
* its own footprint or that of anything parented below it (so a button made of a container
* with a sprite and a label is hit as a whole).
*/
hitTest(target: EntityHandle, x: number, y: number): boolean;
/**
* Whether any collider of `a` overlaps any collider of `b` right now. A collider entity
* stands for itself; any other entity stands for its direct collider children.
*/
isTouching(a: EntityHandle, b: EntityHandle): boolean;
/**
* Moves `target` by (dx, dy) in local units, stopping its solid colliders at other solid
* colliders axis by axis (x first, then y) so it slides along walls. Reports which axes hit.
*/
moveAndSlide(target: EntityHandle, dx: number, dy: number): { blockedX: boolean; blockedY: boolean };
log(message: string): void;
/**
* Places a new instance of an asset into the running scene and returns it. The position is
* local to `parent` (world when none). Returns null when the asset does not exist or cannot
* be placed (a scene). Spawned behaviors run their `On start` on the next tick.
*/
spawn(assetId: string, position: { x: number; y: number; z: number }, parent: EntityHandle | null): EntityHandle | null;
destroy(target: EntityHandle): void;
stop(): void;
/** Ends the run and starts it again from the saved scene (everything spawned is lost). */
restart(): void;
}