A Krunker-style browser FPS — fast blocky team deathmatch against AI bots, in ~3k lines of TypeScript.
Bhop, slide, class builder, 5 hitscan weapons, bot AI with pathfinding, and a full title-screen → matchmaking → match → victory loop. No game engine, no physics library, no art or audio assets — everything is boxes, math and a WebAudio synth.
Features · Screenshots · How it works · Run it · Roadmap
Note: BLOCKSHOT is a personal learning project — a gameplay homage to Krunker.io built to explore FPS fundamentals (movement feel, hitscan combat, bot AI) from scratch. It is not affiliated with Krunker and ships none of its assets or code.
| Feature | How |
|---|---|
| 🏃 Krunker-feel movement | Fast base speed, hold-Space auto-bhop (chained jumps stack a speed bonus), Shift-slide with momentum-carrying slide-jumps, stair auto-step, FOV kick at speed. Custom capsule-vs-AABB collision — no physics lib. |
| 🔫 5 hitscan weapons | Assault Rifle, SMG, 8-pellet Shotgun, scoped Sniper, Revolver. Fully data-driven (src/data/weapons.ts) — recoil, hip/move/air spread, reload, headshot multipliers. A 6th weapon is one data entry. |
| 🧰 Class builder | 5 presets (Triggerman, Run N Gun, Bruiser, Hunter, Detective) + a custom class editor: primary / secondary / perk, persisted to localStorage. |
| 🤖 Bot AI | Finite state machine (roam → engage → hunt) over a waypoint graph with BFS pathing, line-of-sight raycasts, per-bot reaction time, and aim wobble that tightens as they track you. Bots run the exact same movement & weapon code as the player — no cheating. |
| ⚔️ TDM | Match à mort par équipe — 4v4 (you + 3 bots vs 4), first to 50 kills or 5:00, smart spawn selection, respawn timers. |
| 🖥️ Full game loop | Title screen with match selector and fake matchmaking (a lobby fills with bot names), HUD with dynamic-spread crosshair, killfeed, hitmarkers, damage vignette, Tab scoreboard, victory/defeat screen. |
| 🔊 Synthesized audio | Every gunshot, hitmarker and kill sound is generated by a tiny WebAudio synth — the repo contains zero audio files. |
| Scoreboard | Match end |
|---|---|
![]() |
![]() |
| Key | Action |
|---|---|
WASD |
Move |
Space (hold) |
Jump / auto-bhop |
Shift |
Slide |
LMB / RMB |
Fire / Scope (sniper) |
R |
Reload |
1 2 / wheel |
Swap weapon |
Tab |
Scoreboard |
src/
core/ game loop, pointer-lock input, AABB/ray math
data/ weapons, classes/perks, maps — pure data, no logic
game/ world (scene + colliders + waypoint graph), pawn (shared player/bot
movement & health), combat (hitscan), bot (FSM AI), match (TDM rules),
session (renderer / camera / viewmodel / HUD glue), audio (synth)
ui/ title + matchmaking + end screens, class builder, HUD, scoreboard
The key design choice: the simulation never touches rendering. Pawn, Match, combat
and Bot are plain math over positions and AABBs — session.ts and avatar.ts only
visualize them. That separation is deliberate: a future multiplayer server can run the same
sim headless and stay authoritative.
Other bits worth a look:
- Movement (
game/pawn.ts) — per-axis swept AABB collision with step-up (stairs are just boxes), slide with a locked direction and decaying speed, bhop stacks with a landing window. - Combat (
game/combat.ts) — cone-spread hitscan rays tested against the map, then against head spheres and body boxes; nearest hit wins. - Bots (
game/bot.ts) — waypoint graph edges are computed at load by raycasting between waypoints; pathing is a BFS; "humanity" comes from reaction delay + sinusoidal aim error. - Maps (
data/maps.ts) — a map is a list of colored boxes, spawn points and waypoints. New map = new data file, zero code.
Requires Bun.
bun install
bun run dev # → http://localhost:5173bun run build typechecks and produces a static production build in dist/.
Rough payoff order — the sim/render split above is what makes #1 tractable:
- Real multiplayer — Bun WebSocket server running the existing sim authoritatively, client prediction + interpolation, bots backfilling lobbies
- More modes — FFA, Gun Game, Capture the Flag, Hardpoint
- Map editor — in-browser box placement exporting the same map format
- Progression — XP, currency, weapon skins, unlockable classes
- Grenades & abilities, movement depth (wall-slide, air-strafe tuning), killcam, mobile controls
- Three.js — rendering (Lambert materials, one directional shadow light)
- TypeScript (strict) + Vite
- Bun — package manager & runner
- No other runtime dependency — physics, AI, audio and UI are hand-rolled




