Compare commits

..

17 Commits

Author SHA1 Message Date
calic
40d8ddd29d fix(deps): cascade composition 0.4.0 + crafting 0.5.0 pins
Phase J (2026-08-03) bumped lib-core.composition 0.3.0->0.4.0 and
lib-core.crafting 0.3.0->0.5.0, but only vagrant-skeleton and
lib-core.crafting themselves were updated. Dependent manifests kept the
old pins, so dep-fetcher saw disagreeing pins on the same lib and
refused to start both spine-prototype (ENGINE_ERR_LIB_DEP_MISSING,
rc=19) and vagrant-skeleton ("dep check failed", conflict on
lib-core.composition + lib-core.crafting).

Unify all pins on the on-disk versions. No code changes required:
composition 0.4.0 is purely additive (the quality/condition loud-error
was removed; no signature changed), and crafting-display only consumes
crafting.can_craft + crafting.list_recipes, both still present, and
never referenced the `form` field retired by ADR-0055.

README "Requires:" lines synced to match the manifests (Gate 3).

milestone-check.sh: GREEN (build, ctest, smoke, devwrap-ci,
test-all-modules + anomaly scan). vagrant-skeleton headless run clean
at 60 CI frames.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 11:27:22 +02:00
calic
d4c2eaa3cd chore(deps): bump lib-core.render to 0.3.0 (cascade — additive sprite_scale)
No code change. v0.3.0 adds an optional sprite_scale property on
draw_entities path-1; spine-prototype doesn't set it, so default
1.0 preserves v0.2.0 behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-21 11:45:03 +02:00
Axel Meyer
83eef8e5a7 docs: CR-5 — README v0.1.0->v0.3.2, Requires +actor/composition (10 Deps), Pins synct
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 14:47:56 +00:00
Axel Meyer
c9f97d131e chore: bump lib-core.composition dep to 0.3.0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 11:57:40 +02:00
Axel Meyer
581b2a427a chore: bump lib-core.composition dep to 0.2.0 2026-06-13 14:07:46 +02:00
Axel Meyer
05e50a85ff feat: ship manifest.launcher.md for master-detail launcher 2026-06-11 07:57:35 +02:00
Axel Meyer
0227aad47d feat(0.3.0): Player als Actor-Entity (Phase A.6)
Refactor spine-prototype für player_control v0.2.0 + actor:
- composition.define_template{id="player", properties={position,
  movement_speed, sprite_color, sprite_w, sprite_h}, tags={"renderable"}}
- actor.create instanziiert Player bei map-center
- player_control.update(player, dt) ersetzt player.update(dt)
- camera.set_target / interaction.update lesen via actor.position(player)
  (Lua-multi-return)
- Manueller draw_rect für Player raus — Player wird via
  render.draw_entities{tag="renderable"} zusammen mit Sign gezeichnet
- Draw-order: stones zuerst, dann Entities (Sign + Player). Stones-vs-
  Player-Overlay-Issue in der Praxis nicht relevant (Positionen kollidieren
  nicht)

PLAYER_R/G/B Konstanten entfernt (Color jetzt im Template).

Bumps: 0.2.0 → 0.3.0; +actor v0.1.0; player_control 0.1.0 → 0.2.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-09 14:13:17 +00:00
Axel Meyer
fcf8f80b1e 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>
2026-06-09 13:45:27 +00:00
Axel Meyer
d55b9fe4d9 chore(deps): bump lib-core.maps 0.5.6 -> 0.5.7
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 22:44:25 +02:00
Axel Meyer
7781f8a089 chore(deps): bump lib-core.maps 0.5.5 -> 0.5.6
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 17:19:15 +02:00
Axel Meyer
c49f34efac ESC -> lib-management.launcher (renamed per ADR-0045)
The launcher migrated from lib-sporel.launcher to lib-management.launcher
per ADR-0045 (three-tier library naming). Update the ESC handler to
target the new module id so quit-to-launcher continues to work.
2026-05-31 00:22:25 +02:00
calic
f00b8ba76a chore(deps): bump lib-core.maps 0.5.4 -> 0.5.5 2026-05-29 09:56:51 +02:00
calic
5f39b43554 chore(deps): bump lib-core.maps 0.5.3 -> 0.5.4 2026-05-29 01:37:43 +02:00
calic
025ddf3687 chore(deps): bump lib-core.maps 0.5.2 -> 0.5.3 2026-05-29 01:29:23 +02:00
calic
7e0acd9256 chore(deps): bump lib-core.maps 0.4.0 -> 0.5.2 2026-05-28 23:53:21 +02:00
Axel Meyer
037b3ad2c9 Bump lib-core.maps dep to 0.4.0
Picks up the new write APIs (set_cell_gid, set_roof, save_to_disk).
No source changes — lib is purely additive.
2026-05-24 00:53:42 +02:00
Axel Meyer
782387473e Switch spine-prototype demo to fa_terrain_v1 atlas
Replaces the inline color-only demo_tilemap with a dep on the
prototype-fa-starter asset lib and its baked fa_terrain_v1 atlas.
The map atlases[] alias-string is updated to fa_terrain_v1; the
packed-u32 layer-tiles keep their numeric values because the baker
assigned the expected IDs (1 for grass_field surface tile, 2 for
stone_wall_brick wall tile). Adds maps.load_textures() call in init.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 23:16:39 +02:00
6 changed files with 124 additions and 57 deletions

