---
title: Starfleet Clash — real-time multiplayer fleet battles
repo: starfleet
priority: 9
---

# Starfleet Clash — real-time multiplayer space fleet battles

A **real-time multiplayer** browser game: each player commands a **small fleet** of ships on a
large 2D space map, and fleets fight — maneuvering, firing different weapons, and launching
strikes of small fighter craft. Top-down space combat, RTS-lite fleet control, twitch + tactics.

## THE BIG DIFFERENCE FROM THE OTHER GAMES: it's client–server, not single-file
Real-time multiplayer needs an **authoritative server**. Architecture:
- **Server** (Node.js + `ws` websockets, no framework needed): owns the authoritative game state,
  runs the sim at a fixed tick (e.g. 20 Hz), receives player *inputs/orders*, broadcasts state
  snapshots. Rooms/lobbies so multiple matches run independently. This is the source of truth —
  clients never trust each other.
- **Client** (vanilla HTML5 canvas + ES modules, like the other games): renders the world,
  captures orders (select ships, move, target, fire, launch fighters), sends them to the server,
  and **interpolates** between server snapshots for smooth motion. No authoritative logic on the client.
- Wire protocol: small JSON (or binary later) messages — `join`, `input/orders`, `snapshot`,
  `spawn`, `hit`, `death`, `matchEnd`. Snapshot = entities the client can see (positions, hp, type).

## Fleet & control
- Each player starts with a **small fleet** (~3–6 ships) of mixed classes. RTS-style: click/drag to
  select ships, right-click to move/attack-move, hotkeys for abilities. On mobile: tap-select + tap-move.
- Ships have **position, velocity, facing, hp, shields, and a weapon loadout**; they turn and
  accelerate with momentum (space feel), auto-fire weapons at in-range enemies, and obey move/target orders.

## Ship classes (each with distinct weapons/capabilities)
- **Fighter** — tiny, fast, weak; cheap; swarms. Launched in strikes (see Carrier).
- **Corvette** — nimble gunship, rapid light cannons, good vs fighters.
- **Frigate** — balanced, medium railguns + light missiles.
- **Destroyer** — slow, heavy; long-range torpedoes / heavy cannons, high hp, weak vs swarms.
- **Carrier** — launches **fighter strikes** (spawns a squadron of fighters that attack a target,
  then return/rearm), light self-defense, high value target.
- **Support/Repair** — repairs nearby friendly hulls / boosts shields, no offense.
Weapons differ by **range, tracking, damage type, fire rate, projectile speed** (cannons =
hitscan-ish fast bullets; missiles/torpedoes = tracking entity projectiles with travel time;
fighters = spawned units). Rock-paper-scissors: fighters beat destroyers, corvettes beat fighters,
destroyers beat frigates, etc.

## Match loop
- Larger map (scrolling camera + minimap — reuse the exoforge camera/minimap patterns). Players
  spawn on opposite sides. **Objective:** destroy the enemy fleet (or capture points / a flagship —
  start with team-wipe, add modes later). 2-player first; design rooms so N-player / 2v2 is a config bump.
- Respawn/reinforcement optional (start with no respawn — last fleet standing wins).

## Modules
**server/**: `server.js` (ws server + room manager), `sim.js` (authoritative fixed-tick sim:
movement, weapons, projectiles, fighters, collisions, deaths, win check — pure, serializable
state, DOM-free), `entities.js` (ship classes + weapon defs), `protocol.js` (message shapes),
`room.js` (per-match state + player slots).
**client/** (`index.html` + `src/`): `net.js` (websocket client, snapshot buffer + interpolation),
`input.js` (selection + orders → server), `render.js` (world, ships by class/facing, projectiles,
fighters, effects), `hud.js` (fleet status, minimap, order feedback), `camera.js`, `main.js` (loop:
apply interpolated snapshot → render; send orders).

## Testability
- Server sim is a pure `tick(state, inputsByPlayer, dt)` — headless unit-testable (two fleets,
  step N ticks, assert combat resolves + a winner emerges).
- Integration test: spin the server, connect 2 mock ws clients, send orders, assert both receive
  consistent snapshots and a `matchEnd` fires. Client: boots, connects, renders a snapshot, no errors.

## Milestones (each playable + committed)
1. Server + room + 1 ship per player moving on a shared map; client renders both via snapshots + interpolation.
2. Weapons + projectiles + damage + death; a fleet of mixed ships; team-wipe win.
3. Ship classes + distinct weapons + rock-paper-scissors; carrier fighter strikes.
4. Camera + minimap + selection/orders UX polish; lobby to create/join a match.
5. Feel: momentum, shields, hit/explosion effects, HUD, balance pass.

Vanilla stack, no build step on the client; server is plain Node + `ws`. Deploy = static client +
the Node ws server (needs the deploy host to run a Node process + expose the ws port, not just static).
