mirror of
https://github.com/imjasonh/nescript
synced 2026-07-08 17:06:04 +00:00
101 lines
4.2 KiB
Text
101 lines
4.2 KiB
Text
|
|
// Pong — a full NES port of the classic two-paddle game.
|
||
|
|
//
|
||
|
|
// Production-quality example: a title screen with a three-option
|
||
|
|
// menu (CPU VS CPU / 1 PLAYER / 2 PLAYERS), live gameplay with
|
||
|
|
// smooth ball physics and two paddles, powerups that bounce
|
||
|
|
// around the playfield and modify gameplay when caught
|
||
|
|
// (long paddle / fast ball / multi-ball), a victory screen with
|
||
|
|
// a fanfare, and a brisk title march. Every piece of the game
|
||
|
|
// (logic, art, sound, states) is authored in NEScript itself —
|
||
|
|
// no external assets, no external tooling.
|
||
|
|
//
|
||
|
|
// The source is split across examples/pong/*.ne files. This
|
||
|
|
// top-level file declares the hardware config, the reset-time
|
||
|
|
// palette and Tileset, the audio/state/logic includes, and the
|
||
|
|
// `start` declaration. Every include is processed by the parser
|
||
|
|
// before lexing, so it's exactly as if the whole game lived in
|
||
|
|
// one .ne file.
|
||
|
|
//
|
||
|
|
// The file layout mirrors how a real NES game would be organised:
|
||
|
|
//
|
||
|
|
// examples/pong.ne — this file, the top-level game
|
||
|
|
// examples/pong/PLAN.md — living implementation plan
|
||
|
|
// examples/pong/constants.ne — layout + gameplay constants
|
||
|
|
// examples/pong/assets.ne — Tileset sprite block
|
||
|
|
// examples/pong/audio.ne — sfx + music
|
||
|
|
// examples/pong/state.ne — global variables
|
||
|
|
// examples/pong/rng.ne — 8-bit Galois LFSR PRNG
|
||
|
|
// examples/pong/render.ne — draw helpers
|
||
|
|
// examples/pong/input.ne — paddle update (M2+)
|
||
|
|
// examples/pong/ball.ne — ball physics (M3+)
|
||
|
|
// examples/pong/powerup.ne — powerup entity (M8+)
|
||
|
|
// examples/pong/title_state.ne — state Title + menu
|
||
|
|
// examples/pong/play_state.ne — state Playing (inner SERVE/PLAY/POINT phase machine)
|
||
|
|
// examples/pong/victory_state.ne — state Victory
|
||
|
|
//
|
||
|
|
// Controls (humans):
|
||
|
|
// D-pad up/down — move your paddle up/down
|
||
|
|
// A / Start — confirm a menu choice
|
||
|
|
// / return to title from the victory screen
|
||
|
|
//
|
||
|
|
// In CPU-vs-CPU mode both paddles are CPU and the game plays
|
||
|
|
// itself; in 1 PLAYER mode you are the left paddle and the CPU is
|
||
|
|
// the right; in 2 PLAYERS mode both sides are human (P1 left,
|
||
|
|
// P2 right). The headless jsnes golden harness boots straight
|
||
|
|
// into CPU VS CPU (title auto-commits after ~45 frames with no
|
||
|
|
// input) so the captured frame is always a scene from actual
|
||
|
|
// gameplay.
|
||
|
|
//
|
||
|
|
// Build: cargo run --release -- build examples/pong.ne
|
||
|
|
// Output: examples/pong.nes
|
||
|
|
|
||
|
|
game "Pong" {
|
||
|
|
mapper: NROM
|
||
|
|
mirroring: horizontal
|
||
|
|
}
|
||
|
|
|
||
|
|
// ── Palette ─────────────────────────────────────────────────
|
||
|
|
//
|
||
|
|
// Classic Pong is a black field with white paddles and white
|
||
|
|
// ball. We add a yellow accent for powerup icons and the menu
|
||
|
|
// cursor so those read as distinct without growing the sprite
|
||
|
|
// sub-palette budget (sprites all share sp0 in NEScript's
|
||
|
|
// codegen).
|
||
|
|
//
|
||
|
|
// Sprite sub-palette 0 vocabulary:
|
||
|
|
// 0 = transparent
|
||
|
|
// 1 = white (paddles, ball, letters, digits)
|
||
|
|
// 2 = lt_gray (reserved for subtle secondary accents)
|
||
|
|
// 3 = yellow (cursor, powerup icons)
|
||
|
|
palette Main {
|
||
|
|
universal: black
|
||
|
|
|
||
|
|
bg0: [dk_gray, lt_gray, white] // center line + score gutters
|
||
|
|
bg1: [dk_blue, blue, sky_blue] // reserved — P1 side accent
|
||
|
|
bg2: [dk_red, red, peach] // reserved — P2 side accent
|
||
|
|
bg3: [dk_olive,olive, yellow] // reserved — powerup flash
|
||
|
|
|
||
|
|
sp0: [white, lt_gray, yellow] // every sprite uses this
|
||
|
|
sp1: [dk_blue, blue, sky_blue] // reserved
|
||
|
|
sp2: [dk_red, red, peach] // reserved
|
||
|
|
sp3: [dk_gray, lt_gray, white] // reserved
|
||
|
|
}
|
||
|
|
|
||
|
|
// Pull in everything else. Order matters only for symbol visibility:
|
||
|
|
// constants before the state variables that use them, state variables
|
||
|
|
// and helpers before state handlers.
|
||
|
|
include "pong/constants.ne"
|
||
|
|
include "pong/assets.ne"
|
||
|
|
include "pong/audio.ne"
|
||
|
|
include "pong/state.ne"
|
||
|
|
include "pong/rng.ne"
|
||
|
|
include "pong/render.ne"
|
||
|
|
include "pong/input.ne"
|
||
|
|
include "pong/ball.ne"
|
||
|
|
include "pong/powerup.ne"
|
||
|
|
include "pong/title_state.ne"
|
||
|
|
include "pong/play_state.ne"
|
||
|
|
include "pong/victory_state.ne"
|
||
|
|
|
||
|
|
start Title
|