orbit/README.md

92 lines
4.1 KiB
Markdown

# Orbit
> A procedurally generated space RPG in the spirit of *Privateer*, in
> top-down 2D. Built with **Phaser 4** as plain **ES6 modules** — no build
> step, no package managers required to run.
## Run it
Any static file server works (Python, Node, Caddy, nginx, …):
```sh
cd orbit
python3 -m http.server 8080
# → http://localhost:8080
```
> Must be served over **http(s)** — opening `index.html` via `file://` won't
> work, because the game uses ES modules and `fetch`es its JSON config.
## Current state — v0.2: a seedable galaxy
- Main menu with **New Game** and a **Galaxy Seed** panel: the seed is
displayed, editable (click it and type), and rerollable — and the menu
shows what that seed builds (the galaxy's name, system count, archetype
count) **before** you commit. Same seed ⇒ same galaxy.
- **Procedural galaxy**: 40,000 star systems in a seeded disk + core +
spiral arms (`data/galaxy.json`), typed into six themed archetypes
(`data/systems.json`) with per-type distribution weights and radial
bands — the first "how does the galaxy lay itself out" rules.
- **Two-level generation**: the whole galaxy roster is generated at New
Game (~70 ms); each system's planets/moons/belts are generated lazily on
arrival, deterministically (seed + system id), so lazy and eager give
identical results. The current system's name/identity shows top-left in
the game scene.
- Game screen with a basic top-down ship: **click anywhere to fly there**
in infinite, unbounded space (system boundaries/jumps come next)
- Camera gently trails the ship; the **parallax starfield** streams past
while it flies and the view slowly recenters (≈1.5 s) once the ship
comes to rest
- Config-driven setup: every tunable value lives in `data/*.json`
## Project layout
```
orbit/
├── index.html # boots the game
├── data/ # ← ALL tunable config (edit these freely)
│ ├── manifest.json # which config files exist
│ ├── game.json # dimensions, colors, starfield, …
│ ├── menu.json # menu text, colors, button layout, seed panel
│ ├── ship.json # ship feel: thrust, drag, maxSpeed, …
│ ├── galaxy.json # galaxy scale & shape (count, radius, spiral…)
│ ├── systems.json # system archetypes: theme, attributes, distribution
│ └── naming.json # syllable pools for names
├── lib/ # vendored third-party libs (Phaser 4.2.1)
├── js/
│ ├── main.js # entry point: load config → boot Phaser
│ ├── config/ # Config singleton, ConfigLoader, game config
│ ├── scenes/ # MenuScene, GameScene (thin, orchestration)
│ ├── entities/ # Ship (own behavior)
│ ├── galaxy/ # Galaxy (seeded world model), SystemGenerator
│ ├── ui/ # MenuButton (reusable)
│ ├── visuals/ # Starfield (decorative)
│ ├── utils/ # small pure helpers (Color, Rng, NameGenerator)
│ └── vendor/ # shim to the vendored Phaser
└── docs/PROJECT_NOTES.md # ← project conventions: read this
```
## Conventions (short version)
- **Config in JSON.** If a value might change, it goes in `data/`, not code.
Add a file = one line in `data/manifest.json`.
- **One class per file**, ES modules, scenes stay thin, entities own their
behavior. Details in [`docs/PROJECT_NOTES.md`](docs/PROJECT_NOTES.md).
- Phaser is imported only via `js/vendor/phaser.js` (one-file version swap).
## Dev tools
```sh
node dev/ship-behavior.test.mjs # runs the real Ship.update() loop in Node
node dev/starfield.test.mjs # runs the real Starfield.create() in Node
node dev/galaxy.test.mjs # galaxy determinism, distribution, lazy vs eager
```
`dev/test-game.html` boots straight into the GameScene (no menu click),
handy for manual testing of the flight feel.
## Phaser
Phaser 4.2.1 is vendored at `lib/phaser.min.js` (UMD build, MIT license —
see `lib/PHASER_LICENSE.md`). No internet or npm needed at runtime.