Skip to content

Repository files navigation

Halyard Marina at golden hour

INKWAVE

An original Splatoon-style 4v4 turf-war shooter that runs in your browser.
Paint the ground, swim through your ink, out-turf the other team.

▶ Play now · Controls · Online · Run locally · How it works · Contributing

CI three.js r186 No build step MIT


Features

  • Game modes, 4 v 4. Turf War (most ground painted wins) and Zone Control (hold the live zone to count down from 100 — rotating side zones, penalties, overtime). Play against bots on three difficulty levels.
  • Online with friends. Create a private room, share the five-character code, and up to eight players line up in the lobby with their loadouts and looks. Empty slots fill with bots; if someone drops, a bot takes over their squidkid mid-match.
  • Squid form. Hold to dive into your ink: swim fast, refill your tank, climb inked walls, dolphin-jump water gaps.
  • Twelve weapons, each with its own feel: Spritzer, Twinfire Pistols, Canopy Brolly (shotgun + launchable shield), Popper Blaster, Squall Spinner, Glint Charger, Tideline Bow (tri-arrow, two charge rings), Swell Roller, Swish Brush, Brine Cutlass (charged one-hit blade), Sponge Mitts (ink fists, charged leap, wall cling) and Bilge Bucket. Mix any main with any of 15 subs and 19 specials.
  • Seven stages, day or dusk. Tidewater Plaza, Kelpline Terminal, Halyard Marina, Saltpan Basin, Crossroads Market, Lockgate Canals and Terrace Heights, each a real place with its own layout. Some stages change a few pieces for Zone Control.
  • Ink that behaves like liquid. Splats spread and settle, fresh ink is glossy and dries, drips run down walls, and swimming leaves a wake in the surface itself.
  • A map you can actually read. Hold Tab and the camera cranes up into a tilt-shift diorama of the live stage, with pins for your team and one-click Super Jumps.
  • Locker. Choose your squidkid: tentacle style, headgear, face, outfit.
  • Everything procedural. Characters, animation, weapons, textures, props, sound effects and music are all generated in code. There are no downloaded assets except two fonts.

Tidewater Plaza Kelpline Terminal at dusk

Controls

Action Keyboard / mouse Gamepad
Move W A S D Left stick
Aim Mouse Right stick
Fire Left click RT
Squid form Shift LT
Jump / dodge roll Space A
Sub weapon (bomb) Right click / E RB
Special F Y
Map + Super Jump Hold Tab or M, then 1–4 or click a pin View
Pause Esc Start

Gamepads work on the hosted (https) version. On a plain http:// LAN address browsers block the Gamepad API.

Playing online

From the main menu choose Online, then Create a room and send your friends the code (or Join a room and type theirs). The host picks the stage, time of day, match length and whether bots fill empty slots; everyone else picks a team, weapon and look and readies up. The lineup, emotes and ready state are live for everyone in the room.

Rooms run on a tiny relay (a Cloudflare Worker with one Durable Object per room, in server/). It only forwards messages: every player simulates their own squidkid and streams it, and everyone else draws it through the same animation system on a smoothed timeline about a tenth of a second behind. How that works, and the tools used to measure it, are in docs/NET.md.

To play online on your own network, run the relay next to the game:

npm install      # once: the relay runs on wrangler
npm run relay    # ws://<this machine>:8787

A page opened from localhost or a LAN address uses that relay automatically; ?relay=wss://… points it anywhere else.

Running locally

There is no build step. Any static file server works; the included one also serves to your LAN and sends no-cache headers so module updates are never stale.

git clone https://github.com/jaydendavisnc/inkwave.git
cd inkwave
npm install      # Electron + the headless tools
npm start        # the desktop app (Electron)
npm run serve    # or the web version: http://localhost:8490
npm run package  # build the macOS app into dist/ (arm64 + x64)

Optional: drop your own music into songs/ (see songs/README.md); otherwise the procedural soundtrack plays.

Useful URL parameters: ?map=halyard&time=dusk picks a stage, &autostart=180 skips the menus into a 180 s match, &autopilot lets a bot drive you.

npm install      # once, for the headless tools
npm run check    # syntax-check every module
npm run smoke    # boot + 8 s of autopilot in headless Chrome, fails on console errors
npm run build    # assemble dist/ (game + only the three.js addons it imports)
npm run check-maps   # sanity-check every stage layout (and its Zone Control variant)

Bot matches run headless and muted for tuning: MAP=halyard MODE=turf SECS=180 npm run botlab (see tools/botlab/README.md). With the relay running, npm run net-test plays a real match between headless clients and reports what each screen drew (see docs/NET.md).

How it works

  • Ink is painted in texture space. Every paintable face owns a region of one 4K atlas; splats are drawn into it on the GPU while a coarse CPU grid keeps the turf score and gameplay queries in sync. The level shader layers the ink over the surface with its own height, gloss and wetness. See src/world/paint.js and src/world/inkShading.js.
  • Stages are data. A layout is a list of boxes and ramps for one half of the arena; the other half is the 180° rotation, so both teams always get an identical field. Ambient occlusion is baked offline (tools/bake-ao.mjs). See src/world/maps.js.
  • Characters are fully procedural. Geometry, materials, a 60-bone rig and every animation (locomotion, squid form, weapon poses, secondary motion) are code, driven by a spring-based pose system. See docs/RIG.md.
  • Systems talk through events. Weapons, actors and the match emit typed events; effects, HUD and audio subscribe. The contract is documented in docs/EVENTS.md and docs/CONTRACTS.md.
  • Deterministic tooling. The game exposes a freeze/step debug interface so filmstrips, handling measurements and bot simulations are reproducible frame by frame (tools/film.py, tools/measure-handling.mjs).

Rendering is three.js r186 (vendored, plain ES modules with an import map) with GTAO, bloom and a custom grade pass.

Browser support

Chrome and Edge are the target; Firefox works. Safari runs but is slower. A discrete or recent integrated GPU is recommended for the High preset; the settings menu has Medium and Low tiers.

Contributing

Issues and pull requests are welcome. Read CONTRIBUTING.md for the project layout and the checks to run first.

License

MIT © 2026 Jayden Davis. INKWAVE is an independent project and is not affiliated with Nintendo; Splatoon is a trademark of Nintendo.

About

Splatoon-style 4v4 turf-war shooter for the browser, built on three.js. No build step.

Topics

Resources

Contributing

Stars

332 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages