orbit/README.md

146 lines
7.8 KiB
Markdown
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.

# 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/settlements are
generated lazily on arrival, deterministically (seed + system id), so
lazy and eager give identical results.
- **A lived-in galaxy**: the galaxy was settled long before you arrive.
Systems host colonies on habitable worlds, mining stations over resource
worlds, cloud bases riding gas giants, stations adrift in open space, and
beacons — or report *charted · unclaimed* when nobody's there. Rates are
per-archetype (`data/systems.json`) and thin out from the settled core to
the wilder rim (`data/galaxy.json`). Each settlement has a name,
population, and an `owner` seam reserved for the factions/pirates to come.
The current system's dossier (name, identity, what's there) shows
top-left in the game scene.
- Game screen with a basic top-down ship: **click anywhere to fly there**
in the current system's open space (system boundaries/jumps come next).
Discovered worlds get a screen-edge arrow + name tag; **clicking the
name tag autopilots the ship there** (it arrives on the keep-out rim,
facing the world)
- **The home planet** — the player's Terran world — in the system you
start in: a 1024 px disc rendered 1:1 from the `assets/images/planets.png`
spritesheet. Which Terran face it shows (frames 02) is a
seed-deterministic pick, so the same galaxy always yields the same home
world. The ship spawns ~150 px (edge-to-edge) off its rim in a
seed-derived direction, may fly in as close as 50 px from the rim, and
can never cross it — a planet is solid (tuning in `data/planets.json`)
- 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
│ ├── theme.json # shared UI theme: fonts, palette, CRT/glitch tuning
│ ├── ship.json # ship feel: thrust, drag, maxSpeed, …
│ ├── galaxy.json # galaxy scale & shape (count, radius, spiral…)
│ ├── systems.json # system archetypes: theme, attributes, distribution
│ ├── settlements.json # the lived-in layer: settlement kinds & populations
│ ├── research.json # RESEARCH: time-based, one at a time, gates builds/research
│ ├── builds.json # BUILDING: credits + minerals, ship/planet/station upgrades
│ ├── actionbar.json # the command deck: 6 slots (Research, Build, Ship, ·, ·, Menu)
│ └── naming.json # syllable pools for names
├── assets/images/ # art: planets.png (1024×1024 spritesheet frames)
├── assets/fonts/ # UI typefaces: Ethnocentric (headers), Centauri (body)
├── 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), Planet (home world, solid)
│ ├── galaxy/ # Galaxy (seeded world model), SystemGenerator, SystemReport
│ ├── ui/ # MenuButton, GlitchText, CyberShape, ActionBar, DiscoveryCompass (reusable)
│ ├── visuals/ # Starfield, CyberOverlay (CRT/glitch, shared)
│ ├── 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).
## The player's loop: research + building
Beyond flying, Orbit is built around two progression verbs — both are data
layers now, with the rules and panels to come next:
- **Research** (`data/research.json`) — *time-based*. A project takes a fixed
`duration`; the player researches **one thing at a time**
(`maxConcurrent: 1`). Research is the gate: it unlocks **builds** and
**further research**. `projects` is an empty map for now; the `_template`
entry documents the shape each project must have.
- **Building** (`data/builds.json`) — *cost-based*, paid in **credits and
minerals** (`resources`). A build improves the **ship**, a **planet**, or a
**space station** (`category`). `builds` is an empty map; the `_template`
entry documents the shape (including `repeatable`, for things like extra
mining rigs).
- **The command deck** (`data/actionbar.json`, rendered by
`js/ui/ActionBar.js`) — the cyberpunk bar across the bottom of the screen.
Six evenly spaced slots: **Research, Build, Ship, ·, ·, Menu**. The slots
fire `onAction` and are otherwise inert; two slots are reserved. Dressed
with the menu's CRT language — scanlines over the strip and the GlitchText
RGB pull-apart on icons, labels, and the panel outline during bursts. All
layout, palette, and motion (boot flicker, rail comet, glitch bursts, RGB
split, scanlines) live in the config.
`_`-prefixed keys (`_comment`, `_template`, …) are documentation, not
runtime data — loaders and tests ignore them.
## 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
node dev/discovery.test.mjs # discovery rules + compass geometry + chip hit test
node dev/research-builds.test.mjs # data contract: research/builds/actionbar shapes + manifest
```
`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.