1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-11 02:02:58 +00:00
nescript/examples/pong/assets.ne

459 lines
10 KiB
Text
Raw Normal View History

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
// 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"
]
}