Skip to content

Wave 2 (player actions I): drop-through, ladder climb, duck, hurt-knockback; harness v10#37

Draft
SethMorrowSoftware wants to merge 3 commits into
mainfrom
claude/quirky-ramanujan-ushdia
Draft

Wave 2 (player actions I): drop-through, ladder climb, duck, hurt-knockback; harness v10#37
SethMorrowSoftware wants to merge 3 commits into
mainfrom
claude/quirky-ramanujan-ushdia

Conversation

@SethMorrowSoftware

Copy link
Copy Markdown
Owner

The first Kit-touching wave of the content phase, implementing docs/expansion-prep.md §9 in full. Statically verified (all script gates green, embedded Kits in sync, native smoke test passes); needs the OXT pass: harness v10 RUN ALL TESTS first, then both games.

Kit — four controller abilities

Drop-through. Open chains (b2kChain/b2kSmoothGround/b2kAddChain) are created carrying a reserved ONE-WAY collision category (bit 31; b2kDefineLayer now hands out 30 named layers). DOWN+JUMP while standing on one strips the bit from the player's mask for dropMs (260). Two traps found and solved at design time:

  • A pure timer FAILS at real scales — 260 ms of freefall moves a capsule ~14–20 px but the capsule is 48–88 px tall, so restoring the filter mid-straddle makes the one-sided push-out pop the player back on top. The window's close is geometry-aware (straddle rays at expiry, 2-frame extensions, dropMs × 4 hard cap).
  • Rays ignore shape filters, so the ground probe skips one-way hits by category while dropping, or it would re-ground mid-drop.

