A reusable engine template for building Wolfenstein-esque first-person games, built on Pygame + ModernGL.
Forked from StanislavPetrovV's Wolfenstein 3D clone (MIT license). The original project is a complete, playable Wolfenstein 3D tribute. We're extracting its proven rendering and game loop architecture into a composable engine so we can rapidly build different games on the same foundation.
The codebase is split into two packages with a clear boundary:
wolf_engine/ Engine (reusable across games)
config.py Engine constants (resolution, FOV, GL, input, timers)
camera.py First-person camera math
entity.py Base Entity (pos, rot, scale, model matrix, lifecycle)
world.py Entity registry with spatial indexing
collision.py AABB collision with pluggable blockers
raycasting.py DDA raycaster with callback-based blocking/targets
pathfinding.py BFS grid pathfinder with dynamic blockers
rendering/ OpenGL pipeline (shaders, meshes, textures)
game/ Game code (swap this to make a different game)
engine.py Game orchestrator and level lifecycle
player.py Player combat, inventory, interaction
scene.py Render order manager
level_map.py TMX level loader and entity spawning
ray_casting.py Game-specific raycasting rules
path_finding.py Game-specific pathfinding rules
sound.py Audio catalogue
data.py Weapon, NPC, item, HUD definitions
texture_id.py Texture ID registry
entities/ NPC, Door, Item, Weapon, HUD
main.py Entry point
settings.py Re-export shim (backward compat)
assets/ Textures, sounds, music
resources/ Tiled .tmx level files
See ARCHITECTURE.md for the full breakdown of the engine/game boundary, design patterns, and how to build a new game on the engine.
See ENGINE_EXTRACTION_SCRUTINY.md for the original analysis and extraction plan.
- Phase 1: Critical bug fixes -- Done
- Phase 2: Settings split -- Done
- Phase 3: Engine core extraction -- Done
- Phase 3.5: Repo reorganization -- Done
- Phase 4: Rendering pipeline -- Done
RenderScenewith named layers replacing hardcoded render orderShaderManagerwith data-driven loading and#includeresolution- Shared shader snippets (
fog.glsl,gamma.glsl) eliminating duplication TextureArrayBuilderwith mtime-based caching (skips rebuild when unchanged)
- Phase 5: Infrastructure -- Done
Appwith game state stack (push/pop/replace states for menu → playing → paused)AudioManagerwith manifest-driven loading, round-robin channels, positional audioInputManagerwith action-based key bindings (decouples game logic from key codes)TMXLoaderreturning rawLevelDatawithout entity spawning
- Phase 6: Reference game rebuild -- Done
main.pyrebuilt onApp+GameState(replaces hand-rolled game loop)game/level_map.pyusesTMXLoaderfor raw parsing, keeps game entity spawninggame/sound.pyinherits fromAudioManager(replaces manual mixer code)game/player.pyusesInputManagerfor action-based input (decoupled from key codes)
| Dependency | Role |
|---|---|
| Pygame | Window, input, audio, image loading |
| ModernGL | OpenGL 3.3 abstraction |
| PyGLM | Vector/matrix math |
| NumPy | Vertex data arrays |
| PyTMX | Tiled map format parsing |
pip install -r requirements.txt
python main.py| Key | Action |
|---|---|
| Enter / Space | Select menu item |
| Arrow keys / W/S | Navigate menu |
| WASD | Move (in game) |
| Mouse | Look |
| Left click | Shoot |
| 1 / 2 / 3 | Switch weapon (knife / pistol / rifle) |
| Mouse wheel | Cycle weapons |
| F | Interact (open doors) |
| Q / E | Move up / down |
| Tab | Toggle mouse capture |
| Esc | Pause menu / Back |
Levels are Tiled maps (.tmx). See resources/levels/ for examples. Layers:
walls,floors,ceilings-- tile layers with texture IDsplayer-- object layer, single spawn pointdoors,items,npc-- object layers with positioned entities
- Original game by StanislavPetrovV (YouTube tutorial)
- Engine extraction and architecture work by @seanellul
MIT -- see LICENSE.
