Chernobyl

A Duke-Nukem-style FPS built from scratch in C with raylib — text-driven maps, postprocess pipeline, 18 enemy types, and arena combat in your browser

Modular C codebase • zero dependencies beyond raylib

Screenshots

Arsenal

Shotgun
Browning Auto-5
  • Fire Rate0.59s
  • Damage15 × 8 pellets
  • Max Ammo32 shells
  • SpecialDistance-scaled
Machine Gun
MP40
  • Fire Rate0.09s
  • Damage18 per round
  • Max Ammo120 rounds
  • SpecialFull-auto
Launcher
Panzerschreck
  • Fire Rate0.96s
  • Damage200 + 200 splash
  • Max Ammo8 rockets
  • Splash Radius5 meters
Tesla Cannon
Chain Lightning
  • Fire RateCharge-based
  • Damage140 base + chain arcs
  • Range6m primary cone
  • EffectBarrel cascade

Enemies

18 enemy types with billboard sprites, boids separation, multi-state AI, and infighting. Splash damage from rockets and fireballs hits other enemies, triggering chaotic arena brawls.

Chef

65 HP

Standard combatant. Balanced speed and damage output.

Heavy Chef

145 HP

Tank variant. Absorbs punishment, hits harder.

Fast Chef

42 HP

Glass cannon. Closes distance quickly, low survivability.

Cultist

80 HP

Appears alongside chefs in later waves.

Mutant

90 HP

Ranged attacker. Hurls energy balls from distance.

Heavy Mech

260 HP

Armored war machine. Fires rockets from 20m out.

Soldier

HP

Doom shotgunner. Hitscan tracer fire, active in waves.

Cacodemon

HP

Flying fireball spitter. Falls to ground on death with gravity.

Cyber Demon

HP

Boss-tier rocket spammer. Replaces chef boss in wave 2+.

Revenant

HP

Freedoom skeleton with 8-direction walk sprites. Melee combatant, active in waves.

Tentacle Fiend

HP

Ranged tentacled horror. Attacks from distance with projectiles.

Walking Eye

HP

Resurrects nearby corpses. Kill it fast or fight the same enemies twice.

Baron of Hell

HP

Freedoom elite. Heavy melee with HP bar. Hits hard, takes punishment.

Spider Mastermind

HP

Massive boss. Walk-cycle animation, recurring from wave 3 onwards.

Chaingun Zombie

HP

Freedoom CPOS. Rapid-fire hitscan with dedicated chaingun sound.

Lost Soul

HP

Preview. Flying skull, placeholder melee AI.

Pain Elemental

HP

Preview. Floating demon, not in waves yet.

AI STATE MACHINE

Patrol Chase Attack Dying

Controls

W A S DMove
MouseAim / Look
LMBFire
SpaceJump
ShiftSprint
1 2 3 4Switch Weapon
AArena Picker
PPause
- / +Music Volume
MSkip Track / Audio Browser (menu)
EEnemy Sound Lab (menu)
DAsset Discovery (menu)
`Dev Console
F9Audio Browser (in-game)
F11Fullscreen

Architecture

Text-Driven Map Engine

Levels defined in plain-text level0.txt files — walls, spawn points, pickups, and platforms all placed via a human-readable grid. Swap maps without recompiling.

Postprocess Pipeline

Full-screen GLSL post-processing: posterize + ordered dither + warm colour tint. Gives the game a gritty, stylised look on top of the raw 3D scene.

Gibs & Chunky Gore

Enemies explode into gibs and bone fragments on death. Killing blow >2x maxHp triggers chunky-gore mode — 6-10 fatter red chunks, longer-lived floor decals, heavier screen shake, no corpse sprite left behind. Boss-tier enemies use scripted death flourishes instead.

Glowing Tracer Streaks

Projectile bullets leave additive glowing tracer trails. Wall hits spark hot-white with an impact flash. Rockets produce beefier explosions with expanded particle counts.

Floating Damage Numbers

Every hit spawns a white damage number above the enemy. Shotgun pellets aggregate within a 150ms window so a blast reads as one big number. Kill score popups layer on top in yellow.

Camera Juice

Strafe lean rolls the camera into turns. Damage shakes + edge-vignette pulse. 40ms hit-stop world-freeze on kills. Landing kick with shake + dust on hard drops. Warm muzzle screen flash on every shot.

Enemy Sound Lab

Press E from the menu to browse every enemy with an animated walk-cycle preview and per-event sound categories (attack, death, headshot, spawn). Click any row to play. A full dev tool built right into the game.

Powerup Effects

Quad damage and Speed pickups with animated sprites, coloured grab-burst particles, and a screen overlay while active. Low-HP danger pulse tints the edges red.

Custom GLSL Lighting

Hand-written fragment shader with 6 dynamic point lights, distance fog, and per-pixel attenuation. Pulsing additive halos under pickups. Lights flicker and pulse.

Billboard Sprites

18 enemy types rendered as camera-facing quads, back-to-front sorted each frame. Flying enemies fall with gravity. Gold sparks burst on headshots.

Q3-Style Platforms

Moving platforms with Quake 3 Arena-inspired mechanics. Elevators, jump pads, and vertical combat arenas.

Rear-Enemy Warnings

Edge-of-screen threat indicators flash when enemies are behind you. The minimap tints enemies in your rear arc so you always know what’s sneaking up.

Arena Picker

Press A on the main menu to browse all 18 enemy types with cycling sprite previews and attack-frame animations. Spawn any enemy into a test arena.

Dev Console

Quake-style drop-down console toggled with backtick (`). Type wave N to jump to any wave, god for invincibility, noclip, and more. Cheat-aware: using cheats disables leaderboard submission for that run.

