Created for learning purposes of comparation OOP and ECS based game development approaches. OOP based C++17 implementation of Conway's Game of Life using the Vulkan API for rendering with modern graphics techniques and an intuitive user interface.
- Quick Start
- Features
- Technical Highlights
- Requirements
- Installation
- Building the Project
- Running the Application
- Controls
- Configuration
- Project Structure
- Troubleshooting
- Performance Notes
- Development Notes
- License
- Acknowledgments
- About
Get Conway's Game of Life running in minutes!
# 1. Install dependencies
brew install cmake vulkan-headers vulkan-loader molten-vk glslang sdl2 glm
# 2. Set up Vulkan environment (add to ~/.zshrc for persistence)
export VULKAN_SDK=/opt/homebrew/opt/molten-vk
export VK_ICD_FILENAMES=/opt/homebrew/opt/molten-vk/etc/vulkan/icd.d/MoltenVK_icd.json
export VK_LAYER_PATH=/opt/homebrew/opt/molten-vk/share/vulkan/explicit_layer.d
# 3. Clone and build
git clone --recursive <repository-url>
cd live
mkdir -p build && cd build
cmake ..
make -j$(sysctl -n hw.ncpu)
# 4. Run
./GameOfLife# 1. Install prerequisites:
# - Visual Studio 2017+ with C++ Desktop Development
# - CMake from https://cmake.org/download/
# - Vulkan SDK from https://vulkan.lunarg.com/
# - SDL2 and GLM via vcpkg or manual download
# 2. Clone and build
git clone --recursive <repository-url>
cd live
mkdir build
cd build
cmake ..
cmake --build . --config Release
# 3. Run
cd Release
.\GameOfLife.exeWhen you launch the application, you'll see:
- A 256×256 grid with all cells initially dead (dark gray)
- Three GUI panels: Controls, Inspector (hidden), and Statistics
- The simulation paused by default
Try these actions:
- Press
Rto randomize the grid (30% fill) - Press
SPACEto start the simulation - Press
Fto zoom to fit the entire grid - Click on any cell to inspect its properties
- Use the Control Panel to adjust grid size, speed, and lifetime
See Controls for complete keyboard shortcuts and mouse controls.
- Conway's Game of Life Rules (B3/S23): Standard birth and survival conditions
- Extended Lifetime System: Entities have a configurable maximum lifetime (1-512 generations)
- Double Buffered Grid: Ensures correct simultaneous evaluation of all cells
- Persistent Dead Entities: Dead cells retain their data for inspection
- Configurable Grid Size: Support for grids from 10×10 up to 512×512 cells
- Vulkan 1.2 API: Low-level, high-performance graphics
- Instanced Rendering: Efficient GPU-based rendering of thousands of cells
- Hardware Acceleration: Leverages modern GPU capabilities
- Seamless Cell Display: Cells rendered without grid lines for clean visualization
- Dynamic Cell Colors: Visual aging system (green for young, red for old cells)
- Cross-Platform: Windows (native Vulkan) and macOS (MoltenVK)
- Orthographic Projection: 2D view with proper Vulkan Y-flip handling
- Zoom-to-Fit: Automatically frame the entire grid (Hotkey: F)
- Smooth Pan & Zoom: Manual camera control via mouse with no jumps
- Ray Casting: Accurate screen-to-world coordinate conversion
- Zoom Range: 0.1× to 100× magnification
- Control Panel: Play/Pause, Step, Speed control, Grid configuration
- Entity Inspector: Click cells to view their state, age, and lifetime
- Statistics Overlay: Real-time generation count, alive cells, FPS
- Keyboard Shortcuts: Quick access to common functions
- Mouse Wheel Support: Adjust parameters by hovering and scrolling
- Contextual Tooltips: Helpful descriptions for all controls
std::optional- Safe nullable entity access and selectionstd::unique_ptr- RAII memory management[[nodiscard]]- Enforced return value checksenum class- Type-safe entity statesconstexpr- Compile-time configuration constantsif constexpr- Compile-time branching- Default member initializers
- Structured bindings - Elegant tuple unpacking
The project follows modern C++ best practices with a clear separation of concerns:
Config → Centralized configuration (limits, defaults, multipliers)
Entity & Grid → Simulation logic and data storage
Simulation → Game of Life rules with double buffering
Camera → Orthographic projection and transformations
VulkanContext → Instance, device, and surface management
Renderer → Swapchain, pipeline, and command buffers
Gui → Dear ImGui integration
Application → Main loop, event handling, and orchestration
- Frames in Flight: Double buffering with semaphores and fences
- Dynamic Buffers: Instance buffer resizes as needed
- Descriptor Sets: Per-frame uniform buffers
- MoltenVK Support: Proper portability extensions for macOS
- Swapchain Recreation: Handles window resize gracefully
- Efficient Rendering: Instanced rendering for thousands of cells
- Operating System:
- macOS 10.15+ with Metal-capable GPU
- Windows 10+ with Vulkan-capable GPU
- Linux (untested but should work)
- Graphics: Vulkan 1.2+ compatible GPU
- Memory: 4GB RAM minimum
- Disk Space: ~100MB for dependencies and build files
| Dependency | Version | Purpose | Installation |
|---|---|---|---|
| Vulkan SDK | 1.2+ | Graphics API | brew/Manual download |
| SDL2 | 2.0+ | Window and input | brew/vcpkg |
| GLM | Latest | Math library | brew/vcpkg |
| Dear ImGui | Latest | User interface | Git submodule (automatic) |
| CMake | 3.15+ | Build system | brew/Manual download |
| C++ Compiler | C++17 | Compilation | MSVC 2017+, Clang 5+, GCC 7+ |
| Git | Any | Version control | For cloning with submodules |
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"# Install all dependencies via Homebrew
brew install cmake
brew install vulkan-headers
brew install vulkan-loader
brew install molten-vk
brew install glslang
brew install sdl2
brew install glmAdd these to your ~/.zshrc or ~/.bash_profile:
# Vulkan SDK paths
export VULKAN_SDK=/opt/homebrew/opt/molten-vk
export VK_ICD_FILENAMES=/opt/homebrew/opt/molten-vk/etc/vulkan/icd.d/MoltenVK_icd.json
export VK_LAYER_PATH=/opt/homebrew/opt/molten-vk/share/vulkan/explicit_layer.dThen reload your shell:
source ~/.zshrc # or source ~/.bash_profile# Check Vulkan
vulkaninfo --summary
# Check other dependencies
sdl2-config --version
cmake --version- Download from LunarG Vulkan SDK
- Run installer (includes glslangValidator)
- Ensure environment variables are set automatically
- Download from cmake.org
- Add to PATH during installation
- Visual Studio 2017 or newer with C++ Desktop Development
- Or Build Tools for Visual Studio
- Download development libraries from libsdl.org
- Extract to
C:\SDL2or use vcpkg:vcpkg install sdl2
- Download from GitHub
- Extract to
C:\glmor use vcpkg:vcpkg install glm
Clone with submodules to automatically get Dear ImGui:
git clone --recursive https://github.com/VirtualVFix/gol.git
cd liveIf you forgot --recursive, initialize submodules manually:
git submodule update --init --recursiveThis will automatically download Dear ImGui into external/imgui/.
# Create build directory
mkdir -p build
cd build
# Configure with CMake
cmake ..
# Build (using all CPU cores)
make -j$(sysctl -n hw.ncpu)The executable will be at build/GameOfLife.
# Create build directory
mkdir build
cd build
# Configure with CMake
cmake ..
# Build
cmake --build . --config ReleaseThe executable will be at build\Release\GameOfLife.exe.
Alternative: Open the generated .sln file in Visual Studio for IDE-based development.
After building, run from the build directory:
cd build
./GameOfLifeNote: If you encounter Vulkan driver errors, ensure the environment variable is set:
export VK_ICD_FILENAMES=/opt/homebrew/opt/molten-vk/etc/vulkan/icd.d/MoltenVK_icd.json
./GameOfLifeAdd the export to your ~/.zshrc to make it permanent.
cd build\Release
.\GameOfLife.exe| Key | Action |
|---|---|
SPACE |
Play/Pause simulation |
S |
Step one generation (when paused) |
R |
Randomize grid (30% fill) |
C |
Clear grid |
F |
Zoom camera to fit entire grid |
ESC |
Exit application |
| Action | Effect |
|---|---|
Left Click |
Select entity for inspection |
Right Click + Drag |
Pan camera |
Scroll Wheel |
Zoom in/out (when not over GUI) |
Scroll Wheel (on GUI controls) |
Adjust parameter values |
- Play/Pause Button: Start/stop automatic simulation
- Step Button: Manually advance one generation
- Speed Slider: Adjust simulation speed (0.1-100.0 gen/s)
- Hover and scroll: ±0.5 per tick
- Grid Width: Set horizontal cell count (10-512)
- Hover and scroll: ±2 per tick
- Grid Height: Set vertical cell count (10-512)
- Hover and scroll: ±2 per tick
- Max Lifetime: Set maximum cell age (1-512)
- Hover and scroll: ±5 per tick
- Apply & Reset: Create new grid with current settings
- Randomize: Fill current grid with random cells
- Zoom to Fit: Center and scale view to show entire grid
- Shows selected cell properties
- Displays position, state, age, and lifetime
- Updates in real-time
- Generation: Current simulation generation
- Alive Cells: Count of living cells
- FPS: Current frame rate
Hover over any control for detailed information about:
- What the control does
- Valid ranges
- Keyboard shortcuts
- Mouse wheel functionality
All parameters are centralized in src/Config.h for easy customization.
// Simulation defaults (Config::Simulation)
DEFAULT_GRID_WIDTH = 256
DEFAULT_GRID_HEIGHT = 256
DEFAULT_MAX_LIFETIME = 16
DEFAULT_SPEED = 10.0 gen/s
RANDOM_FILL_PERCENTAGE = 30%
// Limits (Config::Limits)
Grid Size: 10-512 cells per dimension
Lifetime: 1-512 generations
Speed: 0.1-100.0 gen/s
Zoom: 0.1×-100×
// Mouse wheel sensitivity (Config::MouseWheel)
Speed: ±0.5 gen/s per scroll
Grid Size: ±2 cells per scroll
Lifetime: ±5 generations per scroll
Zoom: 10% per scroll (delta clamped to ±3)
// Camera (Config::Camera)
DEFAULT_ZOOM = 1.0
ZOOM_TO_FIT_PADDING = 10%
// Colors (Config::Colors)
Young cells: Green (0.2, 0.8, 0.3)
Old cells: Red (1.0, 0.2, 0.3)
Dead cells: Dark gray (0.1, 0.1, 0.1)Edit src/Config.h and rebuild:
namespace Config::Simulation {
constexpr int DEFAULT_GRID_WIDTH = 512; // Your custom size
constexpr int DEFAULT_GRID_HEIGHT = 512;
constexpr int DEFAULT_MAX_LIFETIME = 256;
constexpr float DEFAULT_SPEED = 20.0f;
// ... other parameters
}
namespace Config::Colors {
// Customize cell colors
constexpr CellColor YOUNG_CELL = {0.2f, 0.8f, 0.3f, 1.0f}; // Green
constexpr CellColor OLD_CELL = {1.0f, 0.2f, 0.3f, 1.0f}; // Red
}Then rebuild:
cd build
make
./GameOfLifeAll configuration options are documented in src/Config.h with clear comments.
.
├── CMakeLists.txt # Build configuration
├── README.md # This file
├── .gitmodules # Git submodules (Dear ImGui)
├── src/
│ ├── Config.h # Centralized configuration
│ ├── main.cpp # Entry point
│ ├── Application.h/cpp # Main application loop
│ ├── VulkanContext.h/cpp # Vulkan setup and management
│ ├── Renderer.h/cpp # Rendering pipeline
│ ├── Simulation.h/cpp # Game of Life logic
│ ├── Camera.h/cpp # Camera system with zoom/pan
│ ├── Gui.h/cpp # Dear ImGui interface
│ ├── Entity.h/cpp # Cell entity
│ └── Grid.h/cpp # Grid data structure
├── shaders/
│ ├── shader.vert # Vertex shader (GLSL)
│ └── shader.frag # Fragment shader (GLSL)
├── prompts/
│ └── build.md # Build instructions and notes
├── build/ # Build output (generated by CMake)
│ ├── GameOfLife # Executable (macOS/Linux)
│ ├── GameOfLife.exe # Executable (Windows)
│ └── shaders/ # Compiled SPIR-V shaders
└── external/
└── imgui/ # Dear ImGui library (Git submodule)
Problem: MoltenVK ICD file not found.
Solution: Set the correct environment variable:
export VK_ICD_FILENAMES=/opt/homebrew/opt/molten-vk/etc/vulkan/icd.d/MoltenVK_icd.jsonAdd to ~/.zshrc for permanent fix:
echo 'export VK_ICD_FILENAMES=/opt/homebrew/opt/molten-vk/etc/vulkan/icd.d/MoltenVK_icd.json' >> ~/.zshrc
source ~/.zshrcProblem: Build can't find Config.h.
Solution: Config.h should be in src/ directory. Rebuild:
cd build
rm -rf *
cmake ..
makeProblem: Shaders fail to compile.
Solution: Ensure glslangValidator is in PATH:
# macOS
which glslangValidator
# Should output: /usr/local/bin/glslangValidator
# If not found:
brew install glslangProblem: Build fails with ImGui errors.
Solution: The project uses Git submodules for Dear ImGui. Initialize them:
git submodule update --init --recursiveNote: Always clone with --recursive flag to avoid this issue:
git clone --recursive <repository-url>Problem: CMake can't find SDL2.
Solution:
brew install sdl2
# If already installed, try:
brew reinstall sdl2Problem: Camera jumps when scrolling fast.
Solution: Already fixed! The zoom delta is now clamped to prevent jumps. If still experiencing issues, adjust in src/Config.h:
namespace Config::MouseWheel {
constexpr int ZOOM_DELTA_CLAMP_MAX = 2; // Lower = less sensitive
}Problem: Parameter adjustments too fast or slow.
Solution: Adjust multipliers in src/Config.h:
namespace Config::MouseWheel {
constexpr float SPEED_MULTIPLIER = 0.25f; // Lower = less sensitive
constexpr int GRID_SIZE_MULTIPLIER = 1;
constexpr int LIFETIME_MULTIPLIER = 2;
}- Instanced Rendering: Efficiently renders thousands of cells with a single draw call
- Dynamic Buffers: Memory allocation scales with grid size
- Double Buffering: Prevents screen tearing and ensures smooth rendering
- Cache-Friendly Data: Contiguous memory layout for grid cells
Typical performance on modern hardware:
- 256×256 Grid (65,536 cells): 120+ FPS
- 512×512 Grid (262,144 cells): 60+ FPS
- Frame Timing: Consistent frame times with proper synchronization
- Memory Usage: ~50MB for 512×512 grid
- Tested on: Apple M4, various Intel/AMD systems with Vulkan support
- Reduce grid size for slower hardware
- Lower simulation speed doesn't affect FPS (rendering is decoupled)
- Close inspector/stats panels for minimal performance gain
- Use zoom-to-fit to ensure optimal viewport
- Modern C++17 standards
- Const-correctness throughout
- RAII for resource management
- No raw pointers (uses smart pointers)
- Comprehensive error handling
- Custom rules (not just B3/S23)
- Save/load patterns
- Pattern library
- Color themes
- Hexagonal grids
- 3D visualization
This project is provided as-is for educational purposes.
- Vulkan Tutorial: https://vulkan-tutorial.com/
- Dear ImGui: https://github.com/ocornut/imgui
- SDL2: https://www.libsdl.org/
- GLM: https://github.com/g-truc/glm
- MoltenVK: https://github.com/KhronosGroup/MoltenVK
Created as a demonstration of modern C++ and Vulkan graphics programming. This project showcases:
- Clean, maintainable C++17 code
- Production-quality Vulkan implementation
- Cross-platform compatibility
- Professional software architecture
Version: 1.0
Last Updated: December 2024