feat(0.7.0): Player als Actor-Entity, Puppet syncs (Phase A.6)
Refactor: Player gesplittet in zwei Handles. state.actor (composition- Entity) ist canonical position-owner. state.player (puppet handle) bleibt für Animation + Render zuständig und syncs each frame via puppet.move_to(state.player, actor.position(state.actor)). vagrant_player-Template ist UNTAGGED — render.draw_entities sieht ihn nicht, da puppet.render(state.player) das Sprite-Rendering schon macht. Tag-Konflikt vermieden. Movement-Refactor in M.update: - CI_DRIVE-Branch: actor.move(state.actor, dx*speed*dt, 0) - Normal-Movement: actor.move(state.actor, mx*speed*dt, my*speed*dt) - Sync-Punkt nach beiden Branches: puppet.move_to(state.player, actor.position(state.actor)) - interaction.update + camera.set_target lesen actor.position Sprint-Logic unverändert (eigene WALK_SPEED constants; movement_speed auf actor ist informational/120). Bumps: 0.6.0 → 0.7.0; +actor v0.1.0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
63
init.lua
63
init.lua
@@ -1,4 +1,4 @@
|
||||
-- sporel-module-vagrant-skeleton v0.6.0
|
||||
-- sporel-module-vagrant-skeleton v0.7.0
|
||||
-- Sprite-mode test-chamber: 13-bone humanoid puppet + sprite-tilemap +
|
||||
-- hardcoded furniture. Subterrain-style puppet control model:
|
||||
-- multi-look-target (aim/soft), slerp body rotation, hip-static legs,
|
||||
@@ -9,6 +9,12 @@
|
||||
-- render-path via render.draw_entities{tag="renderable"}). Bed + Bench
|
||||
-- remain hardcoded atlas-furniture in v0.6.0 (no interaction-trigger,
|
||||
-- no demo-pflicht to be entities yet).
|
||||
--
|
||||
-- v0.7.0 (Phase A.6): Player split — actor-entity (state.actor) owns
|
||||
-- canonical position; puppet (state.player) syncs from actor each frame
|
||||
-- via puppet.move_to. Movement-Logic moves the actor; puppet renders.
|
||||
-- Untagged actor — render.draw_entities doesn't see it; puppet handles
|
||||
-- the render via puppet.render(state.player) unchanged.
|
||||
|
||||
local input = require("lib-core.input")
|
||||
local camera = require("lib-core.camera")
|
||||
@@ -17,6 +23,7 @@ local maps = require("lib-core.maps")
|
||||
local puppet = require("lib-core.puppet")
|
||||
local interaction = require("lib-core.interaction")
|
||||
local composition = require("lib-core.composition")
|
||||
local actor = require("lib-core.actor")
|
||||
|
||||
local M = {}
|
||||
|
||||
@@ -47,8 +54,23 @@ composition.define_template{
|
||||
tags = {"renderable"},
|
||||
}
|
||||
|
||||
-- Player-Actor-Template (Phase A.6). Vagrant's player is an actor whose
|
||||
-- position drives the puppet (sync each frame). NOT tagged renderable —
|
||||
-- the puppet handles rendering, render.draw_entities doesn't see this
|
||||
-- entity. movement_speed is informational; vagrant's sprint-logic uses
|
||||
-- its own WALK_SPEED constants directly for the per-frame move.
|
||||
composition.define_template{
|
||||
id = "vagrant_player",
|
||||
properties = {
|
||||
position = {x = 0, y = 0},
|
||||
movement_speed = 120, -- WALK_SPEED_NORMAL
|
||||
},
|
||||
tags = {}, -- intentionally untagged: not renderable
|
||||
}
|
||||
|
||||
local state = {
|
||||
player = nil,
|
||||
player = nil, -- puppet handle (state-bearing for animation)
|
||||
actor = nil, -- composition-entity owning position
|
||||
map = nil,
|
||||
world_tex = nil, -- subterrain_world atlas diffuse handle (used for bed/bench)
|
||||
furniture_uvs = nil, -- name -> { x, y, w, h } from atlas JSON
|
||||
@@ -170,6 +192,16 @@ function M.init(ctx)
|
||||
maps.set_current(state.map)
|
||||
maps.load_textures(aliases)
|
||||
|
||||
-- Player-Actor owns canonical position (Phase A.6). Puppet is spawned
|
||||
-- at the same coords and stays in sync via puppet.move_to each frame.
|
||||
state.actor = actor.create{
|
||||
template = "vagrant_player",
|
||||
properties = {
|
||||
position = {x = 320, y = 240},
|
||||
movement_speed = 120, -- WALK_SPEED_NORMAL
|
||||
},
|
||||
}
|
||||
|
||||
-- Puppet rig + sprite textures.
|
||||
local rig = puppet.load_rig("rigs/humanoid.rig.json", aliases)
|
||||
state.player = puppet.spawn(rig, { x = 320, y = 240 })
|
||||
@@ -300,28 +332,30 @@ function M.update(ctx, dt)
|
||||
if ci_drive_frame > 20 and ci_drive_frame <= 40 then
|
||||
dx = 1; dy = 0
|
||||
moving = true
|
||||
local pos = puppet.position(state.player)
|
||||
puppet.move_to(state.player,
|
||||
pos.x + dx * WALK_SPEED_NORMAL * dt, pos.y)
|
||||
actor.move(state.actor, dx * WALK_SPEED_NORMAL * dt, 0)
|
||||
else
|
||||
moving = false
|
||||
end
|
||||
end
|
||||
|
||||
-- Move puppet.
|
||||
-- Move actor (position-owner). Puppet syncs from actor below.
|
||||
if moving and not CI_DRIVE then
|
||||
local len = math.sqrt(dx * dx + dy * dy)
|
||||
state.move_x = dx / len
|
||||
state.move_y = dy / len
|
||||
local pos = puppet.position(state.player)
|
||||
puppet.move_to(state.player,
|
||||
pos.x + state.move_x * current_walk_speed * dt,
|
||||
pos.y + state.move_y * current_walk_speed * dt)
|
||||
actor.move(state.actor,
|
||||
state.move_x * current_walk_speed * dt,
|
||||
state.move_y * current_walk_speed * dt)
|
||||
elseif not moving then
|
||||
state.move_x = 0
|
||||
state.move_y = 0
|
||||
end
|
||||
|
||||
-- Sync puppet position from actor (Phase A.6: actor is source-of-truth).
|
||||
-- Done once per frame after movement, before puppet.update consumes
|
||||
-- position for animation.
|
||||
puppet.move_to(state.player, actor.position(state.actor))
|
||||
|
||||
-- CI_DRIVE move_x/move_y for anim selection.
|
||||
if CI_DRIVE and moving then
|
||||
state.move_x = dx
|
||||
@@ -344,12 +378,11 @@ function M.update(ctx, dt)
|
||||
puppet.set_look_target(state.player, "soft", wx, wy)
|
||||
|
||||
-- Interaction: dispatches the nearest matching proximity-trigger when
|
||||
-- 'interact' was pressed this frame. Uses player.position as actor.
|
||||
local pos = puppet.position(state.player)
|
||||
interaction.update(pos.x, pos.y)
|
||||
-- 'interact' was pressed this frame. Uses actor.position as anchor.
|
||||
interaction.update(actor.position(state.actor))
|
||||
|
||||
-- Camera follows puppet position each frame.
|
||||
camera.set_target(pos.x, pos.y)
|
||||
-- Camera follows actor position each frame.
|
||||
camera.set_target(actor.position(state.actor))
|
||||
camera.update(dt)
|
||||
|
||||
puppet.update(dt)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "vagrant-skeleton",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.0",
|
||||
"kind": "module",
|
||||
"api": "^0.1",
|
||||
"ci_frames": 60,
|
||||
@@ -16,6 +16,7 @@
|
||||
{"id": "lib-core.camera", "version": "0.3.0"},
|
||||
{"id": "lib-core.render", "version": "0.2.0"},
|
||||
{"id": "lib-core.composition", "version": "0.1.0"},
|
||||
{"id": "lib-core.actor", "version": "0.1.0"},
|
||||
{"id": "lib-core.maps","version":"0.5.7"},
|
||||
{"id": "lib-core.puppet", "version": "0.5.0"},
|
||||
{"id": "lib-core.interaction", "version": "0.1.0"},
|
||||
|
||||
Reference in New Issue
Block a user