mirror of
https://github.com/imjasonh/nescript
synced 2026-07-08 00:45:38 +00:00
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
29 lines
780 B
Text
29 lines
780 B
Text
// pong/rng.ne — 8-bit Galois LFSR PRNG.
|
|
//
|
|
// Classic maximal-period 8-bit Galois LFSR: shift right and XOR in
|
|
// the tap mask 0xB8 whenever the LSB was 1. The sequence visits
|
|
// every non-zero 8-bit value exactly once over 255 calls, which
|
|
// is enough randomness for serve-direction jitter, powerup kind
|
|
// selection, and AI reaction noise.
|
|
|
|
// Advance the LFSR by one step and return the new byte.
|
|
fun rng_next() -> u8 {
|
|
var s: u8 = rng_state
|
|
var lsb: u8 = s & 1
|
|
s = s >> 1
|
|
if lsb == 1 {
|
|
s = s ^ 0xB8
|
|
}
|
|
rng_state = s
|
|
return s
|
|
}
|
|
|
|
// Seed the LFSR. 0 is a degenerate state (the LFSR stays at 0
|
|
// forever), so we coerce zero seeds to 1.
|
|
fun rng_seed(s: u8) {
|
|
if s == 0 {
|
|
rng_state = 1
|
|
} else {
|
|
rng_state = s
|
|
}
|
|
}
|