1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-08 17:06:04 +00:00
nescript/examples
Claude 169a481099
feat(platformer): add stomp-or-die enemy collisions, live HUD, GameOver state
The previous platformer example drew enemies but had almost no
interaction with them: only enemy 1 had a stomp check, the stomp
window was unreachable under the default +1-px-per-frame-plus-a-
jump-every-40-frames autopilot, contact from any other angle was
a silent no-op, and the header comment promised a "title → playing
→ game-over state machine" that didn't actually exist. The README
demo gif and the committed golden both froze that state — a level
the player could walk through indefinitely with no consequence.

Flesh the enemy interaction model out into something real:

- `resolve_enemy_hit(e_sx)`: one helper, called symmetrically for
  both enemies. Computes the player/enemy hitbox overlap (horizontal
  in `e_sx ∈ (72, 96)`, vertical in `player_y ∈ (152, 176)`) and
  branches three ways — falling onto the head is a stomp bounce
  (`rise_count = 6`, `fall_vy = 0`, `stomp_count += 1`, `play Boing`);
  overlap while `rise_count > 0` is a grace pass-through so the
  stomp bounce itself can't retrigger contact on the same enemy;
  anything else (walking into the side, standing on the ground
  against the enemy) is fatal — `alive = 0` and `play hit`.

- New `GameOver` state: draws four enemy tiles across the middle
  of the screen plus a coin row sized to `stomp_count`, stops the
  music, lingers 60 frames then auto-retries, and also honours
  Start for an instant retry.

- Proximity-based autopilot: pre-jump when an enemy is exactly 19 px
  ahead (`e1_sx == 99` or `e2_sx == 99`), capped at two jumps per
  life by `auto_jumps < AUTOPILOT_JUMPS`. Tuning: a JUMP_RISE=12,
  GRAVITY_CAP=4 jump lands the player's feet at enemy-head height
  exactly 21 frames after lift-off, by which point the autopilot
  camera has scrolled the enemy under the player. The first jump
  fires on Playing frame 1 and stomps enemy 1 on frame 22; the
  second fires on Playing frame 101 and stomps enemy 2 on frame
  122. After that the autopilot is exhausted and the third enemy
  encounter (camera wraps back past enemy 1) is fatal — the
  golden harness now sees the full stomp, stomp, die, retry, stomp
  loop instead of a frozen walk.

- Live HUD: up to four coin sprites in the top-left, one per
  stomp, rendered both during `Playing` and on the `GameOver`
  screen so the score is visible in the death frame. `Playing`'s
  player draw is now guarded by `if alive == 1` so the hero
  disappears on the fatal-contact frame and the enemy that killed
  them is visible underneath.

Verified with a per-frame ZP trace through the patched puppeteer
+ jsnes harness: first stomp at emu frame 44 (camera_x=22), second
at emu frame 144 (camera_x=122), death at emu frame 283 (camera_x=5
after a 256-px wrap), `Playing` restart at emu frame 343, third
stomp at emu frame 365. All 22 emulator goldens still match after
the update, and `docs/platformer.gif` regenerated from the new ROM
now shows two clean stomps, a clean side-collision death, the
GameOver screen, and the retry cycle all inside the 6-second demo
window.

Golden updates:
- `tests/emulator/goldens/platformer.png` — the frame-180 capture
  now shows the hero walking forward with a two-coin HUD after
  both autopilot stomps (previously: a frozen bouncing hero).
- `tests/emulator/goldens/platformer.audio.hash` — the track now
  includes two `Boing` stomp bounces, which shifts the hash.
- `examples/platformer.nes` — rebuilt from the rewritten source.

Also updates the platformer rows in `README.md` and
`examples/README.md` to match the new gameplay.

