diff --git a/CLAUDE.md b/CLAUDE.md index 0cdb71c..b6996ee 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -34,7 +34,7 @@ Box2D v3.1.0 (fetched by CMake) - **LCB binding** (`src/box2dxt.lcb`, `library org.openxtalk.box2dxt`): declares `foreign handler` bindings to the shared library and public `b2PascalCase` handlers callable from xTalk. This API speaks **metres and radians**; body type codes are `0=static, 1=kinematic, 2=dynamic`. -- **The Kit** (`src/box2dxt-kit.livecodescript`): a pure-xTalk convenience layer (260+ `b2k*` +- **The Kit** (`src/box2dxt-kit.livecodescript`): a pure-xTalk convenience layer (312 `b2k*` handlers incl. the game modules: input, sprites, player controller, camera) that speaks **screen pixels and degrees**, binds bodies to LiveCode controls, and runs the animation loop. This is what the examples and most users actually call. @@ -44,12 +44,15 @@ Docs live in `docs/` (`architecture.md`, `building.md`, `getting-started.md`, `a binaries are in `prebuilt/` — the SOURCE `tools/package-extension.py` lays into the extension's `src/code/-/` tree; the install is the packaged extension, not a loose drop-in (a loose `box2dxt.{so,dll,dylib}` beside a saved stack is only the dev/fallback path, mapped at runtime -by the Kit's `b2kEnsureNativeLib`). The **Game Kit** (input/sprites/player/camera/sound modules, plan.md -Phases 0-5) is implemented and user-verified on Win32; `plan.md`'s decision log is the as-built -record. Six examples: demo, contraption builder, spike (Phase-0 harness), **platformer showcase** -(the Game Kit pushed hard — the focus of this repo's game work), **slingshot** (angry-birds-style -tower knockdown — the physics core carrying a whole game with zero events and zero assets), and the -**self-test harness** (below). +by the Kit's `b2kEnsureNativeLib`). The **Game Kit** (input/sprites/player/camera/sound modules) is +implemented and user-verified; content **Waves 0-7 are built** (Wave 8, builder cross-pollination, is +the only remaining roadmap item); `plan.md`'s decision log is the as-built record. Six examples: demo, +contraption builder, **spike-gamekit** (the Phase-0 Game Kit harness), **platformer** (the flagship +game showcase — the Game Kit pushed hard across 5 levels, with bestiary I + variety walkers + bestiary +II frog/barnacle/spider — the focus of this repo's game work), **slingshot** (angry-birds-style tower +knockdown over 3 levels — the physics core carrying a whole game with zero events and zero assets), and +the **self-test harness** (below). (The single-screen micro-game was retired in Wave 5; its "whole game +from the physics core" pattern survives only as `kit-guide` section 20 prose.) ## The golden rule: the embedded-Kit sync @@ -105,9 +108,9 @@ failure. Run it after **every** `.livecodescript` edit. pass" and let the user confirm. **The self-test harness** (`examples/box2dxt-selftest.livecodescript`) is the runtime safety net: -~125 deterministic assertions (currently **v12**) driving the real Kit (paused world + -`b2kStepOnce` hand-stepping + `b2kInputInject` scripted keys). The workflow for every **Kit** -change: (1) add/extend an assertion +~180 deterministic assertions across 37 test handlers (currently **v22**) driving the real Kit +(paused world + `b2kStepOnce` hand-stepping + `b2kInputInject` scripted keys). The workflow for +every **Kit** change: (1) add/extend an assertion that captures the new behavior, (2) **bump `kStHarnessV`** (the report header prints it, so a stale paste identifies itself), (3) the user clicks RUN ALL TESTS and reports. **Example-only changes do NOT bump the harness** — the rule is conditional on Kit edits (Waves 1 and 3 shipped @@ -395,7 +398,7 @@ Every kind must be wired through the **whole pipeline** or it half-works. Touch rows; save-keys unique per kind; selection is non-destructive (`selectPart` stores `uSelFg`/`uSelLine` and `deselectPart` restores them, so highlighting never corrupts a part's real colours). -## Contributing conventions (from CONTRIBUTING.md) +## Contributing conventions - **Units/types across the FFI:** reals `double`, booleans `int` (0/1), handles positive `int` (0 invalid, opaque). `b2*` = metres/radians, `b2k*` = pixels/degrees. diff --git a/README.md b/README.md index 7b0c7de..29f8483 100644 --- a/README.md +++ b/README.md @@ -52,9 +52,12 @@ Box2D v3.1.0 (fetched by CMake) a full build-and-run physics sandbox with fans, magnets, lasers, bombs, motors, and save/load. Game-minded? The [platformer showcase](examples/box2dxt-platformer.livecodescript) is the - Game Kit pushed hard — player controller (run, double-jump, wall-jump, - dash, climb, crawl, swim), scrolling camera, spritesheets, moving - platforms, coin puzzles, a hilltop swim pool — and the + Game Kit pushed hard — five scrolling levels (grass, stone, ice, haunted, + desert) with a full player controller (run, double-jump, wall-jump, dash, + duck, climb, swim, drop-through, platform-carry), a bestiary (bats, a + mimic, piranhas, a ghost, a kickable snail shell, crushers, and more), + joints (rope bridge, boulder, exploding barrel, collapsing bridge), + spritesheets, and synthesized audio — and the [slingshot](examples/box2dxt-slingshot.livecodescript) is pure physics joy: catapult cannonballs into toppling towers, angry-birds style (three levels, ballistic aim preview, zero assets). And the @@ -92,9 +95,13 @@ x86) on every push; see [docs/building.md](docs/building.md). ## Contributing -See [CONTRIBUTING.md](CONTRIBUTING.md) for the layer conventions, the -embedded-Kit sync rule, and the static checks -(`python3 tools/check-livecodescript.py`) that gate every change. +The three layers and their conventions are in +[docs/architecture.md](docs/architecture.md); the build is in +[docs/building.md](docs/building.md). The Kit is the single source of truth — +after editing `src/box2dxt-kit.livecodescript`, re-sync the embedded copies +with `python3 tools/sync-embedded-kit.py`. Two static gates run on every change +(and in CI): `python3 tools/check-livecodescript.py` (the script layer) and +`python3 tools/sync-embedded-kit.py --check` (embedded-Kit drift). ## License diff --git a/dist/INSTALL.md b/dist/INSTALL.md index 4818169..5f474b9 100644 --- a/dist/INSTALL.md +++ b/dist/INSTALL.md @@ -64,7 +64,7 @@ The game builds itself and starts immediately. - **Controls:** **arrows / WASD** move · **Space** jump (press again in mid-air to **double-jump**, or off a wall to **wall-jump**) · **SHIFT / X** dash · **↓** duck · **R** restart · **M** mute. Grab every coin (the flag turns gold) - and touch the flag to advance — there are four levels. + and touch the flag to advance — there are five levels. That's it. Enjoy the physics. diff --git a/docs/building.md b/docs/building.md index 147678a..b7af50c 100644 --- a/docs/building.md +++ b/docs/building.md @@ -116,12 +116,12 @@ the recipient a one-step install with the right native library bundled in — no loose libraries to place. To instead hand someone a ready-to-run game as a single self-contained zip (no -repo, no toolchain, no internet, no extension install step), bundle the source -(extension + C shim + Kit), the per-platform native libraries under their bare -name, the demo's spritesheets, a built **and saved** stack, and the end-user -install guide. `tools/make-release.py` does it — the recipient runs straight from -the unzipped folder, with the Kit's `b2kEnsureNativeLib` mapping the -beside-the-stack library at runtime (the dev/fallback path, no install needed): +repo, no toolchain, no internet), bundle the extension (the `.lcb` plus its +`code/-/` native libraries), the C shim + Kit for reference, the +demo's spritesheets, a built **and saved** stack, and the end-user install guide. +`tools/make-release.py` does it — the native library travels **inside the +extension**, so the recipient installs one extension and the engine loads the +right per-platform library automatically (no loose library to place): ```sh # Build & SAVE the stack in OXT first (e.g. the platformer), then: @@ -129,33 +129,37 @@ python3 tools/make-release.py --stack /path/to/NewPlateformerDemo.oxtstack # -> dist/NewPlateformerDemo.zip ``` -It copies `src/box2dxt.lcb` / `box2d_lc.c` / `box2dxt-kit.livecodescript` into -`source/`, renames each `prebuilt/` library to the bare name the Kit maps under -`libraries/`, copies the platformer's `Spritesheets/` art into `spritesheets/`, -adds `dist/INSTALL.md`, and drops your saved stack at the root — producing: +It copies `src/box2dxt.lcb` together with its whole `src/code/` tree into +`extension/` (run `tools/package-extension.py` first to populate it), copies +`box2d_lc.c` / `box2dxt-kit.livecodescript` into `source/` for reference, copies +the platformer's `Spritesheets/` art into `spritesheets/`, adds `dist/INSTALL.md`, +and drops your saved stack at the root — producing: ``` NewPlateformerDemo/ ├── NewPlateformerDemo.oxtstack # your --stack -├── INSTALL.md # the three-step end-user install guide -├── source/ box2dxt.lcb, box2d_lc.c, box2dxt-kit.livecodescript -├── libraries/ box2dxt.{dll,dylib,so} +├── INSTALL.md # the end-user install guide +├── box2dxt.lce # optional prebuilt extension (only with --lce) +├── extension/ box2dxt.lcb + code/-/box2dxt.{so,dll,dylib} +├── source/ box2d_lc.c, box2dxt-kit.livecodescript (reference) └── spritesheets/ the demo's PNG + XML sheets ``` -Override a library with `--win` / `--mac` / `--linux` (e.g. an SSE2 or -older-glibc build), the art folder with `--sheets`, or the stack's in-zip name -with `--stack-name`; `--check` validates the inputs without writing the zip. -The recipient follows `INSTALL.md`: drop their platform's `libraries/` file -beside the stack, **Load** `source/box2dxt.lcb`, open the stack, and point its +Pass `--lce /path/to/box2dxt.lce` to drop a prebuilt extension in too (so testers +can install in one click instead of Packaging `extension/box2dxt.lcb` +themselves); override the art folder with `--sheets`, the stack's in-zip name +with `--stack-name`, or the output path with `--out`; `--check` validates the +inputs without writing the zip. The recipient follows `INSTALL.md`: install the +`.lce` (or open `extension/box2dxt.lcb` in the Extension Builder and **Package** +it — keeping its `code/` folder alongside), open the stack, and point its first-run prompt at `spritesheets/`. ## Platform & CPU notes - **AVX2 / SIMD.** Box2D assumes **AVX2** on x64 by default. If your binary must run on older CPUs, configure Box2D with `-DBOX2D_DISABLE_SIMD=ON` (slower) or - an SSE2 build. The committed `prebuilt/linux-x86_64` binary is built with SIMD - disabled so it runs anywhere. + an SSE2 build. The committed `prebuilt/libbox2dxt-linux-x86_64.so` binary is + built with SIMD disabled so it runs anywhere. ```sh cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DBOX2D_DISABLE_SIMD=ON diff --git a/docs/expansion-prep.md b/docs/expansion-prep.md index 4b3a42e..218b0a3 100644 --- a/docs/expansion-prep.md +++ b/docs/expansion-prep.md @@ -7,15 +7,18 @@ that keep the expansion as reliable as the engine underneath it. | | | |---|---| -| Baseline | Kit + games user-verified; self-test harness **v10, ~113 assertions, all pass** (Wave 2 closed 2026-06-13) | +| Baseline | Kit + games user-verified; self-test harness **v22, ~180 assertions across 37 test handlers, all pass** (current; Waves 1–7 all closed) | | Assets | **LANDED (2026-06-11)** — Kenney's iconic platformer family, ~900 frames; Wave 0 catalogue below | -| Wave 1 | **COMPLETE — user-verified 2026-06-12** (the three-level platformer; see §7) | -| Wave 2 | **COMPLETE — user-verified 2026-06-13** (player actions I, harness v10; see §9) | -| Wave 3 | **BUILT — statically verified 2026-06-13** (bestiary I + HAUNTED HOLLOW; see §10) | -| Showcase polish | **BUILT — statically verified 2026-06-13** (pre-Wave-4: longer/re-spaced levels, the kit's first JOINT mechanics — rope bridge + boulder + barrel; a prototyped wrecking ball was cut as un-sprite-able — and four variety species; all example-side, zero Kit change, no harness bump) | -| Wave 4 | **SWIM user play-tested in the platformer 2026-06-14** (harness **v12**, two Opus reviews clean; see §11). The Kit gained `b2kPlayerAddWater` + a buoyant `swim` mode/state/anim; the platformer's L1 GREEN HILLS gained a **HILLTOP POOL** (a raised-bank basin — the swim showcase, where it's tested), tuned heavier and with the hero hitbox fixed to match the art (gotcha 28), all per the user's OXT pass. DONE: swim zones, pit-dwellers (the micro-game `fish`, debut), lava (already in platformer L4). CARRY-OVER: the collapsing-bridge trap, and the micro-game's L3 "THE DEEP" (built but shows an example-side white-world build issue — set aside) | -| Wave 5 | **BUILT — statically verified 2026-06-14** (player actions II: double-jump `airJumps`, wall-slide/jump, dash, duck capsule-reshape, moving-platform carry — all opt-in Kit knobs, defaults unchanged; harness **v13**, six new tests; see §12). Enabled + showcased in the platformer; the micro-game was retired (focus is the platformer). Awaiting the OXT feel pass. | -| Next | Iterate Wave 5 feel in OXT (the new moves' tuning numbers are first-pass); the collapsing-bridge trap remains a loose end | +| Wave 1 | **COMPLETE — user-verified 2026-06-12** (the iconic-feel base; shipped as a three-level platformer, since grown to **five levels**; see §7) | +| Wave 2 | **COMPLETE — user-verified 2026-06-13** (player actions I; see §9) | +| Wave 3 | **COMPLETE — statically verified 2026-06-13** (bestiary I + HAUNTED HOLLOW; see §10) | +| Showcase polish | **COMPLETE — statically verified 2026-06-13** (pre-Wave-4: longer/re-spaced levels, the kit's first JOINT mechanics — rope bridge + boulder + barrel; a prototyped wrecking ball was cut as un-sprite-able — and four variety species; all example-side, zero Kit change, no harness bump) | +| Wave 4 | **COMPLETE — SWIM user play-tested in the platformer 2026-06-14** (see §11). The Kit gained `b2kPlayerAddWater` + a buoyant `swim` mode/state/anim; the platformer's L1 GREEN HILLS gained a **HILLTOP POOL** (a raised-bank basin — the swim showcase, where it's tested), tuned heavier and with the hero hitbox fixed to match the art (gotcha 28), all per the user's OXT pass. DONE: swim zones, lava (platformer L4), the collapsing bridge (now L4's lava crossing). | +| Wave 5 | **COMPLETE** (player actions II: double-jump `airJumps`, wall-slide/jump, dash, duck capsule-reshape, moving-platform carry — all opt-in Kit knobs, defaults unchanged; see §12). Enabled + showcased in the platformer; the **micro-game was retired here** (focus is the platformer). | +| Wave 6 | **COMPLETE — statically verified, merged** (bestiary II: frog hopper, barnacle lurking clam, spider ceiling-dropper — woven into L1/L2/L4). | +| Wave 7 | **COMPLETE — statically verified, merged** (the desert biome: **L5 SCORCHED DUNES** — the platformer's fifth level, sand/desert). | +| Wave 8 | **NOT STARTED** — builder cross-pollination (animated sprite parts + the player-as-a-part in the Contraption Builder); the only remaining roadmap item. | +| Next | Wave 8: the builder cross-pollination. | | Companions | [plan.md](../plan.md) (history/decision log) · [game-engine-spec.md](game-engine-spec.md) (module design) | --- @@ -178,11 +181,13 @@ to Kit API (`b2kFoe…`). platformer re-skinned sprite-only (real thwomp art, spike tiles, biome ground). *The "it looks like the classics now" wave.* **COMPLETE — user-verified 2026-06-12.** Shipped as a **three-level - platformer**: L1 GREEN HILLS (movement + the toys: springboard, bonk - row, one-way bridge, mound, clouds, spike pit), L2 THE WORKS (button - gate, saw lever, thwomps, yellow key + the walled door), L3 FROZEN - CITADEL (everything on ICE, snow biome, a second saw, red key + - door). Springboards, ?-boxes paying coins, POOLED brick debris, + platformer** (a historical milestone — the platformer has since grown + to **five levels** through Waves 3 and 7): L1 GREEN HILLS (movement + + the toys: springboard, bonk row, one-way bridge, mound, clouds, spike + pit), L2 THE WORKS (button gate, saw lever, thwomps, yellow key + the + walled door), L3 FROZEN CITADEL (everything on ICE, snow biome, a + second saw, red key + door). Springboards, ?-boxes paying coins, + POOLED brick debris, button art on the polled plate, stand-to-flip lever, chained-weight thwomps (static at rest, **not player-movable**), walled doors whose gates are STRUCTURAL (floor-to-ceiling; the flag and last coins @@ -210,25 +215,32 @@ to Kit API (`b2kFoe…`). Design in §9; as-built record in plan.md's decision log. The §9 ABI question resolved to NO ABI CHANGE (the shim's pending shape-def filter already covers chain creation). -3. **Wave 3 — bestiary I:** shelled (kickable!), ghost, bat, mimic, - pipe plant, crusher-with-faces — into a platformer "haunted" section. -4. **Wave 4 — liquids:** swim zones (done — the platformer's hilltop pool) - + lava (already in L4) + pit dwellers (the micro-game fish) + the - collapsing bridge (carry-over). As-built record in §11. -5. **Wave 5 — player actions II:** wall-slide/jump, dash, double-jump - powerup (boxItem delivers it), platform carry. -6. **Wave 6 — bestiary II + promotion:** chaser, lunger, spider, saws; - `b2kFoe…` promotion decision with two consumers in hand. -7. **Wave 7 — the showcase level:** one long level using every biome - mechanic — the "iconic platformer" demonstration piece, plus sprite HUD. -8. **Wave 8 — builder cross-pollination** (closes Phase 5): sprite parts + - the player as placeable kinds in the contraption builder. +3. **Wave 3 — bestiary I (COMPLETE):** shelled (kickable!), ghost, bat, + mimic, pipe plant, crusher-with-faces — into the platformer's L4 + "HAUNTED HOLLOW". +4. **Wave 4 — liquids (COMPLETE):** swim zones (the platformer's hilltop + pool) + lava (L4) + the collapsing bridge (now L4's lava crossing). + As-built record in §11. +5. **Wave 5 — player actions II (COMPLETE):** wall-slide/jump, dash, + double-jump powerup (boxItem delivers it), platform carry. The + micro-game was retired here. +6. **Wave 6 — bestiary II + promotion (COMPLETE):** frog hopper, + barnacle lurking clam, spider ceiling-dropper — woven into L1/L2/L4; + the `b2kFoe…` promotion decision deferred (no second consumer yet — + the micro-game retired). +7. **Wave 7 — the desert biome (COMPLETE):** the platformer's fifth + level, **L5 SCORCHED DUNES** (sand/desert) — the "iconic platformer" + demonstration piece. +8. **Wave 8 — builder cross-pollination (NOT STARTED — the only + remaining roadmap item):** sprite parts + the player as placeable + kinds in the contraption builder. ## 8. Open questions / risks - **macOS/Linux (R1):** unverified; the self-test is the acceptance suite. -- **`b2kScene*` promotion:** likely lands with Wave 4 (a third level wants - the format) — decide then. +- **`b2kScene*` promotion:** did NOT land — the platformer reached five + levels (through Wave 7) keeping its scenes example-side, so the format + was never promoted to Kit API. Revisit only if a second game needs it. - **`spritesheet_complete.xml`** is an orphan (its `sprites.png` wasn't uploaded) — no content loss; upload the PNG later or delete the XML. - **Mixed grids:** 70px (C) vs 128px (B) — normalised per level via diff --git a/docs/game-engine-spec.md b/docs/game-engine-spec.md index adefed0..8284467 100644 --- a/docs/game-engine-spec.md +++ b/docs/game-engine-spec.md @@ -4,7 +4,7 @@ | | | |---|---| -| Status | **Implemented and user-verified on Win32 (2026-06-11)** — all four modules + audio shipped; as-built deltas live in [plan.md](../plan.md)'s decision log; runtime behaviour is asserted by `examples/box2dxt-selftest.livecodescript` (~93 checks). macOS/Linux passes still open (risk R1). | +| Status | **Implemented and user-verified on Win32 (2026-06-11)** — all four modules + audio shipped; as-built deltas live in [plan.md](../plan.md)'s decision log; runtime behaviour is asserted by `examples/box2dxt-selftest.livecodescript` (harness v22, ~180 checks across 37 test handlers, having grown with the content waves). macOS/Linux passes still open (risk R1). | | Scope | New `b2k…` modules in the Kit: **Input**, **Sprites**, **Player**, **Camera** | | Native impact | **None.** No C-shim or LCB changes; ABI stays at 4 | | Companion | [plan.md](../plan.md) — the phased implementation plan | @@ -361,9 +361,9 @@ Input module and writes `b2kSetVelocity` x / preserves y. | `b2kPlayerMake pX, pY, pW, pH [,pSheet]` → control | One call: sprite (or plain capsule graphic if no sheet), capsule body, controller defaults, input armed. Reports the control. | | `b2kPlayerAttach pCtrl` | Adopt an existing control/sprite as the player (capsule body added if it has none). | | `b2kPlayerSet pKey, pValue` / `b2kPlayerGet(pKey)` | Tuning knobs (table below). | -| `b2kPlayerAnims pIdle, pRun, pJump, pFall [,pLand] [,pDuck] [,pClimb] [,pHurt] [,pSwim]` | Map controller states to sheet animations; auto-`FlipH` from facing. (Wave 2-4 slots are optional fallbacks — see kit-reference.) | +| `b2kPlayerAnims pIdle, pRun, pJump, pFall [,pLand] [,pDuck] [,pClimb] [,pHurt] [,pSwim] [,pWall] [,pDash]` | Map controller states to sheet animations; auto-`FlipH` from facing. (Wave 2-5 slots are optional fallbacks — see kit-reference.) | | `b2kPlayerOnGround()` → bool | Grounded this frame (post-tick). | -| `b2kPlayerState()` → word | `idle` / `run` / `jump` / `fall` / `duck` / `climb` / `hurt` / `swim` (+ `land` transition tick). | +| `b2kPlayerState()` → word | `idle` / `run` / `jump` / `fall` / `duck` / `climb` / `hurt` / `swim` / `wallslide` / `dash` (+ `land` transition tick). | | `b2kPlayerFacing()` → 1 / -1 | Last horizontal intent. | | `b2kPlayerJump [pSpeed]` | Programmatic jump (springs, double-jump powerups) — respects the same state machine. | | `b2kPlayerControl pFlag` | Enable/disable input→motion (cutscenes; physics continues). | @@ -396,11 +396,12 @@ automatically when `b2kPlayerAnims` is set. segments are one-sided exactly the way platformers need — a capsule rises through from below and lands on top (`b2kChain`/`b2kSmoothGround`, top surface listed right-to-left; plain `b2kWall` segments are two-sided and cannot do -this). **Explicitly deferred** (designed-for, not in v1) — several have +this). **Explicitly deferred** (designed-for, not in v1) — most have since landed: **drop-through** and **ladders** in Wave 2, **SWIM zones** in -Wave 4. Still ahead: moving-platform velocity carry (v1 relies on friction), -**wall-jump/slide** and **dash** (Wave 5), multiple simultaneous players -(state is per-control already; only the input bindings are global). +Wave 4, and **wall-jump/slide**, **dash**, **double-jump**, **duck +capsule-reshape** + **moving-platform velocity carry** in Wave 5 (v1 had +relied on friction for the carry). Still ahead: multiple simultaneous +players (state is per-control already; only the input bindings are global). ## 7. Module: Camera diff --git a/docs/kit-guide.md b/docs/kit-guide.md index 0a875eb..8521384 100644 --- a/docs/kit-guide.md +++ b/docs/kit-guide.md @@ -66,7 +66,8 @@ This guide is entirely about the **Kit** layer. ## 2. Install and your first scene **Requirements:** the `box2dxt` extension loaded. Check with `put b2Version()` -— it should return `3`. The Kit runs in OpenXTalk and LiveCode 9.6.3+. +— it should return `4` (the shim ABI version). The Kit runs in OpenXTalk and +LiveCode 9.6.3+. **Install:** paste the contents of `src/box2dxt-kit.livecodescript` into your card or stack script. (Or save it as a library stack and `start using` it.) @@ -644,6 +645,15 @@ b2kAnimDef "boss", "wake", "idle,roar", 4, false `b2kSheetFrameNames("chars")` lists every frame key of a sheet you didn't make — the quickest way to find what an atlas calls things. +**Persisting sheets across rebuilds.** By default a sheet is torn down with +the world, so a single-shot scene reloads its art each run. A game that +rebuilds the world per level can keep its sheets cached instead: +`b2kSheetPersist true` makes sheets **survive `b2kTeardown`** (exactly like +synthesized sounds) and reuse an identical reload rather than re-slicing it +— `b2kClear`/`b2kTeardown` then wipe only the sprite *instances*. It's OFF by +default; `b2kSheetsWipe` forces a clean reload (e.g. after the player picks a +new asset folder), and `b2kSheetPersists()` reads the flag back. + ### The player controller (`b2kPlayerMake`) Everything the input and sprite snippets above hand-roll — and the parts @@ -717,7 +727,7 @@ end b2kFrame `b2kTeardown`); `b2kSoundVolume` drives the engine-global loudness. On an engine with no working audio the Kit degrades to silence rather than errors — check `b2kSoundStatus()` if you hear nothing. The platformer's -eight cues are all synthesized; press M in it to mute. +cues are all synthesized this way; press M in it to mute. --- @@ -930,7 +940,7 @@ put b2kAwakeBodyCount() -- awake dynamic bodies (native count) > 1. **Throttle your HUD.** Setting a field's text re-lays-out and redraws it — > a readout that changes every frame costs a redraw every frame. Update HUDs > at ~4 Hz (`if the milliseconds < gHudNextMS then …`), and still skip the -> set when the text is unchanged. Both game examples do this. +> set when the text is unchanged. The platformer and slingshot both do this. > 2. **Write properties and velocities only on change.** Track the last value you > applied (the platformer's gate writes its kinematic velocity only when the > target flips). @@ -1026,10 +1036,11 @@ The **micro-game pattern** is the recommended skeleton for a green-field game on the Kit: a complete game — start screen, levels, a win screen — in a few hundred lines of card logic, with nothing to install beyond the extension (embed the hero sheet as base64; synthesize every sound with -`b2kToneMake`). A dedicated micro-game example once shipped this verbatim; -the repo now concentrates its game work on the **platformer showcase**, but -the pattern below is exactly the one to copy when you start your own game. -Its skeleton is four ideas: +`b2kToneMake`). A dedicated micro-game example once shipped this verbatim; it +has since been retired (the repo now concentrates its game work on the +**platformer** and **slingshot** showcases), but the pattern is **preserved +here** because it remains exactly the skeleton to copy when you start your own +green-field game. Its skeleton is four ideas: **1. A game-state machine, gated by `b2kPlayerControl`.** One `gMode` local (`menu` / `play` / `won`) decides what clicks and keys mean. The @@ -1064,7 +1075,7 @@ when the coin count is full. **3. One call makes the player.** `b2kPlayerMake gSpawnX, gSpawnY, 32, 56, "hero"` creates the capsule body host, the bound sprite, the controller, and arms input. After it: map the anims, set two tuning -knobs, `b2kCamFollow`. The micro-game's whole "character system" is six +knobs, `b2kCamFollow`. A whole "character system" in this pattern is six lines. **4. Game events ride the hooks you already have.** Coins/spikes/door are @@ -1073,10 +1084,10 @@ sensors (`on b2kSensorEnter`); landing and jump sounds key off animation whose `b2kSpriteOnFinish` message teleports the hero home. No new machinery — a game is the Kit's events plus your rules. -Play order: `openCard` builds level 1 and shows the menu → click → +The pattern's flow: `openCard` builds level 1 and shows the menu → click → `mgBegin` → door (all coins) → `mgAdvance` → level 2 → door → `mgShowWin` -→ click → back to level 1. `R` rebuilds the current level, `ESC` pauses, -`M` mutes. +→ click → back to level 1, with `R` to rebuild the current level, `ESC` to +pause, `M` to mute. --- @@ -1305,7 +1316,8 @@ Optional arguments are in `[…]`. `b2kSheetFromImage name,img,fw,fh [,n,margin,spacing]` · `b2kSheetAddFrame sheet,frame,x,y,w,h` · `b2kSheetFrames(name)` `[f]` · `b2kSheetHasFrame(name,frame)` `[f]` · `b2kSheetFrameNames(name)` `[f]` · -`b2kSheetScale name,factor` · +`b2kSheetScale name,factor` · `b2kSheetPersist flag` · `b2kSheetPersists()` `[f]` · +`b2kSheetsWipe` · `b2kSheetFrameSize(name,frame)` `[f]` · `b2kAnimDef sheet,anim,frames,fps [,loop]` · `b2kSpriteNew sheet [,frame,x,y]` · `b2kSpriteFromGIF path [,x,y]` · `b2kSpritePlay spr,anim [,restart]` · `b2kSpriteStop spr` · `b2kSpriteAnim(spr)` `[f]` · diff --git a/docs/kit-reference.md b/docs/kit-reference.md index 4dab621..dad8f06 100644 --- a/docs/kit-reference.md +++ b/docs/kit-reference.md @@ -400,7 +400,8 @@ away + up; `wallJumpX > 0` arms the **wall system**, `wallJumpY` falls back to `jumpSpeed`) · `wallSlideMax` 0 (capped fall px/s while pressing into a wall — the `wallslide` state) · `dashSpeed` 0 (a flat horizontal burst on the **`dash` action**, default keys SHIFT/X; `0` = off) / `dashMs` 160 / `dashCooldownMs` -500 · `duckScale` 1 (ducked capsule height ÷ standing; **< 1 reshapes to a +500 / `airDash` 1 (**1** = dash works mid-air too; `0` = grounded-only) · +`duckScale` 1 (ducked capsule height ÷ standing; **< 1 reshapes to a crawl** so the hero slips under low gaps — feet-anchored, with a headroom check before standing) · `platformCarry` 0 (**1** = a grounded player inherits the velocity of a moving kinematic platform it rides; costs two reads per diff --git a/examples/box2dxt-platformer.livecodescript b/examples/box2dxt-platformer.livecodescript index 7bd4916..f64c332 100644 --- a/examples/box2dxt-platformer.livecodescript +++ b/examples/box2dxt-platformer.livecodescript @@ -1,15 +1,17 @@ -- ===================================================================== -- box2dxt-platformer.livecodescript · Game Kit Phases 1+2+3+4 showcase -- --- A FOUR-LEVEL collect-them-all platformer (each level its own +-- A FIVE-LEVEL collect-them-all platformer (each level its own -- scrolling world in a 1024px viewport) that exercises everything -- built so far: the Kit's PLAYER CONTROLLER (b2kPlayerAttach drives -- movement, jumping, grounding, state and animations - this file holds -- no movement code of its own), atlas spritesheets with named -- animations and scaling, the camera (follow + bounds + shake), --- synthesized sound, the full Wave 1 toy box, the Wave 3 bestiary, and --- now the kit's JOINT + dynamics systems (a sagging rope bridge, a --- rolling boulder, an exploding barrel) plus four more enemy species. +-- synthesized sound, the full Wave 1 toy box, the Wave 3 + Wave 6 +-- bestiaries (bats, mimics, piranhas, the ghost, kickable shells, +-- crushers, a frog, a barnacle, a spider), the kit's JOINT + dynamics +-- systems (a sagging rope bridge, a rolling boulder, an exploding +-- barrel), and variety walkers (mouse, worm, ladybug, fire slime). -- Collect EVERY coin on a level (the goal -- flag turns GOLD), touch the flag, and the next level builds; level -- 5's flag is the win. Anything without sheet art falls back to plain @@ -32,23 +34,24 @@ -- are NOT draggable) · R restarts the CURRENT level · ESC pauses -- · M mutes the synthesized sound -- --- THE FOUR LEVELS (every beat holds a coin; the flag advances): +-- THE FIVE LEVELS (every beat holds a coin; the flag advances): -- LEVEL 1 GREEN HILLS (8640px) - movement + the toys: the -- SPRINGBOARD mid-meadow (sky coin above; a 42px hop for -- non-bouncers), the BONK ROW (headbutt ?-boxes, SMASH bricks -- into debris), the one-way BRIDGE over a spike slime, the -- slope MOUND, one-way CLOUDS with the fly, the bee, the --- SPIKE PIT, a fast MOUSE, a coin on the open meadow run, a --- flying ladybug - then the rope-bridge finale over a chasm, +-- SPIKE PIT, a fast MOUSE, a hopping FROG, a coin on the open +-- meadow run, a flying ladybug - then the rope-bridge finale, -- the crusher alley, and the hilltop SWIM POOL to the flag. -- LEVEL 2 THE WORKS (5952px) - the machines: drag the -- CRATE onto the yellow BUTTON to open the gate (coin in -- the gateway), the Wave 2 LADDER up to its bonus ledge, -- the red CHECKPOINT, the saw LEVER (STAND at it to power -- the sweeping saw down - running past never flips it), --- both SAWS, a crawling WORM, THWOMP ALLEY (chained weights: --- ride the second one's head to the top coin; grab the --- YELLOW KEY between them), a breather cloud with its bee, +-- both SAWS, a crawling WORM, a lurking BARNACLE, the THWOMP +-- ALLEY (chained weights: ride the second one's head to the +-- top coin; grab the YELLOW KEY between them), a breather +-- cloud with its bee, -- the Wave 5 LIFT BAY (its signature: RIDE the moving deck -- across the grinder for a mid-bay coin - platform-carry), -- then the crusher alley and the WALLED DOOR - a stone @@ -71,12 +74,19 @@ -- path), two BATS roosting under a stone bar (they drop -- and swoop), a pit, a long FOUR-burrow PIRANHA row (they -- will not rise under your feet), the shy GHOST that drifts --- closer while you face away, two faced CRUSHERS around a +-- closer while you face away, a SPIDER that drops from an +-- overhang, two faced CRUSHERS around a -- LAVA strip crossed by a COLLAPSING BRIDGE (cross the -- crumbling planks fast, or double-jump it), a smouldering FIRE -- SLIME, the POWDER KEG bay (an explosive barrel + woodpile, -- scattered by b2kExplode), the red crusher alley (its --- signature gauntlet), purple steps, the last flag. +-- signature gauntlet), purple steps, the flag. +-- LEVEL 5 SCORCHED DUNES (4240px) - WAVE 7's DESERT biome: a sand +-- DUNE (ramp slope) to crest, a sand slime, a hopping FROG, a +-- THORN PIT to leap (checkpoint at the brink), a two-cloud +-- HOP, then bestiary II with room to read - a snail, a lurking +-- BARNACLE, a SPIDER on a sand overhang - and sand steps to +-- the final flag (the win). -- -- WHAT TO VERIFY (the Phase 3 + level-rebuild OXT pass) -- 1. Feel: a TAPPED jump is clearly shorter than a HELD one; jumping