Skip to content

khasinski/quake

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

quake-rb

A port of the Quake (1996) engine to Ruby. Reads original .pak/.bsp/.mdl assets and renders them via OpenGL + SDL2.

quake-rb running e1m1

Why

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.

Quick start

gem install quake-rb
quake

Or fetch the repository and run.

bundle install
bundle exec bin/quake

On 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)

Controls

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

What works

  • 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

What doesn't (yet)

  • Multiplayer / netcode
  • QuakeC server program — game logic is faked at engine level
  • Episode/level transitions (trigger_changelevel is a no-op)
  • Mirrors, particle warp, dynamic lights
  • Sky cube / skybox replacement
  • Demo playback

Maps

The shareware PAK ships:

start, e1m1, e1m2, e1m3, e1m4, e1m5, e1m6, e1m7, e1m8

Pass -map maps/e1m3.bsp to load a different one.

Architecture

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).

Development

# 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 --yjit

Status

This 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/.

License

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.

About

Quake engine port in Ruby

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages