1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-08 08:55:38 +00:00
nescript/examples/pong/assets.ne
Claude 21b91f6398
examples/pong: production-quality Pong game with powerups and multi-ball
A complete, playable Pong game split across examples/pong/*.ne files
and pulled in from a top-level examples/pong.ne. Features:

- **Title screen** with a 3-option menu (CPU VS CPU / 1 PLAYER /
  2 PLAYERS), a cursor sprite, blinking "PRESS A" prompt, brisk
  title march on pulse 2, and autopilot that auto-confirms CPU VS
  CPU after 45 frames of no input so the headless jsnes golden
  harness reaches gameplay by frame 180.

- **Ball physics** with signed-magnitude velocity (u8 magnitude +
  sign bit per axis), wall bounce at top/bottom, paddle AABB
  collision with push-out, and score-out detection at left/right
  exits.

- **Multi-ball** via parallel ball_* arrays (MAX_BALLS = 3). Each
  ball scores a point independently; the round continues until the
  last ball exits the playfield.

- **CPU AI** that tracks the nearest active ball heading toward its
  side with a per-frame step, 4 px dead zone, and CPU_SPEED = 1 so
  rallies can end naturally.

- **Three powerup types** that spawn every ~4 seconds, bounce off
  all four walls, and are caught by paddle AABB overlap:
  1. LONG — extends the catching paddle from 24 → 40 px for 5 hits
  2. FAST — doubles ball x-velocity on the catcher's next hit
  3. MULTI — spawns two extra balls on the catcher's next hit

- **Victory** at first-to-7 with a "PLAYER N WINS" banner and the
  builtin fanfare, auto-returning to Title.

- **Audio**: 5 user-declared sfx (WallBounce, PaddleHit, Score,
  PowerSpawn, PowerCatch) plus a title march and the builtin
  fanfare for victory.

Source layout mirrors examples/war:

    examples/pong.ne               top-level game shell
    examples/pong/PLAN.md          living design doc
    examples/pong/constants.ne     layout + gameplay constants
    examples/pong/assets.ne        45-tile Tileset (paddles, ball, alphabet,
                                   digits, cursor, center-line, powerup icons)
    examples/pong/audio.ne         sfx + music declarations
    examples/pong/state.ne         all mutable globals
    examples/pong/rng.ne           8-bit Galois LFSR
    examples/pong/render.ne        draw helpers
    examples/pong/input.ne         paddle step (human + CPU AI)
    examples/pong/ball.ne          multi-ball physics + paddle collision
    examples/pong/powerup.ne       powerup entity (spawn, bounce, catch, apply)
    examples/pong/title_state.ne   state Title + menu
    examples/pong/play_state.ne    state Playing (P_SERVE/P_PLAY/P_POINT)
    examples/pong/victory_state.ne state Victory

Verification:
- 616 compiler unit tests pass (cargo test --all-targets)
- cargo fmt / cargo clippy --all-targets -- -D warnings clean
- 33/33 emulator harness goldens match
- examples/pong.nes builds byte-identically from source

https://claude.ai/code/session_0134F5uwDEVTes2Ee9S7JeXy
2026-04-16 01:25:29 +00:00

458 lines
10 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// pong/assets.ne — the one big Tileset sprite block.
//
// Every custom 8×8 CHR tile in Pong is stacked vertically inside a
// single `sprite Tileset { pixels: [...] }` declaration. The parser
// splits each consecutive 8 rows into its own tile, so tile index N
// in a `draw Tileset frame: N` call picks the N'th block.
//
// Every constant in constants.ne points at a position in this list.
// If you add or remove a tile, update BOTH this file AND the matching
// constant range.
//
// Colour vocabulary (sp0 sub-palette in pong.ne):
// . transparent
// 1 white (paddles, ball, alphabet, digits)
// 2 lt_gray (reserved — subtle accents)
// 3 yellow (powerup icons, cursor highlight)
sprite Tileset {
pixels: [
// ── 01-26: alphabet A..Z (6-wide bold on transparent) ─
//
// Bold sans-serif letters with 2-pixel strokes so they
// still read on a CRT. Every letter is 6 wide, centred
// in the 8-wide tile. This block is the same shape as
// war's alphabet so a future refactor could lift it into
// a shared include.
// A
"........",
"..1111..",
".11..11.",
".11..11.",
".111111.",
".11..11.",
".11..11.",
"........",
// B
"........",
".11111..",
".11..11.",
".11111..",
".11..11.",
".11..11.",
".11111..",
"........",
// C
"........",
"..11111.",
".11..11.",
".11.....",
".11.....",
".11..11.",
"..11111.",
"........",
// D
"........",
".1111...",
".11.11..",
".11..11.",
".11..11.",
".11.11..",
".1111...",
"........",
// E
"........",
".111111.",
".11.....",
".11111..",
".11.....",
".11.....",
".111111.",
"........",
// F
"........",
".111111.",
".11.....",
".11111..",
".11.....",
".11.....",
".11.....",
"........",
// G
"........",
"..11111.",
".11.....",
".11.111.",
".11..11.",
".11..11.",
"..1111..",
"........",
// H
"........",
".11..11.",
".11..11.",
".111111.",
".11..11.",
".11..11.",
".11..11.",
"........",
// I
"........",
"..1111..",
"...11...",
"...11...",
"...11...",
"...11...",
"..1111..",
"........",
// J
"........",
"....111.",
".....11.",
".....11.",
".....11.",
".11..11.",
"..1111..",
"........",
// K
"........",
".11..11.",
".11.11..",
".1111...",
".11.11..",
".11..11.",
".11..11.",
"........",
// L
"........",
".11.....",
".11.....",
".11.....",
".11.....",
".11.....",
".111111.",
"........",
// M
"........",
".11..11.",
".111111.",
".111111.",
".11..11.",
".11..11.",
".11..11.",
"........",
// N
"........",
".11..11.",
".111.11.",
".111111.",
".11.111.",
".11..11.",
".11..11.",
"........",
// O
"........",
"..1111..",
".11..11.",
".11..11.",
".11..11.",
".11..11.",
"..1111..",
"........",
// P
"........",
".11111..",
".11..11.",
".11..11.",
".11111..",
".11.....",
".11.....",
"........",
// Q
"........",
"..1111..",
".11..11.",
".11..11.",
".11.111.",
".11.11..",
"..111.1.",
"........",
// R
"........",
".11111..",
".11..11.",
".11..11.",
".11111..",
".11.11..",
".11..11.",
"........",
// S
"........",
"..11111.",
".11.....",
"..1111..",
".....11.",
".....11.",
".11111..",
"........",
// T
"........",
".111111.",
"...11...",
"...11...",
"...11...",
"...11...",
"...11...",
"........",
// U
"........",
".11..11.",
".11..11.",
".11..11.",
".11..11.",
".11..11.",
"..1111..",
"........",
// V
"........",
".11..11.",
".11..11.",
".11..11.",
".11..11.",
"..1111..",
"...11...",
"........",
// W
"........",
".11..11.",
".11..11.",
".11..11.",
".111111.",
".111111.",
".11..11.",
"........",
// X
"........",
".11..11.",
"..1111..",
"...11...",
"...11...",
"..1111..",
".11..11.",
"........",
// Y
"........",
".11..11.",
".11..11.",
"..1111..",
"...11...",
"...11...",
"...11...",
"........",
// Z
"........",
".111111.",
".....11.",
"....11..",
"...11...",
"..11....",
".111111.",
"........",
// ── 27-36: digits 0..9 ────────────────────────────
// 0
"........",
"..1111..",
".11..11.",
".11..11.",
".11..11.",
".11..11.",
"..1111..",
"........",
// 1
"........",
"...11...",
"..111...",
".1.11...",
"...11...",
"...11...",
"..1111..",
"........",
// 2
"........",
"..1111..",
".11..11.",
".....11.",
"....11..",
"..11....",
".111111.",
"........",
// 3
"........",
"..1111..",
".11..11.",
"....11..",
".....11.",
".11..11.",
"..1111..",
"........",
// 4
"........",
"....11..",
"...111..",
"..1.11..",
".11.11..",
".111111.",
"....11..",
"........",
// 5
"........",
".111111.",
".11.....",
".11111..",
".....11.",
".11..11.",
"..1111..",
"........",
// 6
"........",
"..1111..",
".11.....",
".11111..",
".11..11.",
".11..11.",
"..1111..",
"........",
// 7
"........",
".111111.",
".....11.",
"....11..",
"...11...",
"..11....",
"..11....",
"........",
// 8
"........",
"..1111..",
".11..11.",
"..1111..",
".11..11.",
".11..11.",
"..1111..",
"........",
// 9
"........",
"..1111..",
".11..11.",
".11..11.",
"..11111.",
".....11.",
"..1111..",
"........",
// ── 37: paddle top cap ────────────────────────────
//
// Paddles are 8 px wide and an integer number of tiles
// tall. Each paddle is rendered as TOP + (N-2) × MID + BOT,
// where N is 3 in normal mode (24 px) or 5 in long mode
// (40 px). The cap tiles are rounded at the outer edge so
// the paddle doesn't look like a blunt slab.
"..1111..",
".111111.",
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
// ── 38: paddle middle (repeated for tall paddles) ─
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
// ── 39: paddle bottom cap ─────────────────────────
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
"11111111",
".111111.",
"..1111..",
// ── 40: ball ──────────────────────────────────────
//
// 6×6 filled circle centred in the 8×8 tile.
"........",
"..1111..",
".111111.",
".111111.",
".111111.",
".111111.",
"..1111..",
"........",
// ── 41: cursor arrow (▶) ─────────────────────────
//
// Yellow-tinted so it pops against white menu text.
"........",
"..3.....",
"..33....",
"..333...",
"..333...",
"..33....",
"..3.....",
"........",
// ── 42: center-line dash ──────────────────────────
//
// A vertical 2-px stripe down the centre column of the
// tile. Repeated every 32 px vertically to form the
// classic Pong dashed divider.
"...11...",
"...11...",
"...11...",
"...11...",
"...11...",
"...11...",
"...11...",
"...11...",
// ── 43: powerup LONG icon ─────────────────────────
//
// A yellow "L" on a framed background. The frame is
// white so the icon reads against the black playfield.
"11111111",
"13....31",
"13.3..31",
"13.3..31",
"13.3..31",
"13.3333.",
"13....31",
"11111111",
// ── 44: powerup FAST icon (F) ─────────────────────
"11111111",
"13....31",
"13.3333.",
"13.3..31",
"13.333.1",
"13.3..31",
"13.3..31",
"11111111",
// ── 45: powerup MULTI icon (M) ────────────────────
"11111111",
"13....31",
"13.3.3.1",
"13.333.1",
"13.3.3.1",
"13.3.3.1",
"13.3.3.1",
"11111111"
]
}