View File

@@ -2,9 +2,9 @@
Foundational end-to-end demo module from the bootstrap phase. Loads `lib-core.maps` and demonstrates lib-composition with basic player movement, free-pan camera, click-select, RMB-move, and proximity-triggered interactions. Self-exits after 30 frames for CI.
**Version:** 0.1.0
**Version:** 0.3.2
**Module-ID:** spine-prototype
**Requires:** lib-core.maps v>=0.1.1, lib-core.render v>=0.1.0, lib-core.camera v>=0.3.0, lib-core.selection v>=0.1.0, lib-core.input v>=0.4.0, lib-core.player_control v>=0.1.0, lib-core.interaction v>=0.1.0, lib-core.command v>=0.1.0
**Requires:** lib-core.maps v0.5.7, lib-core.render v0.2.0, lib-core.camera v0.3.0, lib-core.selection v0.1.0, lib-core.input v0.4.0, lib-core.player_control v0.2.0, lib-core.actor v0.1.0, lib-core.interaction v0.1.0, lib-core.command v0.1.0, lib-core.composition v0.4.0, lib-asset.prototype-fa-starter v0.2.0
**Tags:** demo, skeleton, foundational, tile-map
## Topology
@@ -47,7 +47,7 @@ graph LR
## Demonstrates
- End-to-end bootstrap of a module: manifest deps -> init -> update -> render -> cleanup.
- Lib-composition: 8 libs (maps, render, camera, input, selection, command, player_control, interaction) wired together in one module.
- Lib-composition: 10 libs (maps, render, camera, input, selection, command, player_control, actor, interaction, composition) wired together in one module, plus the `lib-asset.prototype-fa-starter` asset pack.
- Tile-based map loading + walkability queries via `lib-core.maps`.
- Free-pan + follow camera through `lib-core.camera` (`set_target`, `bind_pan_keys`, `update`).
- Click-select / drag-box / modifier-keys via `lib-core.selection`.

View File

@@ -1,8 +0,0 @@
{
"id": "demo_tilemap",
"tile_size": 32,
"tiles": [
{"id": "grass", "walkable": true, "color": [110, 170, 80]},
{"id": "stone", "walkable": false, "color": [120, 120, 120]}
]
}

120
init.lua
View File

