Axel Meyer e627f0097f initial: actor v0.1.0 — composition-wrapper + movement-speed-contract
Phase-A.5 implementation per
sporel-meta/docs/superpowers/specs/2026-06-09-phase-A-...
Re-Entry from P.0-Actor-Deferral (Trigger 1: Composition-Aktivierung).

Slim wrapper: actor.create validates properties.movement_speed > 0,
delegates to composition.create. actor.position reads dotted position
back as two numbers. actor.move does direct inert-write to position.x
+ position.y (engine §11 inert-write; Action-routing deferred).

DEFERRED in v0.1: Body-Slot-Aggregator, Walk-Capability, Movement-State
on entity, Action-mediated move. All have re-entry-trigger notes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-09 13:57:20 +00:00

lib-core.actor

Thin wrapper over lib-core.composition that enforces a baseline-speed contract for "actor" entities. Provides convenience helpers for position-read + position-write (inert-mediated). Doesn't track any ephemeral movement-state (vel/dir) — that stays in player_control or whatever drives the actor each frame.

Version: 0.1.0 Lib-ID: lib-core.actor Requires: lib-core.composition v>=0.1.0 Tags: actor, entity, movement

Topology

graph LR
  this["lib-core.actor"]
  lib_core_composition["lib-core.composition"]
  this --> lib_core_composition
  engine["engine.*"]
  this --> engine

Scope (v0.1.0 — Spine)

Re-Entry from P.0-Actor-Deferral (Trigger 1: Composition-Aktivierung). v0.1 is a minimal slice; intentional non-goals:

  • No Body-Slot-Aggregator. Phase D / J trigger.
  • No Walk-Capability (per ADR-0002 capabilities-as-derived). Waits for a second actor-consumer that needs capability-routing.
  • No Movement-State on the entity. vel / dir / direction-flags are ephemeral; kept in player_control (or whatever driver). Persisted ones come with a re-entry-trigger.
  • No Action-mediated move. v0.1 uses engine-§11 inert-write directly. Action-routing is the "right" path for game-state-weighty mutations but waits until a "move" Action is registered and event/effect routing matters.

API

actor.create(spec)

Syntax: actor.create({template: string, properties: table}) -> entity

Example:

-- Caller defines a template via composition first:
composition.define_template{
    id = "player",
    properties = {
        position       = {x = 0, y = 0},
        movement_speed = 200,
        sprite_color   = engine.render.rgb(200, 60, 80),
        sprite_w       = 24,
        sprite_h       = 24,
    },
    tags = {"renderable", "player"},
}

-- Then actor.create instantiates:
local p = actor.create{
    template = "player",
    properties = {
        position       = {x = 400, y = 300},
        movement_speed = 200,
    },
}

Description: Validates that properties.movement_speed is a positive number, then delegates to composition.create. Loud-Error if movement_speed is missing, non-number, or non-positive.

The caller is responsible for composition.define_template{id=...} before invoking. Actor doesn't auto-define templates.

actor.position(handle)

Syntax: actor.position(handle) -> x, y

Description: Returns the actor's current position as two numbers (x, y). Reads via entity:get_property("position.x"/"position.y"). Loud-Error if handle is nil.

actor.move(handle, dx, dy)

Syntax: actor.move(handle, dx: number, dy: number) -> void

Example:

-- Typical caller (player_control update-loop):
local speed = actor.movement_speed(player)
local move_dx, move_dy = compute_input_direction()
actor.move(player, move_dx * speed * dt, move_dy * speed * dt)

Description: Adds (dx, dy) to the actor's current position via direct inert-write. Caller does dt-scaling and any speed-multiplication upstream. v0.1 uses engine §11 inert-write — Action-routing is a future re-entry trigger (see Scope above).

actor.movement_speed(handle)

Syntax: actor.movement_speed(handle) -> number

Description: Convenience read of the actor's movement_speed property (in pixels/sec by convention; caller decides the unit).

Conventions

  • Position-Format: composite-table at authoring-time (properties = { position = {x, y} }), flattened by composition to scalar properties position.x and position.y. See Phase-A Spec §5 A-Q5 revision (2026-06-09).
  • movement_speed: pixels per second. dt-scaling applied at the caller, NOT by actor.move.

References

  • Spec: meta/docs/superpowers/specs/2026-06-09-phase-A-inactive-entities-composition-actor-reentry-design.md
  • Origin: meta/docs/superpowers/specs/2026-05-10-p0-actor-deferral.md (Trigger 1: Composition-Aktivierung)
  • Architecture: meta/docs/architecture/composition-model.md (Actor as Item-with-Body-Slot in Phase D; v0.1 is composition-only wrapper)
  • ADR-0001 (engine knows verbs, libs bring nouns)
  • ADR-0002 (capabilities as derived properties — Walk-Capability deferred)
  • ADR-0010 (read/write asymmetry — v0.1 inert-write escape hatch)
  • ADR-0038 (API-Doc-Convention)
Description
No description provided
Readme 31 KiB
Languages
Lua 100%