142 lines
7.5 KiB
Markdown
142 lines
7.5 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/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)
|
||
- **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 0–2) 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/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.
|