@@ -1,14 +1,17 @@
local maps = require("lib-core.maps")
local r_lib = require("lib-core.render")
local camera = require("lib-core.camera")
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 maps = require("lib-core.maps")
local r_lib = require("lib-core.render")
local camera = require("lib-core.camera")
local input = require("lib-core.input")
local player_control = require("lib-core.player_control")
local interaction = require("lib-core.interaction")
local selection = require("lib-core.selection")
local command = require("lib-core.command")
local composition = require("lib-core.composition")
local actor = require("lib-core.actor")
local demo_map = maps.load("maps/demo.map.json")
maps.set_current(demo_map)
maps.load_textures(engine.module.asset_aliases())
local m_size = maps.size()
local t_size = maps.tile_size()
@@ -55,17 +58,52 @@ camera.enable_pan_edge()
-- unsichtbar in follow-mode wegen set_target-override jeden Frame).
camera.set_pan_enabled("keys", false)
-- Configure player: defaults are 24x24 + 200 px/sec; place at map-center
local p_size = player.size()
player.set_position(map_center_x - p_size.w / 2, map_center_y - p_size.h / 2)
player.bind_movement("move_left", "move_right", "move_up", "move_down")
-- Player-Template (Phase A.5/A.6 — Actor + composition).
-- position is the visual CENTER per render.draw_entities convention.
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"},
}
local PLAYER_R, PLAYER_G, PLAYER_B = 200, 60, 80
-- Spawn the player at map-center; bind WASD movement.
local player = actor.create{
template = "player",
properties = {
position = {x = map_center_x, y = map_center_y},
movement_speed = 200,
},
}
player_control.bind_movement("move_left", "move_right", "move_up", "move_down")
-- 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 = {
@@ -96,14 +134,22 @@ function init(ctx)
local t = camera.target()
engine.print(string.format("camera: target=(%d,%d) zoom=%.2f", t.x, t.y, camera.zoom()))
engine.print(string.format("input: %d actions bound", input.action_count()))
local p = player.position()
local s = player.size()
local px, py = actor.position(player)
local sw = player:get_property("sprite_w")
local sh = player:get_property("sprite_h")
engine.print(string.format("player: pos=(%d,%d) size=%dx%d speed=%d",
p.x, p.y, s.w, s.h, player.speed()))
px, py, sw, sh, actor.movement_speed(player)))
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.
@@ -127,19 +173,17 @@ 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))
-- P.3.6: draw stones
-- P.3.6: draw stones (still Lua-tables; future-slice makes them
-- entities too)
for _, s in ipairs(stones) do
engine.render.draw_rect(s.x, s.y, s.w, s.h,
engine.render.rgb(s.color[1], s.color[2], s.color[3]))
end
-- draw player on top of map/stones
local p = player.position()
local sz = player.size()
engine.render.draw_rect(p.x, p.y, sz.w, sz.h,
engine.render.rgb(PLAYER_R, PLAYER_G, PLAYER_B))
-- Draw all renderable entities (Sign + Player). Drawn AFTER
-- stones so the Player visually overlays stone-occlusions —
-- in practice positions don't collide, but the layering
-- intent is preserved.
r_lib.draw_entities{ tag = "renderable" }
-- P.3.6: highlights over selected entities (world-space)
selection.render_highlights()
maps.draw_map_post_entities()
@@ -151,7 +195,7 @@ end
function update(ctx, dt)
if input.was_action_pressed("quit") then
-- ADR-0028: ESC returns to launcher per P.3.4.
engine.switch_module("lib-sporel.launcher")
engine.switch_module("lib-management.launcher")
return
end
@@ -163,10 +207,8 @@ function update(ctx, dt)
-- Player + interaction nur in follow-mode (in free-cam ist player pausiert).
if not free_cam_mode then
player.update(dt)
local p = player.position()
local s = player.size()
interaction.update(p.x + s.w / 2, p.y + s.h / 2)
player_control.update(player, dt)
interaction.update(actor.position(player))
end
-- Pan-Summation jeden Frame (keys nur wenn enabled; drag + edge always-on).
@@ -176,9 +218,7 @@ function update(ctx, dt)
if not free_cam_mode then
-- Follow-cam: set_target jeden Frame -> drag/edge "drift" wird unsichtbar.
local p = player.position()
local s = player.size()
camera.set_target(p.x + s.w / 2, p.y + s.h / 2)
camera.set_target(actor.position(player))
end
-- CI-conditional self-exit (unverändert aus P.0):

29
manifest.launcher.md Normal file
View File

@@ -0,0 +1,29 @@
---
{
"summary":"Spine prototype demo — RMB-move + proximity sign",
"author":"calic",
"tags":["demo","foundational","tile-map"],
"teaser_images":[]
}
---
# Spine Prototype
Foundational end-to-end demo from the bootstrap phase.
## What it shows
- Tile-map loading via lib-core.maps
- Click-select + drag-box-select units
- Right-mouse-button move command
- Proximity-triggered sign interaction (press E near it)
- Free-pan camera toggle (Tab)
## Controls
- WASD / arrow-keys: move
- E: interact
- Tab: toggle free-pan camera
- Mouse-left: select units
- Mouse-right: move-command
- ESC: quit to launcher

View File

@@ -1,18 +1,24 @@
{
"id": "spine-prototype",
"version": "0.1.0",
"version": "0.3.2",
"kind": "module",
"api": "^0.1",
"ci_frames": 30,
"entry_point": "init.lua",
"asset_aliases": {
"fa_terrain_v1": "lib-asset.prototype-fa-starter"
},
"deps": [
{"id":"lib-core.maps","version":"0.2.0"},
{"id":"lib-core.render","version":"0.1.0"},
{"id":"lib-core.maps","version":"0.5.7"},
{"id":"lib-core.render","version":"0.3.0"},
{"id":"lib-core.camera","version":"0.3.0"},
{"id":"lib-core.selection","version":"0.1.0"},
{"id":"lib-core.input","version":"0.4.0"},
{"id":"lib-core.player_control","version":"0.1.0"},
{"id":"lib-core.player_control","version":"0.2.0"},
{"id":"lib-core.actor","version":"0.1.0"},
{"id":"lib-core.interaction","version":"0.1.0"},
{"id":"lib-core.command","version":"0.1.0"}
{"id":"lib-core.command","version":"0.1.0"},
{"id":"lib-core.composition","version":"0.4.0"},
{"id":"lib-asset.prototype-fa-starter","version":"0.2.0"}
]
}

View File

@@ -2,7 +2,7 @@
"schema_version": 2,
"id": "demo",
"size": { "w": 16, "h": 16 },
"atlases": ["demo_tilemap"],
"atlases": ["fa_terrain_v1"],
"layers": {
"surface": {
"tiles": [