77 lines
3.4 KiB
Markdown
77 lines
3.4 KiB
Markdown
# slither.ts 🐍
|
||
|
||
A full **slither.io clone** written in TypeScript — authoritative Node.js + WebSocket
|
||
server, Canvas 2D client, zero asset files (every texture is generated at runtime,
|
||
every sound is synthesized with the Web Audio API).
|
||
|
||
## Run it
|
||
|
||
```bash
|
||
npm install
|
||
npm run build
|
||
npm start
|
||
```
|
||
|
||
Then open **http://localhost:8080** in your browser. Open more tabs (or other
|
||
machines on your LAN) for more human players — the arena is automatically
|
||
filled to 12 snakes with AI bots.
|
||
|
||
For development: `npm run dev` builds and starts the server.
|
||
|
||
## Features
|
||
|
||
- **Smooth movement** — 30 Hz authoritative simulation, 15 Hz snapshots,
|
||
client-side dead reckoning (the client runs the same movement model every
|
||
frame) with decaying snapshot-correction offsets, plus dt-based exponential
|
||
camera smoothing
|
||
- **Grow by eating glowing pellets** scattered across the arena
|
||
- **Boost** with `SPACE` (or hold left mouse / second touch finger) — moves
|
||
~2× faster while burning your length and shedding pellets from your tail
|
||
- **Eliminations** — make others crash into your body; you cannot collide with
|
||
yourself
|
||
- **Death explosions** — dead snakes burst into glowing pellets along their
|
||
whole body for everyone else to harvest
|
||
- **Live leaderboard** (top 10, updates in real time) + score / rank / kills HUD
|
||
- **Instant respawning** — click or hit `Enter`, no countdown
|
||
- **Large circular arena** with a glowing red border that kills on contact
|
||
- **Minimap** showing the entire map, all players and your position
|
||
- **Slither.io-style background** — dark grey gradient, repeating hexagon grid,
|
||
faint glowing hexagon outlines, soft ambient light + vignette
|
||
- **AI bots** with pellet-seeking, obstacle avoidance and hunting behaviour
|
||
- **Main menu** with nickname entry, **settings** (volume, quality, minimap),
|
||
and **fullscreen** support — all persisted to localStorage
|
||
- **Sound effects** (eat, boost whoosh, death explosion, UI clicks) and
|
||
**particle effects** (eat sparkles, boost bubbles, death bursts)
|
||
|
||
## Controls
|
||
|
||
| Input | Action |
|
||
| ---------------- | ------------------------------- |
|
||
| Mouse / touch | Steer (snake follows cursor) |
|
||
| `SPACE` / click | Boost (drains length) |
|
||
| `Enter` | Instant respawn when dead |
|
||
|
||
## Project layout
|
||
|
||
```
|
||
shared/ constants + protocol shared by client & server
|
||
server/ world simulation (movement, collisions, bots) + HTTP/WS server
|
||
client/src/ renderer, background, minimap, particles, audio, UI, input
|
||
public/ index.html, style.css and the compiled client JS
|
||
scripts/ smoke.mjs — end-to-end WebSocket smoke test
|
||
```
|
||
|
||
## How it works
|
||
|
||
The server simulates everything at 30 ticks/s and broadcasts compact JSON
|
||
snapshots at 15 Hz (snake bodies as flat integer arrays; pellets as incremental
|
||
add/remove deltas after a one-time full list). The client does **not** render
|
||
the snapshots directly — it runs the same movement model locally every frame
|
||
(dead reckoning): your own snake is steered straight from your input angle
|
||
with the server's turn-rate limit (zero perceived input latency), remote
|
||
snakes use headings estimated from snapshot deltas. Each snapshot captures
|
||
the prediction error as per-point correction offsets that decay smoothly over
|
||
the following frames, so server authority is kept without any visible steps.
|
||
Collision and eating use a uniform-grid spatial hash, so the sim stays fast
|
||
with a full arena of long snakes.
|