Compare commits
19 Commits
bad48a8396
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40d8ddd29d | ||
|
|
d4c2eaa3cd | ||
|
|
83eef8e5a7 | ||
|
|
c9f97d131e | ||
|
|
581b2a427a | ||
|
|
05e50a85ff | ||
|
|
0227aad47d | ||
|
|
fcf8f80b1e | ||
|
|
d55b9fe4d9 | ||
|
|
7781f8a089 | ||
|
|
c49f34efac | ||
|
|
f00b8ba76a | ||
|
|
5f39b43554 | ||
|
|
025ddf3687 | ||
|
|
7e0acd9256 | ||
|
|
037b3ad2c9 | ||
|
|
782387473e | ||
|
|
b79dd8e472 | ||
|
|
7fac933066 |
@@ -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`.
|
||||
|
||||
@@ -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]}
|
||||
]
|
||||
}
|
||||
123
init.lua
123
init.lua
@@ -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.
|
||||
@@ -126,22 +172,21 @@ end
|
||||
function render(ctx)
|
||||
engine.render.clear_color(engine.render.rgb(20, 20, 30))
|
||||
camera.begin()
|
||||
r_lib.draw_map()
|
||||
-- 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
|
||||
maps.draw_map_pre_entities()
|
||||
-- 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()
|
||||
camera.finish()
|
||||
-- P.3.6: drag-box overlay (screen-space, after camera.finish)
|
||||
selection.render_drag_box()
|
||||
@@ -150,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
|
||||
|
||||
@@ -162,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).
|
||||
@@ -175,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
29
manifest.launcher.md
Normal 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
|
||||
@@ -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.1.2"},
|
||||
{"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"}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,48 @@
|
||||
{
|
||||
"schema_version": 2,
|
||||
"id": "demo",
|
||||
"tilemap": "demo_tilemap",
|
||||
"size": {"w": 16, "h": 16},
|
||||
"tiles": [
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
|
||||
]
|
||||
"size": { "w": 16, "h": 16 },
|
||||
"atlases": ["fa_terrain_v1"],
|
||||
"layers": {
|
||||
"surface": {
|
||||
"tiles": [
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
|
||||
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16
|
||||
]
|
||||
},
|
||||
"wall": {
|
||||
"tiles": [
|
||||
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,
|
||||
32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user