feat(P.3.5): Tab-toggle free-cam demo + camera dep bump 0.1.0 -> 0.2.0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Axel Meyer
2026-05-13 02:23:54 +02:00
parent f0a5e4d1b3
commit e7d80ce16c
2 changed files with 42 additions and 12 deletions

View File

@@ -23,6 +23,21 @@ input.bind("move_right", { "d", "right" })
input.bind("move_up", { "w", "up" })
input.bind("move_down", { "s", "down" })
input.bind("interact", { "e" })
-- P.3.5: Free-Cam demo (Tab toggle)
input.bind("toggle_free_cam", { "tab" })
input.bind("pan_drag", { "mouse_middle" })
-- pan_*-Actions teilen sich die Keys mit move_*-Actions (additive bindings).
input.bind("pan_left", { "a", "left" })
input.bind("pan_right", { "d", "right" })
input.bind("pan_up", { "w", "up" })
input.bind("pan_down", { "s", "down" })
camera.bind_pan_keys("pan_left", "pan_right", "pan_up", "pan_down")
camera.bind_pan_drag("pan_drag")
camera.enable_pan_edge()
-- Start in follow-mode: pan_keys aus (drag/edge bleiben enabled, sind aber
-- 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()
@@ -36,6 +51,9 @@ local PLAYER_R, PLAYER_G, PLAYER_B = 200, 60, 80
local sign = { x = 144, y = 144, text = "Hier steht: Willkommen im Spine." }
local SIGN_R, SIGN_G, SIGN_B = 220, 200, 60
-- P.3.5: Free-Cam-Mode state
local free_cam_mode = false
local frames = 0
local TARGET_FRAMES = 60
@@ -81,24 +99,36 @@ end
function update(ctx, dt)
if input.was_action_pressed("quit") then
-- ADR-0028: ESC returns to launcher rather than exiting the app.
-- If launcher is not discoverable, P.3.2 lifecycle handles via fatal.
-- ADR-0028: ESC returns to launcher per P.3.4.
engine.switch_module("lib-sporel.launcher")
return
end
player.update(dt)
-- P.3.5: Tab toggles between follow-cam and free-cam.
if input.was_action_pressed("toggle_free_cam") then
free_cam_mode = not free_cam_mode
camera.set_pan_enabled("keys", free_cam_mode)
end
-- Camera follows player center
local p = player.position()
local s = player.size()
camera.set_target(p.x + s.w / 2, p.y + s.h / 2)
-- 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)
end
-- Interaction proximity-check + dispatch
interaction.update(p.x + s.w / 2, p.y + s.h / 2)
-- Pan-Summation jeden Frame (keys nur wenn enabled; drag + edge always-on).
camera.update(dt)
-- CI-conditional self-exit: enables headless smoke runs.
-- Interactive runs (no SPOREL_CI=1) loop until ESC.
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)
end
-- CI-conditional self-exit (unverändert aus P.0):
frames = frames + 1
if os.getenv("SPOREL_CI") == "1" and frames >= TARGET_FRAMES then
engine.exit(0)

View File

@@ -7,7 +7,7 @@
"deps": [
{"id":"lib-core.maps","version":"0.1.1"},
{"id":"lib-core.render","version":"0.1.0"},
{"id":"lib-core.camera","version":"0.1.0"},
{"id":"lib-core.camera","version":"0.2.0"},
{"id":"lib-core.input","version":"0.3.0"},
{"id":"lib-core.player_control","version":"0.1.0"},
{"id":"lib-core.interaction","version":"0.1.0"}