https://claude.ai/code/session_013Bi4H4YQ5or5HtMB4doUFi
2026-04-13 20:23:07 +00:00
..
arrays_and_functions.ne Add README, LICENSE, examples, fix draw parser lookahead 2026-04-12 00:38:19 +00:00
arrays_and_functions.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
audio_demo.ne examples: adopt the friendly asset syntax 2026-04-13 18:04:21 +00:00
audio_demo.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
bitwise_ops.ne examples: add 5 new programs covering match/loop/logic/bitwise/scanline 2026-04-12 19:05:18 +00:00
bitwise_ops.nes fix(optimizer): preserve cross-block LoadImm uses in const_fold DCE 2026-04-13 16:29:44 +00:00
bouncing_ball.ne
bouncing_ball.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
coin_cavern.ne M2: Wire IR pipeline, add Coin Cavern example and integration tests 2026-04-11 23:34:35 +00:00
coin_cavern.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
comparisons.ne examples: 4 new programs covering MMC3 + other e2e gaps 2026-04-12 20:48:31 +00:00
comparisons.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
friendly_assets.ne language: pleasant asset syntax for palettes, CHR, bg, sfx, music 2026-04-13 16:09:53 +00:00
friendly_assets.nes language: pleasant asset syntax for palettes, CHR, bg, sfx, music 2026-04-13 16:09:53 +00:00
function_chain.ne examples: 4 new programs covering MMC3 + other e2e gaps 2026-04-12 20:48:31 +00:00
function_chain.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
hello_sprite.ne
hello_sprite.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
inline_asm_demo.ne examples: inline_asm_demo.ne 2026-04-12 18:02:59 +00:00
inline_asm_demo.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
logic_ops.ne examples: add 5 new programs covering match/loop/logic/bitwise/scanline 2026-04-12 19:05:18 +00:00
logic_ops.nes fix(optimizer): preserve cross-block LoadImm uses in const_fold DCE 2026-04-13 16:29:44 +00:00
loop_break_continue.ne examples: add 5 new programs covering match/loop/logic/bitwise/scanline 2026-04-12 19:05:18 +00:00
loop_break_continue.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
match_demo.ne examples: add 5 new programs covering match/loop/logic/bitwise/scanline 2026-04-12 19:05:18 +00:00
match_demo.nes fix(optimizer): preserve cross-block LoadImm uses in const_fold DCE 2026-04-13 16:29:44 +00:00
mmc1_banked.ne Add README, LICENSE, examples, fix draw parser lookahead 2026-04-12 00:38:19 +00:00
mmc1_banked.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
mmc3_per_state_split.ne examples: 4 new programs covering MMC3 + other e2e gaps 2026-04-12 20:48:31 +00:00
mmc3_per_state_split.nes fix(optimizer): preserve cross-block LoadImm uses in const_fold DCE 2026-04-13 16:29:44 +00:00
palette_and_background.ne examples: adopt the friendly asset syntax 2026-04-13 18:04:21 +00:00
palette_and_background.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
platformer.ne feat(platformer): add stomp-or-die enemy collisions, live HUD, GameOver state 2026-04-13 20:23:07 +00:00
platformer.nes feat(platformer): add stomp-or-die enemy collisions, live HUD, GameOver state 2026-04-13 20:23:07 +00:00
README.md feat(platformer): add stomp-or-die enemy collisions, live HUD, GameOver state 2026-04-13 20:23:07 +00:00
scanline_split.ne examples: add 5 new programs covering match/loop/logic/bitwise/scanline 2026-04-12 19:05:18 +00:00
scanline_split.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
sprites_and_palettes.ne examples: adopt the friendly asset syntax 2026-04-13 18:04:21 +00:00
sprites_and_palettes.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
state_machine.ne Add README, LICENSE, examples, fix draw parser lookahead 2026-04-12 00:38:19 +00:00
state_machine.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
structs_enums_for.ne Language: struct literals 2026-04-12 17:15:57 +00:00
structs_enums_for.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00
two_player.ne examples: 4 new programs covering MMC3 + other e2e gaps 2026-04-12 20:48:31 +00:00
two_player.nes fix(optimizer): preserve cross-block LoadImm uses in const_fold DCE 2026-04-13 16:29:44 +00:00
uxrom_banked.ne examples: add uxrom_banked and jsnes golden 2026-04-13 02:04:25 +00:00
uxrom_banked.nes commit built ROMs alongside .ne sources 2026-04-13 15:12:39 +00:00

NEScript Examples

Quick Start

# Build the compiler
cargo build --release

# Compile all examples
for f in examples/*.ne; do cargo run -- build "$f"; done

# Or compile one
cargo run -- build examples/hello_sprite.ne

Open any .nes file in an NES emulator (Mesen, FCEUX, etc.)

Examples

File Features Description
hello_sprite.ne input, draw Move a sprite with the d-pad
bouncing_ball.ne if/else, variables Auto-bouncing sprite with edge detection
coin_cavern.ne states, functions, constants 3-state game with gravity and coin collection
arrays_and_functions.ne arrays, functions, while Enemy array with collision detection
state_machine.ne on enter/exit, transitions Multi-state flow with timers
sprites_and_palettes.ne sprites, scroll, cast Inline CHR data, PPU scroll writes, type casting
mmc1_banked.ne MMC1, banks, multiply Banked mapper with software multiply
palette_and_background.ne palette, background, set_palette, load_background Reset-time initial load plus vblank-safe runtime swaps
friendly_assets.ne named colours, grouped palette, pixel art, tilemap+legend, palette_map, scalar sfx pitch, note-name music Exercises every "friendlier" asset syntax at once — the palette uses bg0..sp3 + a shared universal:, the sprite is authored as ASCII pixel art, the background uses a legend { ... } + map: tilemap with a palette_map: for attributes, the sfx uses a scalar pitch: + envelope: alias, and the music uses note names (C4, E4 40, rest 10) with a tempo: default.
platformer.ne every subsystem End-to-end side-scrolling demo: custom CHR tileset, full 32×30 nametable with per-region attribute palettes, 2×2 metasprite hero with gravity/jump physics, wrap-around horizontal scrolling, stomp-or-die enemy collisions with a live stomp-count HUD, coin pickups, user-declared SFX + music, and a Title → Playing → GameOver state machine with a proximity-based autopilot so the headless harness cycles through stomp, stomp, die, and retry inside six seconds. Regenerate the tile art with cargo run --bin gen_platformer_tiles.

Emulator Controls

NES Button Typical Key
D-pad Arrow keys
A Z
B X
Start Enter
Select Right Shift

About Sprites

Sprite names in draw Player at: (x, y) are parsed and recorded in the AST. You can define sprites with inline CHR tile data:

sprite Player {
    chr: [0x3C, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3C,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
}

If no matching sprite declaration exists, the draw uses the built-in default tile (a smiley face). See sprites_and_palettes.ne for a full example.

Compiler Commands

# Compile to ROM
cargo run -- build game.ne

# Custom output path
cargo run -- build game.ne --output my_game.nes

# Type-check only
cargo run -- check game.ne

# View generated 6502 assembly
cargo run -- build game.ne --asm-dump

# Debug mode
cargo run -- build game.ne --debug