Cellular Automaton

Implementation of Conway’s game of life written in C++ using SDL2 and Imgui. Source code is available on Github

/cellular-automaton/featured.gif

Project Info
  • Language: C++
  • Libraries: SDL2 and Imgui
Game of Life is a two-dimensional grid of cells, each of which is in one of two possible states, live or dead(or populated and unpopulated respectively). Every cell interacts with its eight neighbours, which are the cell that are horizontally, vertically, or diagonally adjacent.

At each step in time , the following transitions occur:

  1. Any live cell with fewer than two live neighbours dies, as if by underpopulation.
  2. Any live cell with two or three live neighbours lives on to the next generation.
  3. Any live cell with more than three live neighbours dies, as if by overpopulation.
  4. Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.

I used SDL2 for 2D rendering and input, And Imgui for user interface.

The cells are stored in a 2D Array in the Game class in Game.h. The Game class also has all the core logic of the game.

The cells have been rendered using the SDL_RenderFillRect() function which takes a SDL_Rect as a parameter. And the grid lines with SDL_RenderDrawRect().

The cell can be either LIVE or DEAD. All cells in the array are in the default DEAD state when the simulation starts. When the simulation runs, it iterates over every cell and checks its neighbours to determine whether it would live or die based on the above rules. The Life() function in the Game class first stores all the cells in the m_backupCells 2D array, then it iterates over every cell and calculate the number of neighbours from the m_backupCells array. Based on the number of neighbours it determine whether the cell would live or die in the next generation and update that information into the m_cells 2D array.

Both the 2D arrays are just boolean arrays storing LIVE or DEAD states as 1 or 0 respectively. And total number of neighbours is the sum of all eight neighbour’s boolean state.

	void Game::Life()
	{
		m_generation++;
		for (int y = 0; y < NUM_CELLS; y++)
		{
			for (int x = 0; x < NUM_CELLS; x++)
			{
				m_backupCells[y][x] = m_cells[y][x];
			}
		}

		int neighbours = 0;
		for (int y = 0; y < NUM_CELLS; y++)
		{
			for (int x = 0; x < NUM_CELLS; x++)
			{
				neighbours = m_backupCells[y - 1][x - 1] + m_backupCells[y - 1][x] + m_backupCells[y - 1][x + 1] +
					m_backupCells[y][x - 1] + m_backupCells[y][x + 1] +
					m_backupCells[y + 1][x - 1] + m_backupCells[y + 1][x] + m_backupCells[y + 1][x + 1];

				if (neighbours < 2)
					m_cells[y][x] = 0;
				else if (neighbours > 3)
					m_cells[y][x] = 0;
				else if (neighbours == 3)
					m_cells[y][x] = 1;
			}
		}
	}

The m_generation variable just keep track of the number of generations.

For UI it was easy to setup imgui as it already comes with a SDL Renderer backend(imgui_impl_sdlrenderer.h).

There are some interesting effects shown in the Wikipediea page. One of which is called Gosper’s glider gun shown in the above gif.

In this project I learned a lot about imgui library like how to properly set it up and use with SDL2 renderer. While creating the build system with cmake I learned how to statically link a library like imgui with the project. Learned about various SDL render draw functions.