A port of the Quake (1996) engine to Ruby. Reads original .pak/.bsp/.mdl assets and renders them via OpenGL + SDL2.
Mostly as a counterpart to doom - to see how far you can take id Software's classic engines in plain Ruby, and to learn the BSP/PVS/lightmap pipeline.
gem install quake-rb
quakeOr fetch the repository and run.
bundle install
bundle exec bin/quakeOn first run, with no data/id1/pak0.pak present, you'll be asked to download the freely-redistributable shareware Quake (Episode 1, ~17 MB). It's pulled from archive.org/quakeshareware/QUAKE_SW.zip and extracted into ./data/id1/pak0.pak. You can also drop your own registered pak0.pak (and pak1.pak) in there manually.
System requirements:
- Ruby 3.1+
- SDL2 (
brew install sdl2/apt install libsdl2-dev) - OpenGL 2.1
unzip(used by the shareware fetcher)
| Key | Action |
|---|---|
| WASD | Move |
| Mouse | Look |
| Space | Jump |
| C | Crouch |
| 1–8 / scroll | Weapon select |
| N | Toggle noclip |
| L | Dump player pose + save a screenshot to debug/shots/ (debug aid) |
| Esc | Quit |
- BSP loading + face extraction with texture coordinates
- Texture mapping with the original 256-colour palette
- Static lightmaps from the lighting lump
- PVS culling, including:
- leaf 0 fallback (treat solid leaf as all-visible, à la TyrQuake)
- FatPVS expansion when the camera leaf touches a liquid surface
- vis-through-water: liquid faces in PVS bring the leaves on the other side of their plane into view, so translucent water shows the cave bed instead of clear-color void
- Sky rendering: two-layer scrolling cloud + back layer, PVS-culled
- Water/slime/lava: turbsin-warped texture, alpha-blended translucency, backface culling for the duplicate front/back face pairs Quake's BSP compiler emits
- Brush entities (doors, plats, buttons, triggers) with their own transforms
- MDL alias models with frame interpolation
- Particle effects + viewmodel + HUD
- Player physics: walk, crouch, jump, friction, water levels, platform riding
- Item pickups, weapon switching, shareware audio mixer
- Multiplayer / netcode
- QuakeC server program — game logic is faked at engine level
- Episode/level transitions (
trigger_changelevelis a no-op) - Mirrors, particle warp, dynamic lights
- Sky cube / skybox replacement
- Demo playback
The shareware PAK ships:
start, e1m1, e1m2, e1m3, e1m4, e1m5, e1m6, e1m7, e1m8
Pass -map maps/e1m3.bsp to load a different one.
lib/quake/
bsp/ reader, types, face vertices, PVS / FatPVS / vis-through-water
pak/ pak0.pak reader
mdl/ alias model reader
wad/ gfx.wad (HUD/menu graphics) reader
palette.rb 256-colour palette → RGBA
math/vec3.rb plain Ruby vector
physics/ hull trace + Player (walk/swim/jump/noclip)
game/
engine.rb orchestrates renderers + physics + entity simulation
brush_entities entity-driven door/plat/button state machines
item_pickups touchable items
player_state weapons, ammo, health, armor
renderer/
gl_textured opaque world brushes (with lightmap pass)
gl_brush_model sub-model brushes (doors etc.) at entity transforms
gl_alias_model .mdl monsters + items
gl_water *water0/*slime0/*lava0/*teleport with turbsin warp
gl_sky two-layer scrolling sky
gl_lightmap lightmap atlas builder
gl_texture_manager mipmapped diffuse texture cache
gl_particles explosion/spark sprites
gl_viewmodel first-person weapon
gl_hud statusbar + numbers
sound/ SDL_mixer-backed sound effects
pak_downloader.rb shareware fetcher
version.rb VERSION = "0.1.0"
bin/
quake interactive game
quake-debug headless DSL runner (`teleport`, `screenshot`, `dump` etc.)
test/ minitest suite
debug/scripts/ ad-hoc investigation scripts (gitignored)
The headless runner is genuinely useful for working on the engine without a window — see debug/scripts/* for examples (water visibility traces, leaf inspection, BSP dumps).
# Run the tests
bundle exec ruby -Itest -Ilib -e 'Dir["test/**/*_test.rb"].each { |f| require File.expand_path(f) }'
# Run a headless debug script (renders to a hidden window)
bundle exec bin/quake-debug debug/scripts/water_real.rb
# Run the game with YJIT
bundle exec bin/quake --yjitThis is a hobby project. It can comfortably walk you through e1m1 and shoot the rotating shotgun, but the QuakeC server program is not implemented, so monsters don't fight back and triggers don't change levels. The renderer is the most complete part — everything in the "What works" list above is in lib/quake/renderer/.
GPL-2.0-only, matching the original Quake source release.
The shareware Quake data is © 1996 id Software, freely redistributable. The registered Quake data (if you supply your own pak0.pak + pak1.pak) is not redistributable; you must own a copy.