Boss Telegraphs

Spider Mastermind: 1.5s red laser-sight tracks your position, then a hitscan burst — sidestep the laser and it misses. Cyber Demon: 1.2s ground-crack ring followed by a 3m AoE stomp with linear falloff, then a twin-rocket combo.

Replay System

Every run is recorded as deterministic inputs + RNG seed in a compact .ifr file (~5-50 KB). Uploaded alongside scores to the leaderboard. Watch any run play back in-browser via versioned WASM builds — old replays stay watchable forever across game updates.

Video Recording

Native (macOS): captures gameplay as H.264 MP4 at 960×540 / 1.0 Mbps with AAC audio. Continues recording 3 seconds after death so the killing blow, “YOU DIED” splash, and final score all land in the clip. Real upload progress bar via NSURLSession delegate. Web: captures canvas + WebAudio as WebM via MediaRecorder. Videos attached to leaderboard entries for instant playback.

Asset Discovery

Press D from the menu to browse Blasphemer (1459 sprites across 24 groups), Freedoom Attic (1326 sprites with recursive folder browsing), and the Freedoom MIDI catalog (113 tracks). Arrow keys navigate, +/- zoom, Enter plays sounds.

Deterministic RNG

All 196 rand() callsites replaced with seeded xorshift32 (ChernobylRand()). Seed captured at run start so replay playback is frame-perfect. Enables anti-cheat verification of submitted replays.

Leaderboard Integration

On death, submit your 3-character initials to the public leaderboard. Shows your placement rank (“PLACED #N”) and a direct link to the scores page. Cheated runs are blocked from submission. Replay attached automatically for a Watch button on the scoreboard.

No Engine

No Unity, no Unreal, no Godot. Just C, raylib for windowing/GL, and raw OpenGL shaders. Build with a single gcc invocation.

Modular C • game.c + hud.c + effects.c + score_post.m + v2/level.c + v2/postfx.c • compiles in seconds

Sound Design

Four-Track Shuffled Playlist

Hell March, Funeral March, Soviet March, and GB Stranger rotate each game, shuffled with no immediate repeats. Volume adjustable with -/+ keys, M to skip track.

Per-Enemy Death Sounds

6 chef death variants, dedicated mutant scream, SS guard growl, and per-type attack cues (chef windup zing). Boss-phase swell on spawn, cut on kill so it doesn’t bleed into the death flourish.

Player & UI Cues

Footstep loop that crossfades with movement speed. Pause cue. Powerup-grab fanfares (distinct for Quad and Speed). Quad-ended stinger. Wave-advance cue on each new wave.

Announcer Stingers

UT/MK-style voice lines: First Blood, Headshot, Multi-Kill, Monster Kill, Killing Spree, Fatality. Triggered by kill streaks and special shots.

Audio Browser

Press F9 (or M from menu) to open a 3-panel sound browser. Categories by gameplay role, now-playing panel with progress bar, play/pause/loop controls, and mouse-wheel scrolling. Game music pauses while browsing.

Distance-Scaled FX

Explosions, gunfire, and enemy death sounds all attenuate by player distance — far-away kills sound distant, not point-blank. Mirrors the Explode() falloff curve. Spatial audio gives positional feedback on enemy locations.

View on GitHub

Source code • Build instructions • Asset pipeline