Files
transcience/README.md
T
claude de48afcbd9
ci / verify (push) Successful in 46s
Fix aiming under a scrolling camera; add status and decisions docs
The aim bug was collateral from the camera work. "Mouse relative to the centre
of the screen" WAS the cursor's world position while the world was drawn fixed
at the origin, so subtracting the player position gave the right vector. Once
the camera scrolled, that expression became the aim vector itself, and
subtracting the player position again made the ship aim at a fixed world
location -- walking around swung the crosshair with the mouse held still.

Fixed by inverting the transform the view actually draws with (world = screen -
world_view.position, published by the game scene each frame) rather than
assuming the player is centred, so it still holds if the camera later clamps at
map edges or gets shake or look-ahead. tests/unit/test_aim.gd pins it, including
the regression directly: moving the player must not move the crosshair.

Documentation, for other sessions picking this up cold:
- docs/ROADMAP.md rewritten as the status map -- every feature in the brief
  against its state and the file implementing it, the known gaps called out
  (actor interest management is the notable one), and the ten design questions
  that are genuinely unspecified and should not be guessed at.
- docs/DECISIONS.md, new: settled decisions with their reasoning, so a session
  does not re-litigate or re-ask. Several are not the obvious default -- no
  i-frames, no contact damage, non-interruptible escape, and never sending the
  map seed.
- CLAUDE.md and README point at both.

137 tests; check.sh, test.sh and smoke.sh pass.
2026-09-03 20:58:03 +02:00

50 lines
2.2 KiB
Markdown

# Transcience
Top-down twin-stick bullet-hell with a dedicated, server-authoritative backend.
Godot 4.7, GDScript, no external runtime dependencies.
## Play
```bash
tools/server.sh # dedicated server on :27015
tools/client.sh --join --name ada # connect a client
```
Or run one client and press **Host and play** for a listen server.
**Controls** — WASD move, mouse aim, LMB fire, **E** on the ring in the hub to
enter a dungeon, **hold F** for three seconds to escape back to the hub.
## Develop
```bash
tools/check.sh # parse-check every script ~5s
tools/test.sh # GUT suite, headless ~2s
tools/smoke.sh # server + 2 bot clients, ENet ~35s
godot --headless --path . --script tools/bench.gd
```
Read [CLAUDE.md](CLAUDE.md) first — it is short, and the Godot CLI gotchas in it
will otherwise cost an afternoon.
## What is here
| | |
| --- | --- |
| **Twin-stick bullet hell** | Server-simulated bullet field, ~350 concurrent bullets at 0.24 ms/tick. |
| **Authoritative multiplayer** | Clients send input only. Hits, damage, death and instance transfers are server decisions. Prediction + reconciliation for the local player. |
| **Enemies** | Four readable behaviours (static, drift, orbit, approach, strafe) composed with bullet emitters. |
| **Boss** | The Warden of the Fold: stationary, four phases, each adding one idea. Defined entirely as data. |
| **Lobby hub** | Shared persistent instance with a portal into dungeon runs. |
| **Emergency escape** | Three-second channel back to the hub, cancelled by damage. |
## Docs
- [docs/ROADMAP.md](docs/ROADMAP.md) — what is built, what is next, where each feature lives
- [docs/DECISIONS.md](docs/DECISIONS.md) — settled design decisions and their reasoning
- [CLAUDE.md](CLAUDE.md) — commands, invariants, Godot CLI gotchas
- [docs/WORKFLOW.md](docs/WORKFLOW.md) — agent-assisted Godot development, and why the setup looks like this
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — code map and the node-free simulation
- [docs/NETCODE.md](docs/NETCODE.md) — replication model, hit validation, known gaps
- [docs/ROADMAP.md](docs/ROADMAP.md) — what is built and what is next