fix(input): #87 key_pressed/key_released edges never fired under the frame loop
Since #83 the loop commits the device layer once per frame (input_drive), but a game that ALSO called Input.poll by hand committed a second time in the same frame; input_device_commit copies in_held into in_prev at the top of every commit, so the second commit left in_prev == in_held and the edges (held && !prev) could never see a transition. Fix: an in_have_frame_driver flag. The loop's input_drive sets it; a manual Input.poll under the loop then becomes a no-op returning the frame's key instead of re-committing. An entry-driven harness has no loop, so the flag stays false and each Input.poll commits a frame as before (the #7/#50 record/replay + device tests are unchanged). Frame loop now calls input_drive. Example input_edge (press edge on the down frame, release edge on the up frame). Full suite 110/0, goldens byte-identical, fixpoint holds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
bdf1a97550
commit
0497029dae
6 changed files with 64 additions and 12 deletions
|
|
@ -142,14 +142,19 @@ function input_slot_has(s: int, k: int) -> bool {
|
|||
return false
|
||||
}
|
||||
|
||||
# Advance one frame of input and return the frame's key. This is the single
|
||||
# per-frame input read: call it once at the top of a frame.
|
||||
# live — read the live key (rt_poll).
|
||||
# record — read the live key and append it to the recording.
|
||||
# replay — take the next key from the recording (the live device is ignored).
|
||||
# It also advances the multi-key device layer below (held keys, analog, mouse),
|
||||
# snapshotting or replaying the full per-frame state — #50 extends #7's tape.
|
||||
function input_poll() -> int {
|
||||
# #87 — a frame-loop game now has its device layer committed automatically by the
|
||||
# generated loop (which calls input_drive once per frame). in_have_frame_driver
|
||||
# records that a loop is driving input, so a *manual* Input.poll in a handler
|
||||
# becomes a no-op instead of committing a second time in the same frame — a double
|
||||
# commit copied in_held into in_prev twice, which destroyed the key_pressed /
|
||||
# key_released edges (in_prev ended up equal to in_held). An entry-driven harness
|
||||
# has no loop, so the flag stays false and each Input.poll commits a frame as before.
|
||||
var in_have_frame_driver: bool = false
|
||||
|
||||
# The actual per-frame input read: read the live key (or a recorded one), advance
|
||||
# the record/replay tape, and rebuild the multi-key device layer (held keys, mouse,
|
||||
# gamepad — #50). Returns the frame's key.
|
||||
function input_commit() -> int {
|
||||
input_last = input_frame
|
||||
if input_mode == 2 { # replay
|
||||
var k = 0
|
||||
|
|
@ -168,6 +173,22 @@ function input_poll() -> int {
|
|||
return k
|
||||
}
|
||||
|
||||
# Called by the generated frame loop once per frame (#83). Marks that a loop is
|
||||
# driving input so a later manual Input.poll this frame does not double-commit.
|
||||
function input_drive() -> int {
|
||||
in_have_frame_driver = true
|
||||
return input_commit()
|
||||
}
|
||||
|
||||
# Input.poll — the single per-frame input read a game can call by hand. In a
|
||||
# frame-loop game the loop already drove input this frame (input_drive), so this is
|
||||
# a no-op that returns the frame's key; in an entry-driven harness (no loop) it
|
||||
# commits a frame of input each call, exactly as before.
|
||||
function input_poll() -> int {
|
||||
if in_have_frame_driver { return input_frame }
|
||||
return input_commit()
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# device layer (#50) — multiple simultaneous keys, analog axes/vectors, the
|
||||
# mouse, gamepads and touch, plus a full-state record/replay snapshot.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue