Restructured per ADR-0038: Abstract + bold-list Badges + Topology H2 + H3-API-Subsections (one per public function) + Conventions/Consumer pattern/CHANGELOG/References. Topology auto-populated via Sporel.exe --lint --fix. Pre-commit hook installed via --install-hooks. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.6 KiB
lib-core.interaction
Proximity-trigger + action-dispatch. Register triggers with (target_x, target_y, range, action_name, callback); per-frame update(actor_x, actor_y) checks distance + was_action_pressed and fires the nearest matching trigger per action_name.
Version: 0.1.0
Lib-ID: lib-core.interaction
Requires: lib-core.input v>=0.4.0
Tags: interaction, trigger, proximity, dispatch
Topology
graph LR
this["lib-core.interaction"]
lib_core_input["lib-core.input"]
this --> lib_core_input
API
interaction.register(target_x, target_y, range, action_name, callback)
Syntax: interaction.register(target_x: number, target_y: number, range: number, action_name: string, callback: fun(info: table)) -> id
Example:
local id = interaction.register(144, 144, 40, "interact", function(info)
engine.print("you pressed interact at distance " .. info.distance)
end)
Description: Registers a proximity-trigger. Range is scalar pixel-radius. When the action's press-edge fires inside range, the callback is called with info = { actor_x, actor_y, target_x, target_y, distance, trigger_id, action_name }. Returns an opaque id used for unregister. Loud error(...) on misuse (non-number coords, non-positive range, non-string action, non-function callback).
interaction.unregister(id)
Syntax: interaction.unregister(id: id) -> void
Description: Removes a trigger. Silent no-op if id is unknown.
interaction.update(actor_x, actor_y)
Syntax: interaction.update(actor_x: number, actor_y: number) -> void
Example:
function update(ctx, dt)
interaction.update(player_center_x, player_center_y)
end
Description: Per-frame proximity-check + dispatch. Per action_name, only the NEAREST in-range trigger fires that frame; different action_names are independent (all may fire same frame).
interaction.list()
Syntax: interaction.list() -> {id: id, target_x: number, target_y: number, range: number, action_name: string}[]
Description: Returns an array of trigger-records. Debug + UI inspection.
interaction.trigger_count()
Syntax: interaction.trigger_count() -> integer
Description: Returns the number of currently registered triggers.
Conventions
- Targets are points (not AABBs in v0.1.0).
rangeis scalar pixel-radius. - Distance:
engine.spatial.distance(actor, target) <= range. - Multi-match resolution: per
action_name, only NEAREST in-range trigger fires per update. - Was-pressed semantics:
input.was_action_pressed(single-frame edge). - Silent-accept for
action_namethat hasn't been bound withlib-core.input— trigger simply never fires. - Callback errors bubble up (no pcall-wrap in v0.1.0).
Consumer pattern
local interaction = require("lib-core.interaction")
local input = require("lib-core.input")
input.bind("interact", { "e" })
local sign = { x = 144, y = 144, text = "Hier steht: ..." }
interaction.register(sign.x, sign.y, 40, "interact", function(info)
engine.print(sign.text)
end)
function update(ctx, dt)
interaction.update(player_center_x, player_center_y)
end
CHANGELOG
v0.1.0 (P.0)
- Initial release: register/unregister + per-frame proximity + nearest-per-action dispatch.
References
- Spec v0.1.0 (P.0):
meta/docs/superpowers/specs/2026-05-10-p0-lib-interaction-design.md - ADR-0001 (engine knows verbs, libs bring nouns)
- ADR-0031 (pixel-convention: Y-down-positive)
- ADR-0038 (API-Doc-Convention)