First Commit

This commit is contained in:
Syntriax 2021-11-24 10:49:55 +03:00
parent 339c470e3e
commit a2960ee689
9 changed files with 226 additions and 0 deletions

3
.gitignore vendored
View File

@ -30,3 +30,6 @@
*.exe
*.out
*.app
include/SDL2/
.vscode

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "include/ConfigurationParser"]
path = include/ConfigurationParser
url = https://github.com/Syntriax/ConfigurationParser

View File

@ -1,2 +1,3 @@
# SDL2_GameOfLife
Simple Conway's Game of Life written with SDL2 in C++

@ -0,0 +1 @@
Subproject commit a92b2fe91a0989619c5284c7e9c5962a8047ec16

8
makefile Normal file
View File

@ -0,0 +1,8 @@
includeF = -Iinclude
libraryF = -Llib -lSDL2
bin/main.exe: src/main.cpp obj/GameOfLife.o
g++ -std=c++17 -o bin/main.exe src/main.cpp obj/GameOfLife.o $(includeF) $(libraryF)
obj/GameOfLife.o: src/GameOfLife.cpp
g++ -std=c++17 -c -o obj/GameOfLife.o src/GameOfLife.cpp $(includeF) $(libraryF)

79
src/GameOfLife.cpp Normal file
View File

@ -0,0 +1,79 @@
#include "GameOfLife.h"
int *GameOfLife::GetCell(int x, int y, int *buffer) { return buffer + y * width + x; }
int GameOfLife::GetNeighborCount(int x, int y, int *buffer)
{
int i, j;
int result = 0;
for (i = -1; i < 2; i++)
for (j = -1; j < 2; j++)
result += *GetCell(x + i, y + j, buffer) & 1;
return result - (*GetCell(x, y, buffer) & 1);
}
int GameOfLife::CalculateState(int state, int neighborCount)
{
if (state == 0)
return neighborCount == 3;
return neighborCount == 2 || neighborCount == 3;
}
void GameOfLife::Iterate()
{
int x, y;
int count = 0;
int *backCell;
for (y = 1; y < height - 1; y++)
for (x = 1; x < width - 1; x++)
{
count = GetNeighborCount(x, y, front);
backCell = GetCell(x, y, back.get());
if (CalculateState(*GetCell(x, y, front), count))
*backCell = livePixelColor;
else
*backCell = 0;
}
std::memcpy(front, back.get(), width * height * sizeof(int));
}
void GameOfLife::SetDisplay(int *pixelPointer, SDL_PixelFormat *pixelFormat)
{
front = pixelPointer;
livePixelColor = SDL_MapRGBA(pixelFormat, 255, 255, 255, 255);
}
bool GameOfLife::SetDimensions(int width, int height)
{
this->width = width;
this->height = height;
back = std::make_unique<int[]>(width * height);
return back.get() != nullptr;
}
bool GameOfLife::Randomize(int seed)
{
if (front == nullptr)
return false;
int count = width * height;
std::srand(seed);
for (int i = 0; i < count; i++)
if (rand() % 2 == 0)
*(front + i) = livePixelColor;
else
*(front + i) = 0;
return true;
}
GameOfLife::GameOfLife() { SetDimensions(100, 100); }
GameOfLife::GameOfLife(int width, int height) { SetDimensions(width, height); }
GameOfLife::~GameOfLife() {}

26
src/GameOfLife.h Normal file
View File

@ -0,0 +1,26 @@
#pragma once
#include "headers.h"
class GameOfLife
{
private:
int width;
int height;
int livePixelColor;
int *front;
std::unique_ptr<int[]> back;
int *GetCell(int, int, int *);
int GetNeighborCount(int, int, int *);
int CalculateState(int, int);
public:
const int *GetGridPointer();
void Iterate();
void SetDisplay(int *, SDL_PixelFormat *);
bool SetDimensions(int, int);
bool Randomize(int);
GameOfLife();
GameOfLife(int, int);
~GameOfLife();
};

20
src/headers.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
// #ifndef GameOfLifeHeaders
// #define GameOfLifeHeaders
#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#include <iostream>
#include <memory>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include "GameOfLife.h"
#include "ConfigurationParser/ConfigurationParser.h"
// #endif

85
src/main.cpp Normal file
View File

@ -0,0 +1,85 @@
#include "headers.h"
#define CONFIG_PATH "config.cfg"
#define WIDTH_CONF_KEY "WIDTH"
#define HEIGHT_CONF_KEY "HEIGHT"
#define FPS_CONF_KEY "FPS"
#define SEED_CONF_KEY "SEED"
void ReadConfig(Syn::ConfigurationParser &parser)
{
if (parser.ParseFile(CONFIG_PATH))
return;
parser[WIDTH_CONF_KEY] = "400";
parser[HEIGHT_CONF_KEY] = "400";
parser[FPS_CONF_KEY] = "60";
parser[SEED_CONF_KEY] = "0";
parser.WriteFile(CONFIG_PATH);
}
void Update(SDL_Surface *surface, GameOfLife *life)
{
SDL_LockSurface(surface);
life->Iterate();
SDL_UnlockSurface(surface);
}
int main(int argc, char *argv[])
{
SDL_Event event;
SDL_Renderer *renderer;
SDL_Window *window;
SDL_Surface *surface;
GameOfLife life;
Syn::ConfigurationParser config;
ReadConfig(config);
int width = std::stoi(config[WIDTH_CONF_KEY]);
int height = std::stoi(config[HEIGHT_CONF_KEY]);
int fps = std::stoi(config[FPS_CONF_KEY]);
int seed = std::stoi(config[SEED_CONF_KEY]);
bool isRunning = true;
int tickForNext = 1000 / fps;
int nextTick = 0;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow(
"Game of Life",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
width, height,
SDL_WindowFlags::SDL_WINDOW_OPENGL);
renderer = SDL_CreateRenderer(window, -1, SDL_RendererFlags::SDL_RENDERER_ACCELERATED);
surface = SDL_GetWindowSurface(window);
life.SetDimensions(width, height);
life.SetDisplay((int *)surface->pixels, surface->format);
life.Randomize(seed);
while (isRunning)
{
while (SDL_PollEvent(&event) != 0)
{
switch (event.type)
{
case SDL_QUIT:
isRunning = false;
break;
}
}
if (SDL_GetTicks() >= nextTick)
{
Update(surface, &life);
SDL_UpdateWindowSurface(window);
nextTick += tickForNext;
}
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}