Axel Meyer b8e745e452 feat(0.2.0): BREAKING — Actor-Entity statt Lua-locals (Phase A.6)
Refactor: position / size / speed leben jetzt auf einer Actor-Entity
(lib-core.actor + lib-core.composition); player_control hält nur noch
die Action-Bindings und das per-frame Update.

Removed surface (use actor.* / composition.* instead):
  M.set_position / M.position / M.set_size / M.size /
  M.set_speed / M.speed

Neuer Flow:
  composition.define_template{id="player", properties={position,
      movement_speed, sprite_w, sprite_h, ...}, ...}
  local p = actor.create{template="player", properties={...}}
  player_control.bind_movement(...)
  player_control.update(p, dt)  -- liest position/movement_speed/sprite_w/h
                                -- aus dem actor; AABB-Collision um center,
                                -- commit via actor.move oder no-op

position.x/.y wird als visual CENTER behandelt (Phase-A Konvention).
4-corner-AABB-Check verschiebt sich entsprechend.

DEPRECATED-MVP-Marker auf :99 entfernt (actor-integration realisiert).

Bumps: 0.1.0 → 0.2.0 (BREAKING, pre-1.0 minor); +actor v0.1.0 dep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-09 14:12:56 +00:00
2026-05-16 18:04:37 +02:00

lib-core.player_control

Input-driven movement for a single Actor-Entity. Reads input-direction via lib-core.input, applies 4-corner-AABB collision against lib-core.maps.is_walkable around the actor's visual center, then commits via actor.move. All-or-nothing block (no wall-sliding).

Version: 0.2.0 Lib-ID: lib-core.player_control Requires: lib-core.maps v>=0.5.7, lib-core.input v>=0.4.0, lib-core.actor v>=0.1.0 Tags: player, movement, aabb, collision, actor

Topology

graph LR
  this["lib-core.player_control"]
  lib_core_maps["lib-core.maps"]
  this --> lib_core_maps
  lib_core_input["lib-core.input"]
  this --> lib_core_input
  lib_core_actor["lib-core.actor"]
  this --> lib_core_actor
  engine["engine.*"]
  this --> engine

Scope (v0.2.0 — Phase A.6 refactor)

Breaking change vs v0.1.0: position / size / speed are no longer stored in player_control; they live on the actor-entity (read via actor.position / actor.movement_speed / entity properties). The lib retains only the per-frame update plus the action-bindings.

This decouples player-control from any single-player assumption: each call passes its own actor-handle. Multi-actor controllers (e.g. squad- demos, RTS-style click-to-move) compose by holding multiple actor-handles externally.

API

player_control.bind_movement(left, right, up, down)

Syntax: player_control.bind_movement(left: string, right: string, up: string, down: string) -> void

Example:

input.bind("move_left",  { "a", "left" })
input.bind("move_right", { "d", "right" })
input.bind("move_up",    { "w", "up" })
input.bind("move_down",  { "s", "down" })
player_control.bind_movement("move_left", "move_right", "move_up", "move_down")

Description: Registers 4 input-action names for WASD-style direction. Until called, update(actor, dt) is a silent no-op (debug- friendly).

player_control.update(actor_handle, dt)

Syntax: player_control.update(actor_handle, dt: number) -> void

Example:

function update(ctx, dt)
    player_control.update(state.player, dt)
end

Description: Reads bound actions; computes direction-vector via lib-core.input.direction; reads the actor's position (center), movement_speed, and sprite_w/sprite_h properties; predicts a new center position; runs 4-corner-AABB walkability check around the new center; commits via actor.move(handle, ncx-cx, ncy-cy) on pass, no-op on blocked (all-or-nothing).

Loud-Error if actor_handle is nil. Silent no-op before bind_movement is called.

Conventions

  • Position is visual CENTER of the actor (matches render.draw_entities Phase-A convention).
  • AABB-Collision around the center: the 4 corners are (cx ± w/2, cy ± h/2).
  • All-or-nothing block on collision (wall-sliding deferred).
  • Caller owns rendering (lib has no draw fn). Pair with lib-core.render.draw_entities{tag = "renderable"}.
  • Module composes camera-follow via camera.set_target(actor.position(handle)).
  • Y-down-positive per ADR-0031.

Consumer pattern

local player_control = require("lib-core.player_control")
local actor          = require("lib-core.actor")
local composition    = require("lib-core.composition")
local input          = require("lib-core.input")
local camera         = require("lib-core.camera")

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"},
}

input.bind("move_left",  { "a", "left" })
input.bind("move_right", { "d", "right" })
input.bind("move_up",    { "w", "up" })
input.bind("move_down",  { "s", "down" })

local p = actor.create{
    template = "player",
    properties = {
        position       = {x = 244, y = 244},
        movement_speed = 200,
    },
}
player_control.bind_movement("move_left", "move_right", "move_up", "move_down")

function update(ctx, dt)
    player_control.update(p, dt)
    camera.set_target(actor.position(p))
end

function render(ctx)
    -- Player gets drawn together with all renderable entities.
    render.draw_entities{ tag = "renderable" }
end

CHANGELOG

v0.2.0 (Phase A.6 — 2026-06-09)

  • BREAKING: removed set_position / position / set_size / size / set_speed / speed. Use actor.position / actor.movement_speed / actor_handle:get_property("sprite_w") etc.
  • update now takes (actor_handle, dt) instead of just (dt).
  • Position is now visual-CENTER (was top-left in v0.1).
  • New dep: lib-core.actor v0.1.0.

v0.1.0 (P.0)

  • Initial release: position/size/speed + bind_movement + per-frame update with 4-corner-AABB collision.

References

  • Spec v0.1.0 (P.0): meta/docs/superpowers/specs/2026-05-09-p0-lib-player_control-design.md
  • Spec v0.2.0 (Phase A): meta/docs/superpowers/specs/2026-06-09-phase-A-inactive-entities-composition-actor-reentry-design.md
  • ADR-0001 (engine knows verbs, libs bring nouns)
  • ADR-0031 (pixel-convention: Y-down-positive)
  • ADR-0038 (API-Doc-Convention)
Description
P.0.lib.player_control � player movement + AABB-wall-collision
Readme 43 KiB
Languages
Lua 89.5%
Shell 10.5%