feat(0.2.0): Sign as composition-Entity (Phase A.3)

Refactor spine-prototype to use lib-core.composition for the Sign:
template defines sprite_color + sprite_w + sprite_h + text + position;
create instantiates with per-instance position + text override.
Render switches from direct draw_rect to render.draw_entities{tag=
"renderable"}; interaction.register reads position from entity-properties.

Direct hardcoded `local sign = {x, y, text}` Lua-local + SIGN_R/G/B
constants entfernt. Sign demo-behavior identisch (12×12 yellow rect at
tile-center (4,4) = (144,144); E within 40px → print text).

Bumps: render dep 0.1.0 → 0.2.0; +composition v0.1.0; module 0.1.0 →
0.2.0.

Stones + Player bleiben Lua-locals (A.5/A.6 territory).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Axel Meyer
2026-06-09 13:45:27 +00:00
parent d55b9fe4d9
commit fcf8f80b1e
2 changed files with 39 additions and 13 deletions

View File

@@ -5,7 +5,8 @@ local input = require("lib-core.input")
local player = require("lib-core.player_control")
local interaction = require("lib-core.interaction")
local selection = require("lib-core.selection")
local command = require("lib-core.command")
local command = require("lib-core.command")
local composition = require("lib-core.composition")
local demo_map = maps.load("maps/demo.map.json")
maps.set_current(demo_map)
@@ -63,10 +64,28 @@ player.bind_movement("move_left", "move_right", "move_up", "move_down")
local PLAYER_R, PLAYER_G, PLAYER_B = 200, 60, 80
-- Sign as module-local (actor deferred — see actor-deferral spec)
-- Tile (4,4) center: 4*32+16 = 144 px in walkable grass-area
local sign = { x = 144, y = 144, text = "Hier steht: Willkommen im Spine." }
local SIGN_R, SIGN_G, SIGN_B = 220, 200, 60
-- Sign-Template (Phase A.1 — composition + Inactive-Entity-Pattern).
-- Position-Property is the visual CENTER per render.draw_entities convention.
composition.define_template{
id = "sign",
properties = {
sprite_color = engine.render.rgb(220, 200, 60),
sprite_w = 12,
sprite_h = 12,
text = "default sign text",
position = {x = 0, y = 0},
},
tags = {"renderable"},
}
-- Instantiate the demo sign at tile (4,4)-center = 144 px in grass-area.
local sign = composition.create{
template = "sign",
properties = {
position = {x = 144, y = 144},
text = "Hier steht: Willkommen im Spine.",
},
}
-- P.3.6/P.3.7: 6 stones as selectables + movable units (3 speed classes).
local stones = {
@@ -102,9 +121,16 @@ function init(ctx)
engine.print(string.format("player: pos=(%d,%d) size=%dx%d speed=%d",
p.x, p.y, s.w, s.h, player.speed()))
interaction.register(sign.x, sign.y, 40, "interact", function(info)
engine.print(sign.text)
end)
-- Position + text are read once at registration; the sign is stationary
-- in v0.1 so a snapshot is correct. If it ever moves, the interaction-
-- API would need closure-form anchor (currently raw-number-only).
interaction.register(
sign:get_property("position.x"),
sign:get_property("position.y"),
40, "interact",
function(info)
engine.print(sign:get_property("text"))
end)
engine.print(string.format("interaction: %d trigger(s) registered",
interaction.trigger_count()))
-- P.3.6/P.3.7: Register each stone as selectable AND movable.
@@ -128,9 +154,8 @@ function render(ctx)
engine.render.clear_color(engine.render.rgb(20, 20, 30))
camera.begin()
maps.draw_map_pre_entities()
-- draw sign on top of map
engine.render.draw_rect(sign.x - 6, sign.y - 6, 12, 12,
engine.render.rgb(SIGN_R, SIGN_G, SIGN_B))
-- draw all renderable entities (Phase A.2: tag-based render)
r_lib.draw_entities{ tag = "renderable" }
-- P.3.6: draw stones
for _, s in ipairs(stones) do
engine.render.draw_rect(s.x, s.y, s.w, s.h,