61 lines
2.3 KiB
Markdown
61 lines
2.3 KiB
Markdown
# lib-core.player_control
|
|
|
|
P.0 player movement lib. Single player with top-left position + size +
|
|
speed. Reads input direction via `lib-core.input`, applies 4-corner-AABB
|
|
collision against `lib-core.maps.is_walkable`, all-or-nothing block
|
|
(no wall-sliding).
|
|
|
|
- Lib-ID: `lib-core.player_control`
|
|
- Version: `0.1.0`
|
|
- Spec: `meta/docs/superpowers/specs/2026-05-09-p0-lib-player_control-design.md`
|
|
|
|
Forward-compat stubs (DEPRECATED-MVP) for wall-sliding, actor-integration,
|
|
sprite-rendering, click-to-move, drag-select, animation, velocity/momentum,
|
|
walls-collision, multi-player.
|
|
|
|
## API
|
|
- `player.set_position(x, y)` — top-left, pixel-coords
|
|
- `player.position() → {x, y}` — top-left
|
|
- `player.set_size(w, h)` — bounding box (default 24x24)
|
|
- `player.size() → {w, h}`
|
|
- `player.set_speed(px_per_sec)` — default 200
|
|
- `player.speed() → number`
|
|
- `player.bind_movement(left_action, right_action, up_action, down_action)`
|
|
- `player.update(dt)` — reads bound actions, predicts next pos, AABB-collision-check, mutates position
|
|
|
|
## Conventions
|
|
- Position is top-left corner of player AABB (matches engine.render.draw_rect).
|
|
- Center calculation lives in caller: `cx = position.x + size.w/2`.
|
|
- All-or-nothing block on collision (no wall-sliding in P.0).
|
|
- Module owns rendering (lib has no draw fn). Module composes camera-follow.
|
|
- Silent no-op for `update()` before `bind_movement` (debug-friendly).
|
|
- Lua `error(...)` for setter misuse (caller-bug fast-fail).
|
|
|
|
## Consumer pattern
|
|
```lua
|
|
local player = require("lib-core.player_control")
|
|
local input = require("lib-core.input")
|
|
|
|
input.bind("move_left", { engine.input.KEY_A, engine.input.KEY_LEFT })
|
|
input.bind("move_right", { engine.input.KEY_D, engine.input.KEY_RIGHT })
|
|
input.bind("move_up", { engine.input.KEY_W, engine.input.KEY_UP })
|
|
input.bind("move_down", { engine.input.KEY_S, engine.input.KEY_DOWN })
|
|
|
|
player.set_position(244, 244)
|
|
player.bind_movement("move_left", "move_right", "move_up", "move_down")
|
|
|
|
function update(ctx, dt)
|
|
player.update(dt)
|
|
local p = player.position()
|
|
local s = player.size()
|
|
camera.set_target(p.x + s.w/2, p.y + s.h/2) -- camera follows player center
|
|
end
|
|
|
|
function render(ctx)
|
|
-- draw map first, then player on top
|
|
local p = player.position()
|
|
local s = player.size()
|
|
engine.render.draw_rect(p.x, p.y, s.w, s.h, engine.render.rgb(200, 60, 80))
|
|
end
|
|
```
|