First Commit
This commit is contained in:
parent
339c470e3e
commit
a2960ee689
|
@ -30,3 +30,6 @@
|
||||||
*.exe
|
*.exe
|
||||||
*.out
|
*.out
|
||||||
*.app
|
*.app
|
||||||
|
|
||||||
|
include/SDL2/
|
||||||
|
.vscode
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "include/ConfigurationParser"]
|
||||||
|
path = include/ConfigurationParser
|
||||||
|
url = https://github.com/Syntriax/ConfigurationParser
|
|
@ -1,2 +1,3 @@
|
||||||
# SDL2_GameOfLife
|
# SDL2_GameOfLife
|
||||||
|
|
||||||
|
Simple Conway's Game of Life written with SDL2 in C++
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit a92b2fe91a0989619c5284c7e9c5962a8047ec16
|
|
@ -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)
|
|
@ -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() {}
|
|
@ -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();
|
||||||
|
};
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue