48 lines
1.7 KiB
TypeScript
48 lines
1.7 KiB
TypeScript
import type { RenderPrototype, RenderTransform } from "../render/RenderScene"
|
|
import type { Collider } from "../world/Collider"
|
|
|
|
/** Open actor behavior and representation. Concrete definitions are ordinary game
|
|
* objects referenced directly by instances. */
|
|
export type ActorDefinition<State, World> = {
|
|
prototype: RenderPrototype
|
|
update: (state: State, dt: number, world: World) => void
|
|
transform: (state: State) => RenderTransform
|
|
collider?: (state: State, world: World) => Collider | null
|
|
}
|
|
|
|
/** Type-erased live actor. `create` captures concrete state safely, allowing one
|
|
* level to hold unrelated actor state types without a content union. */
|
|
export type Actor<World> = {
|
|
readonly definition: object
|
|
readonly prototype: RenderPrototype
|
|
readonly updateState: (dt: number, world: World) => void
|
|
readonly readTransform: () => RenderTransform
|
|
readonly readCollider: (world: World) => Collider | null
|
|
}
|
|
|
|
export namespace Actor {
|
|
export function create<State, World>(
|
|
definition: ActorDefinition<State, World>,
|
|
state: State,
|
|
): Actor<World> {
|
|
return {
|
|
definition,
|
|
prototype: definition.prototype,
|
|
updateState: (dt, world) => definition.update(state, dt, world),
|
|
readTransform: () => definition.transform(state),
|
|
readCollider: (world) => definition.collider?.(state, world) ?? null,
|
|
}
|
|
}
|
|
|
|
export function update<World>(actor: Actor<World>, dt: number, world: World): void {
|
|
actor.updateState(dt, world)
|
|
}
|
|
|
|
export function transform<World>(actor: Actor<World>): RenderTransform {
|
|
return actor.readTransform()
|
|
}
|
|
|
|
export function collider<World>(actor: Actor<World>, world: World): Collider | null {
|
|
return actor.readCollider(world)
|
|
}
|
|
}
|