Hills/slopes opt out with a new trailing noDrop flag (the platformer's mound passes it). No ABI change: b2lc_chain_create already consumes the staged one-shot shapedef filter — the design's open question dissolved on inspection. ABI stays 4.

Ladder climb. b2kPlayerAddLadder x1,y1,x2,y2 registers polled zones (zero physics objects; wiped by clear/teardown). In-zone + UP/DOWN → state climb: gravity 0, moveY drives y at climbSpeed, x at half speed, releasing hangs. The jump-exit listens only to jump keys that are not also moveY keys — so SPACE dismounts while UP keeps climbing, even under the platformer's space,up,w binding. UP grabs only with ladder above the head (standing on the deck a zone pokes through, UP jumps — never re-grabs); DOWN grabs only mid-air (drop through the deck, hold DOWN, catch the ladder).

Duck. DOWN while grounded brakes vx to 0 with the duck pose; jump presses are swallowed (down+jump on solid ground just ducks). No hitbox change this wave — documented so nobody designs duck-under gaps before Wave 5.

Hurt-knockback standard. b2kPlayerHurt [fromX]: control off, away-pop (hurtPopX/hurtPopY, ground-snap exempt), hurt anim, control restored at the first landing after hurtMs/2 or at hurtMs, whichever comes first, then an invulnerability window (invulnMs) with b2kPlayerHurtIs() as the game-side gate.

Plus: b2kPlayerAnims gains optional climb/duck/hurt slots with fallbacks; b2kPlayerState() adds the three states; and a latent cross-build landmine fixedb2kSetCategory/b2kSetCollisionGroup fed Box2D v3.1's 64-bit default-mask read-back (≈1.8e19) into the shim's 2^53 gate, silently no-oping the whole write; both setters now normalise to the Kit's 32-bit space.

Harness v10

Four new suites, ~20 self-diagnosing assertions: drop-through (pierce, land below, chain re-solidifies), climb (grab/hang/ascend/jump-off/ground-out, gravity-scale restored), duck (brake, down+jump never launches), hurt (away-pop, invuln no-op, control auto-restore).

Games (the two consumers proving the API)

  • Platformer: L2 gains the ladder + one-way bonus ledge above the plate area (9th coin) on real character_beige_climb_a/b frames; knockback for slime sides/saws/spikes (no fall counted), respawn kept for pits/kill plane/thwomp crush; the OnFinish respawn handler is gated by gHurtLock so the controller's non-looping hurt pose can never teleport the hero.
  • Micro-game: same knockback/respawn split; the L2 exit door moves onto a tower no jump reaches, climbed via a new ladder level verb; an optional alien skin picker (S on the menu — embedded hero + five aliens with real climb/duck/hurt frames) behind the Spritesheets folder, falling back silently so the file stays zero-asset by default.

Docs ride along: kit-reference, kit-guide (a new action-verbs teaching section + the noDrop recipe), CHANGELOG, plan.md decision log, expansion-prep §9 as-built notes.

OXT checklist for the user

  1. Harness v10: RUN ALL TESTS → expect ALL PASS (~122 assertions; report any FAIL line verbatim).
  2. Platformer: drop through the L1 bridge/clouds (duck on the mound must NOT sink); climb the L2 ladder to the bonus coin, drop back through the deck; get hit by a slime side/saw/spike → knocked away + flashing, no teleport; fall in a pit → respawn as before; finish all three levels (no Wave 1 regressions).
  3. Micro-game: paste-and-play asset-free; L1 ledge drop; L2 tower climb (hold RIGHT at the top to drift over the lip); spikes/sweeper knock back, world-fall respawns; S on the menu cycles skins once the folder is given.

https://claude.ai/code/session_01ECCfoqgaPXT8v32VCxWjBG


Generated by Claude Code

claude added 3 commits June 12, 2026 17:52
…ckback; harness v10

The first Kit-touching wave of the content phase, per expansion-prep #9.

Kit (player module):
- Drop-through: open chains carry a reserved ONE-WAY category (bit 31;
  b2kDefineLayer now allocates 30 named layers); DOWN+JUMP on one strips
  the bit from the player's mask for dropMs. The window's close is
  GEOMETRY-AWARE (straddle rays + dropMs x4 hard cap): a pure timer
  restores the filter while a tall capsule still straddles the line and
  the one-sided push-out pops it back on top. The ground probe skips
  one-way hits while dropping (rays ignore shape filters). New noDrop
  flag on b2kChain/b2kSmoothGround/b2kAddChain for hills and slopes.
  NO ABI CHANGE: chain creation already consumes the staged shapedef
  filter, resolving the design's open question.
- Climb: b2kPlayerAddLadder/ClearLadders polled zones; gravity 0, moveY
  drives y at climbSpeed, x at half speed, hang on release. Jump-exit
  listens only to jump keys that are NOT moveY keys (space dismounts,
  up keeps climbing under the platformer's space,up,w binding). UP
  grabs only with ladder above the head; DOWN grabs only in the air.
- Duck: DOWN while grounded brakes vx to 0; jump presses swallowed
  (down+jump on solid ground just ducks). No hitbox change this wave.
- Hurt-knockback standard: b2kPlayerHurt [fromX] (away-pop, hurt anim,
  control restored at first landing after hurtMs/2 or at hurtMs,
  whichever first) + b2kPlayerHurtIs() invulnerability gate. Explicit
  b2kPlayerControl takes ownership from the pending auto-restore.
- b2kPlayerAnims gains climb/duck/hurt slots with fallbacks; new states
  duck/climb/hurt; new keys dropMs/climbSpeed/hurtMs/invulnMs/hurtPopX/
  hurtPopY.
- Hardened: b2kSetCategory/b2kSetCollisionGroup normalise the engine's
  64-bit default-mask read-back (silent-no-op class on v3.1 builds).

Harness v10: four new suites (~20 assertions) - drop-through pierce/
re-solidify, climb grab/hang/jump-off/ground-out with gravity-scale
checks, duck brake/no-launch, hurt pop/invuln-no-op/auto-restore.

Platformer: L2 ladder + one-way bonus ledge above the plate (9th coin,
real character_beige_climb frames); the mound passes noDrop; knockback
for slime sides/saws/spikes (no fall counted), respawn kept for pits,
kill plane and the thwomp crush; OnFinish respawn gated by gHurtLock so
the controller's hurt pose can never teleport the hero.

Micro-game: same knockback/respawn split; L2 exit door moved onto a
tower no jump reaches with a new 'ladder' level verb; optional alien
skin picker (S on the menu, five colours with real climb/duck/hurt
frames) behind the Spritesheets folder - zero-asset default preserved.

Docs: kit-reference, kit-guide (action-verbs section + noDrop), the
CHANGELOG, plan.md decision log, expansion-prep #9 as-built notes.
Statically verified (all gates green; native smoke test passes);
needs the OXT pass: harness v10 RUN ALL TESTS, then both games.

https://claude.ai/code/session_01ECCfoqgaPXT8v32VCxWjBG
…hurt pop

Hot-path wins before OXT live test:

1. b2kPlayerRebuildJumpExit — pre-build the "jump keys NOT in moveY" code
   list at b2kBindAction/b2kBindAxis time. b2kPlayerJumpExitPressed drops
   from a per-frame repeat+string-build to two b2kCodesInSet lookups.
   Called automatically on both relevant bind calls (and b2kInputOn's
   starter defaults trigger it via the same path).

2. b2kPlayerZoneScan — single function replaces b2kPlayerInLadder /
   b2kPlayerLadderTop (both were separate repeat-for-each-line loops over
   sPlayLadders). The tick now calls ZoneScan once per climb-tick frame
   (exit check) and once per entry-check frame (covers both the top-y and
   the in-zone flag in one pass). Public wrappers kept for back-compat.

3. sPlayHurtHalfMs — pre-cache hurtMs/2 in b2kPlayerTuneCache, removing
   the division from b2kPlayerHurt (called on every knockback hit).

4. b2kPlayerHurt raw velocity write — body handle tB already in hand;
   swap b2kSetVelocity wrapper (ref lookup + "vx,vy" string round-trip)
   for direct b2SetVelocity + b2SetAwake with pre-divided metre values.
   y-flip: screen up = positive in Box2D y-up (gotcha 9).

All static gates pass; embedded Kit re-synced across all 6 examples;
native smoke test 1/1.

https://claude.ai/code/session_01ECCfoqgaPXT8v32VCxWjBG
CHANGELOG gains a "Changed" entry for the four Wave 2 hot-path wins.
plan.md gains a decision-log row documenting the design rationale for
each change and the pre-OXT gotcha audit (itemDelimiter, local placement,
handler balance, all clean).

https://claude.ai/code/session_01ECCfoqgaPXT8v32VCxWjBG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants