Below is the C++ SDL2 implementation for Conway's Game of Life. It has been compiled to WebAssembly using Emscripten and integrated into this website.
How the Code Works
C++ SDL2 Implementation
The core simulation is handled by a C++ program using SDL2 for rendering. Here's a high-level breakdown of its functionality:
1. Initialization:
Sets up the SDL window and renderer with specified dimensions.
Initializes SDL_ttf for text rendering.
Defines essential constants like window size, cell size, and grid dimensions.
Loads fonts and creates UI elements such as buttons and dropdowns for user interaction.
2. Patterns Definition:
Predefines various starting patterns (e.g., Blinker, Toad, Glider) using coordinate points.
Each pattern is associated with a name for easy selection via the dropdown menu.
3. Main Loop (`main_loop`):
Event Handling: Captures user interactions like button clicks, dropdown selections, and grid cell toggles.
Simulation Update: Advances the Game of Life simulation based on the current state of the grid and user-defined speed settings.
Rendering: Draws the current state of the grid, UI buttons, dropdowns, and timer onto the screen.
4. User Controls:
Run/Pause Button: Toggles the simulation's running state.
Reset Button: Clears the grid and resets the simulation time.
Speed Controls: Allows users to adjust the simulation speed (e.g., x1, x2, x5, x10, x100).
Pattern Dropdown: Enables selection of predefined patterns to initialize the grid.
5. Cleanup: Ensures all SDL resources are properly released upon exiting the application.
Starting Patterns
Here's a breakdown of each pattern:
Blinker: A simple oscillator that alternates between horizontal and vertical states. Repeats every two generations, flipping its orientation.
Toad: Another oscillator with a period of two. Consists of two rows of three cells each, offset to create oscillation.
Beacon: A small, two-cell oscillator. Creates a pattern that alternates between two stable blocks connected by a gap.
Small Pulsar: A larger oscillator with a period of three. Generates a pulsating pattern that expands and contracts symmetrically.
Pentadecathlon: One of the longest-lived oscillators. Exhibits a highly stable oscillating pattern over many generations.
Glider: A spaceship that moves diagonally across the grid. Translates its shape downward and to the right with each generation.
R-pentomino: A small, asymmetrical pattern that leads to complex behavior. Evolves into a variety of structures before stabilizing, showcasing rich dynamics.
Lightweight Spaceship (LWSS): A lightweight spaceship that moves horizontally across the grid.
T-tetromino: A small, stable pattern. Remains static over generations, acting as a simple building block.
Diehard: A pattern that eventually disappears after a certain number of generations. Demonstrates transient behavior before all cells die out.
Random: Initializes the grid with a random distribution of live cells.
Rules of Conway's Game of Life
The Game of Life operates on a two-dimensional grid of cells, each of which can be either alive or dead. The simulation evolves through discrete time steps (generations) based on the following rules:
Underpopulation: Any live cell with fewer than two live neighbors dies. Represents the concept of insufficient support leading to extinction.
Survival: Any live cell with two or three live neighbors lives on to the next generation. Denotes stability within a balanced environment.
Overpopulation: Any live cell with more than three live neighbors dies. Illustrates the consequences of overcrowding.
Reproduction: Any dead cell with exactly three live neighbors becomes a live cell. Symbolizes new life arising from optimal conditions.
Neighbor Definition: Each cell has eight neighbors: horizontally, vertically, and diagonally adjacent cells. The grid can be treated with toroidal boundaries, meaning the edges are connected to form a continuous surface without borders.