Skip to content

VirtualVFix/gol

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Conway's Game of Life (Vulkan Test)

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.

Platform C++ Vulkan License

Table of Contents


Quick Start

Get Conway's Game of Life running in minutes!

macOS Quick Start

# 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

Windows Quick Start

# 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.exe

First Steps

When 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:

  1. Press R to randomize the grid (30% fill)
  2. Press SPACE to start the simulation
  3. Press F to zoom to fit the entire grid
  4. Click on any cell to inspect its properties
  5. Use the Control Panel to adjust grid size, speed, and lifetime

See Controls for complete keyboard shortcuts and mouse controls.


Features

Core Simulation

  • 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

Graphics & Rendering

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

Camera System

  • 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

User Interface (Dear ImGui)

  • 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

Technical Highlights

C++17 Features Used

  • std::optional - Safe nullable entity access and selection
  • std::unique_ptr - RAII memory management
  • [[nodiscard]] - Enforced return value checks
  • enum class - Type-safe entity states
  • constexpr - Compile-time configuration constants
  • if constexpr - Compile-time branching
  • Default member initializers
  • Structured bindings - Elegant tuple unpacking

Architecture

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

Vulkan Implementation Details

  • 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

Requirements

System Requirements

  • 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

Development Dependencies

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

Installation

macOS Installation

1. Install Homebrew (if not already installed)

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

2. Install Required Dependencies

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

3. Set Up Vulkan Environment Variables

Add 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.d

Then reload your shell:

source ~/.zshrc  # or source ~/.bash_profile

4. Verify Installation

# Check Vulkan
vulkaninfo --summary

# Check other dependencies
sdl2-config --version
cmake --version

Windows Installation

1. Install Vulkan SDK

  • Download from LunarG Vulkan SDK
  • Run installer (includes glslangValidator)
  • Ensure environment variables are set automatically

2. Install CMake

  • Download from cmake.org
  • Add to PATH during installation

3. Install Visual Studio

  • Visual Studio 2017 or newer with C++ Desktop Development
  • Or Build Tools for Visual Studio

4. Install SDL2

  • Download development libraries from libsdl.org
  • Extract to C:\SDL2 or use vcpkg: vcpkg install sdl2

5. Install GLM

  • Download from GitHub
  • Extract to C:\glm or use vcpkg: vcpkg install glm

Building the Project

Clone Repository

Clone with submodules to automatically get Dear ImGui:

git clone --recursive https://github.com/VirtualVFix/gol.git
cd live

If you forgot --recursive, initialize submodules manually:

git submodule update --init --recursive

This will automatically download Dear ImGui into external/imgui/.

macOS Build

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

Windows Build

# Create build directory
mkdir build
cd build

# Configure with CMake
cmake ..

# Build
cmake --build . --config Release

The executable will be at build\Release\GameOfLife.exe.

Alternative: Open the generated .sln file in Visual Studio for IDE-based development.


Running the Application

macOS

After building, run from the build directory:

cd build
./GameOfLife

Note: 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
./GameOfLife

Add the export to your ~/.zshrc to make it permanent.

Windows

cd build\Release
.\GameOfLife.exe

Controls

Keyboard Shortcuts

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

Mouse Controls

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

GUI Controls

Control Panel

  • 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

Inspector Panel

  • Shows selected cell properties
  • Displays position, state, age, and lifetime
  • Updates in real-time

Statistics Panel

  • Generation: Current simulation generation
  • Alive Cells: Count of living cells
  • FPS: Current frame rate

Tooltips

Hover over any control for detailed information about:

  • What the control does
  • Valid ranges
  • Keyboard shortcuts
  • Mouse wheel functionality

Configuration

All parameters are centralized in src/Config.h for easy customization.

Default Configuration

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

Customizing Configuration

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

All configuration options are documented in src/Config.h with clear comments.


Project Structure

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

Troubleshooting

macOS: Failed to create window / VK_ERROR_INCOMPATIBLE_DRIVER

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

Add to ~/.zshrc for permanent fix:

echo 'export VK_ICD_FILENAMES=/opt/homebrew/opt/molten-vk/etc/vulkan/icd.d/MoltenVK_icd.json' >> ~/.zshrc
source ~/.zshrc

macOS: Config.h not found

Problem: Build can't find Config.h.

Solution: Config.h should be in src/ directory. Rebuild:

cd build
rm -rf *
cmake ..
make

Shader Compilation Errors

Problem: Shaders fail to compile.

Solution: Ensure glslangValidator is in PATH:

# macOS
which glslangValidator
# Should output: /usr/local/bin/glslangValidator

# If not found:
brew install glslang

Missing Dear ImGui

Problem: Build fails with ImGui errors.

Solution: The project uses Git submodules for Dear ImGui. Initialize them:

git submodule update --init --recursive

Note: Always clone with --recursive flag to avoid this issue:

git clone --recursive <repository-url>

SDL2 Not Found (macOS)

Problem: CMake can't find SDL2.

Solution:

brew install sdl2
# If already installed, try:
brew reinstall sdl2

Zoom Jumping Issues

Problem: 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
}

Mouse Wheel Too Sensitive/Slow

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;
}

Performance Notes

Optimizations

  • 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

Performance Benchmarks

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

Performance Tips

  1. Reduce grid size for slower hardware
  2. Lower simulation speed doesn't affect FPS (rendering is decoupled)
  3. Close inspector/stats panels for minimal performance gain
  4. Use zoom-to-fit to ensure optimal viewport

Development Notes

Code Quality

  • Modern C++17 standards
  • Const-correctness throughout
  • RAII for resource management
  • No raw pointers (uses smart pointers)
  • Comprehensive error handling

Extension Ideas

  • Custom rules (not just B3/S23)
  • Save/load patterns
  • Pattern library
  • Color themes
  • Hexagonal grids
  • 3D visualization

License

This project is provided as-is for educational purposes.


Acknowledgments


About

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

About

Game of Life (Vulcan Test)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published