Initial commit
This commit is contained in:
commit
1a564b75ca
16 changed files with 424 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
build/
|
||||||
|
life
|
28
Makefile
Normal file
28
Makefile
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Written with extensive help from https://makefiletutorial.com
|
||||||
|
|
||||||
|
CC = g++
|
||||||
|
|
||||||
|
TARGET_EXEC = life
|
||||||
|
|
||||||
|
SRC_DIR = src
|
||||||
|
INC_DIR = include
|
||||||
|
BUILD_DIR = build
|
||||||
|
|
||||||
|
CFLAGS = -I $(INC_DIR) -MMD -MP -I c:/SDL2/include -I c:/SDL2/include/SDL2 -Dmain=SDL_main
|
||||||
|
LDFLAGS = -L c:/SDL2/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -static-libstdc++ -static-libgcc
|
||||||
|
|
||||||
|
SRC = $(wildcard $(SRC_DIR)/*.cpp)
|
||||||
|
OBJ = $(SRC:$(SRC_DIR)/%.cpp=$(BUILD_DIR)/%.o)
|
||||||
|
DEP = $(OBJ:%.o=%.d)
|
||||||
|
|
||||||
|
$(TARGET_EXEC): $(OBJ)
|
||||||
|
$(CC) $(OBJ) -o $(TARGET_EXEC) $(LDFLAGS)
|
||||||
|
|
||||||
|
$(OBJ): $(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
|
||||||
|
@mkdir -p $(BUILD_DIR)
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -rf $(BUILD_DIR) $(TARGET_EXEC)
|
||||||
|
|
||||||
|
-include $(DEP)
|
3
README.md
Normal file
3
README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Game of life
|
||||||
|
|
||||||
|
A CS100 project. The git history is lost because the original git repository was deleted, this one was reconstructed from the files I submitted. A compiled version for windows is provided, you can compile for mac and linux using the provided makefile, minor changes to makefile might be required.
|
11
include/drawing.h
Normal file
11
include/drawing.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef DRAWING_H
|
||||||
|
#define DRAWING_H
|
||||||
|
|
||||||
|
// Public
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
// Private
|
||||||
|
static void draw_grid_lines();
|
||||||
|
static void draw_cells();
|
||||||
|
|
||||||
|
#endif
|
13
include/events.h
Normal file
13
include/events.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef EVENTS_H
|
||||||
|
#define EVENTS_H
|
||||||
|
|
||||||
|
#include <SDL_events.h>
|
||||||
|
|
||||||
|
// Public
|
||||||
|
void handle_events();
|
||||||
|
|
||||||
|
//Private
|
||||||
|
void handle_key_event(SDL_Keycode key_pressed);
|
||||||
|
void handle_mouse_event(int x, int y);
|
||||||
|
|
||||||
|
#endif
|
13
include/game.h
Normal file
13
include/game.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef GAME_H
|
||||||
|
#define GAME_H
|
||||||
|
|
||||||
|
// Public
|
||||||
|
void start_game();
|
||||||
|
void toggle_pause();
|
||||||
|
|
||||||
|
extern bool paused;
|
||||||
|
|
||||||
|
// Private
|
||||||
|
static void game_loop();
|
||||||
|
|
||||||
|
#endif
|
17
include/globals.h
Normal file
17
include/globals.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef CONFIG_H
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
#define CELL_SIZE 20
|
||||||
|
|
||||||
|
#define GRID_WIDTH 64
|
||||||
|
#define GRID_HEIGHT 48
|
||||||
|
|
||||||
|
#define WINDOW_WIDTH GRID_WIDTH * CELL_SIZE
|
||||||
|
#define WINDOW_HEIGHT GRID_HEIGHT * CELL_SIZE
|
||||||
|
|
||||||
|
#define FRAMES_PER_SECOND 60
|
||||||
|
#define UPDATES_PER_SECOND 5
|
||||||
|
|
||||||
|
#define ALIVE true
|
||||||
|
#define DEAD false
|
||||||
|
#endif
|
12
include/grid.h
Normal file
12
include/grid.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef GRID_H
|
||||||
|
#define GRID_H
|
||||||
|
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
// Public
|
||||||
|
void clear_grid();
|
||||||
|
void iterate_grid();
|
||||||
|
|
||||||
|
extern bool grid[GRID_HEIGHT][GRID_WIDTH];
|
||||||
|
|
||||||
|
#endif
|
14
include/main.h
Normal file
14
include/main.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef MAIN_H
|
||||||
|
#define MAIN_H
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
// Public
|
||||||
|
void quit_application(int exit_code);
|
||||||
|
|
||||||
|
extern SDL_Window *window;
|
||||||
|
|
||||||
|
// Private
|
||||||
|
static void init();
|
||||||
|
|
||||||
|
#endif
|
9
include/timing.h
Normal file
9
include/timing.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef TIMING_H
|
||||||
|
#define TIMING_H
|
||||||
|
|
||||||
|
// Public
|
||||||
|
void limit_fps();
|
||||||
|
|
||||||
|
extern double delta_time;
|
||||||
|
|
||||||
|
#endif
|
93
src/drawing.cpp
Normal file
93
src/drawing.cpp
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#include "drawing.h" // This file
|
||||||
|
#include "game.h" // Get paused state
|
||||||
|
#include "globals.h" // Size macros
|
||||||
|
#include "grid.h" // Get grid state
|
||||||
|
#include "main.h" // Get window
|
||||||
|
|
||||||
|
void clear_window() {
|
||||||
|
SDL_Surface *surface = SDL_GetWindowSurface(window);
|
||||||
|
|
||||||
|
Uint32 background = SDL_MapRGB(surface->format, 0x2E, 0x34, 0x40);
|
||||||
|
|
||||||
|
SDL_FillRect(surface, NULL, background);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* grid_lines_surface() {
|
||||||
|
Uint32 rmask, gmask, bmask, amask;
|
||||||
|
rmask = 0xff000000;
|
||||||
|
gmask = 0x00ff0000;
|
||||||
|
bmask = 0x0000ff00;
|
||||||
|
amask = 0x000000ff;
|
||||||
|
|
||||||
|
SDL_Surface *grid_lines = SDL_CreateRGBSurface(0, WINDOW_WIDTH, WINDOW_HEIGHT, 32, rmask, gmask, bmask, amask);
|
||||||
|
|
||||||
|
Uint32 lines_color = SDL_MapRGB(grid_lines->format, 0x3B, 0x42, 0x52);
|
||||||
|
|
||||||
|
SDL_Surface *vertical = SDL_CreateRGBSurface(0, 2, WINDOW_HEIGHT, 32, rmask, gmask, bmask, amask);
|
||||||
|
SDL_FillRect(vertical, NULL, lines_color);
|
||||||
|
for (int i = 0; i <= GRID_WIDTH; i++) {
|
||||||
|
SDL_Rect destination;
|
||||||
|
destination.x = i * CELL_SIZE - 1;
|
||||||
|
destination.y = 0;
|
||||||
|
|
||||||
|
SDL_BlitSurface(vertical, NULL, grid_lines, &destination);
|
||||||
|
}
|
||||||
|
SDL_FreeSurface(vertical);
|
||||||
|
|
||||||
|
SDL_Surface *horizontal = SDL_CreateRGBSurface(0, WINDOW_WIDTH, 2, 32, rmask, gmask, bmask, amask);
|
||||||
|
SDL_FillRect(horizontal, NULL, lines_color);
|
||||||
|
for (int i = 0; i <= GRID_HEIGHT; i++) {
|
||||||
|
SDL_Rect destination;
|
||||||
|
destination.x = 0;
|
||||||
|
destination.y = i * CELL_SIZE - 1;
|
||||||
|
|
||||||
|
SDL_BlitSurface(horizontal, NULL, grid_lines, &destination);
|
||||||
|
}
|
||||||
|
SDL_FreeSurface(horizontal);
|
||||||
|
|
||||||
|
return grid_lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* cell_surface() {
|
||||||
|
SDL_Surface *cell = SDL_CreateRGBSurface(0, CELL_SIZE, CELL_SIZE, 32, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
Uint32 cell_color = SDL_MapRGB(cell->format, 0xE5, 0xE9, 0xF0);
|
||||||
|
SDL_FillRect(cell, NULL, cell_color);
|
||||||
|
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw() {
|
||||||
|
clear_window();
|
||||||
|
|
||||||
|
draw_cells();
|
||||||
|
|
||||||
|
if (paused) draw_grid_lines();
|
||||||
|
|
||||||
|
SDL_UpdateWindowSurface(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_grid_lines() {
|
||||||
|
SDL_Surface *surface = SDL_GetWindowSurface(window);
|
||||||
|
static SDL_Surface *grid_lines = grid_lines_surface();
|
||||||
|
|
||||||
|
SDL_BlitSurface(grid_lines, NULL, surface, &surface->clip_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_cells() {
|
||||||
|
SDL_Surface *surface = SDL_GetWindowSurface(window);
|
||||||
|
static SDL_Surface *cell = cell_surface();
|
||||||
|
|
||||||
|
for (int i = 0; i < GRID_HEIGHT; i++)
|
||||||
|
for (int j = 0; j < GRID_WIDTH; j++) {
|
||||||
|
if (grid[i][j] == ALIVE) {
|
||||||
|
SDL_Rect destination;
|
||||||
|
destination.x = j * CELL_SIZE;
|
||||||
|
destination.y = i * CELL_SIZE;
|
||||||
|
|
||||||
|
SDL_BlitSurface(cell, NULL, surface, &destination);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
src/events.cpp
Normal file
49
src/events.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#include <SDL_events.h>
|
||||||
|
|
||||||
|
#include "events.h" // This file
|
||||||
|
#include "game.h" // Get and set paused state
|
||||||
|
#include "globals.h" // Cell size macros
|
||||||
|
#include "grid.h" // Set grid
|
||||||
|
#include "main.h" // Quit
|
||||||
|
|
||||||
|
void handle_events() {
|
||||||
|
SDL_Event event;
|
||||||
|
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
handle_key_event(event.key.keysym.sym);
|
||||||
|
break;
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
handle_mouse_event(event.button.x, event.button.y);
|
||||||
|
break;
|
||||||
|
case SDL_QUIT:
|
||||||
|
quit_application(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_key_event(SDL_Keycode key_pressed) {
|
||||||
|
switch (key_pressed) {
|
||||||
|
case SDLK_q:
|
||||||
|
quit_application(0);
|
||||||
|
break;
|
||||||
|
case SDLK_SPACE:
|
||||||
|
case SDLK_RETURN:
|
||||||
|
toggle_pause();
|
||||||
|
break;
|
||||||
|
case SDLK_r:
|
||||||
|
if (paused) clear_grid();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_mouse_event(int x, int y) {
|
||||||
|
if (!paused) return;
|
||||||
|
|
||||||
|
int i = y / CELL_SIZE;
|
||||||
|
int j = x / CELL_SIZE;
|
||||||
|
|
||||||
|
grid[i][j] = !grid[i][j];
|
||||||
|
}
|
43
src/game.cpp
Normal file
43
src/game.cpp
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#include "drawing.h" // Draw in game loop
|
||||||
|
#include "events.h" // Handle events in loop
|
||||||
|
#include "game.h" // This file
|
||||||
|
#include "globals.h" // Timing macros
|
||||||
|
#include "grid.h" // Iterate the grid
|
||||||
|
#include "timing.h" // Timings
|
||||||
|
|
||||||
|
// Public
|
||||||
|
bool paused;
|
||||||
|
|
||||||
|
// Private
|
||||||
|
const double req_update_time = 1.0 / UPDATES_PER_SECOND;
|
||||||
|
double time_since_update;
|
||||||
|
|
||||||
|
void start_game() {
|
||||||
|
clear_grid();
|
||||||
|
paused = true;
|
||||||
|
time_since_update = 0;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
game_loop();
|
||||||
|
|
||||||
|
limit_fps();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_loop() {
|
||||||
|
handle_events();
|
||||||
|
|
||||||
|
if (!paused) if ((time_since_update += delta_time) >= req_update_time) {
|
||||||
|
iterate_grid();
|
||||||
|
time_since_update -= req_update_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle_pause() {
|
||||||
|
paused = !paused;
|
||||||
|
time_since_update = 0;
|
||||||
|
}
|
46
src/grid.cpp
Normal file
46
src/grid.cpp
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include "globals.h" // Grid size macros
|
||||||
|
|
||||||
|
bool grid[GRID_HEIGHT][GRID_WIDTH];
|
||||||
|
|
||||||
|
void clear_grid() {
|
||||||
|
for (int i = 0; i < GRID_HEIGHT; i++)
|
||||||
|
for (int j = 0; j < GRID_WIDTH; j++) grid[i][j] = DEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count_alive_neighbours(int x, int y) {
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (int i = x - 1; i <= x + 1; i++)
|
||||||
|
for (int j = y - 1; j <= y + 1; j++){
|
||||||
|
if (i == x && j == y) continue;
|
||||||
|
|
||||||
|
int m = (i + GRID_HEIGHT) % GRID_HEIGHT;
|
||||||
|
int n = (j + GRID_WIDTH) % GRID_WIDTH;
|
||||||
|
|
||||||
|
if (grid[m][n] == ALIVE) count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iterate_grid() {
|
||||||
|
bool new_grid[GRID_HEIGHT][GRID_WIDTH];
|
||||||
|
|
||||||
|
for (int i = 0; i < GRID_HEIGHT; i++)
|
||||||
|
for (int j = 0; j < GRID_WIDTH; j++) {
|
||||||
|
int neighbours = count_alive_neighbours(i, j);
|
||||||
|
|
||||||
|
if (grid[i][j] == ALIVE) {
|
||||||
|
if (neighbours < 2) new_grid[i][j] = DEAD;
|
||||||
|
else if (neighbours == 2 || neighbours == 3) new_grid[i][j] = ALIVE;
|
||||||
|
else new_grid[i][j] = DEAD;
|
||||||
|
} else {
|
||||||
|
if (neighbours == 3) new_grid[i][j] = ALIVE;
|
||||||
|
else new_grid[i][j] = DEAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < GRID_HEIGHT; i++)
|
||||||
|
for (int j = 0; j < GRID_WIDTH; j++) grid[i][j] = new_grid[i][j];
|
||||||
|
}
|
44
src/main.cpp
Normal file
44
src/main.cpp
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#include "game.h" // To start the game
|
||||||
|
#include "globals.h" // Window dimensions
|
||||||
|
#include "main.h" // This file
|
||||||
|
|
||||||
|
// Public
|
||||||
|
SDL_Window *window;
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
init();
|
||||||
|
|
||||||
|
start_game();
|
||||||
|
|
||||||
|
quit_application(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
if(SDL_Init(SDL_INIT_VIDEO) != 0) {
|
||||||
|
printf("Could not start SDL.\nSDL error: %s\n", SDL_GetError());
|
||||||
|
quit_application(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
window = SDL_CreateWindow("Game of Life",
|
||||||
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
WINDOW_WIDTH, WINDOW_HEIGHT, 0);
|
||||||
|
|
||||||
|
if (window == NULL) {
|
||||||
|
printf("Could not create window: %s\n", SDL_GetError());
|
||||||
|
quit_application(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void quit_application(int exit_code) {
|
||||||
|
if (window != NULL) SDL_DestroyWindow(window);
|
||||||
|
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
exit(exit_code);
|
||||||
|
}
|
27
src/timing.cpp
Normal file
27
src/timing.cpp
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#include "globals.h" // Timing macros
|
||||||
|
#include "timing.h" // This file
|
||||||
|
|
||||||
|
// Public
|
||||||
|
double delta_time;
|
||||||
|
|
||||||
|
// Private
|
||||||
|
const double req_delta_time = 1.0 / FRAMES_PER_SECOND;
|
||||||
|
|
||||||
|
int t_start = 0;
|
||||||
|
|
||||||
|
void limit_fps() {
|
||||||
|
int t_end = SDL_GetTicks();
|
||||||
|
delta_time = (t_end - t_start) / 1000.0;
|
||||||
|
|
||||||
|
double extra_time = req_delta_time - delta_time;
|
||||||
|
|
||||||
|
int sleep_time = extra_time * 1000;
|
||||||
|
if (sleep_time > 0) SDL_Delay(sleep_time);
|
||||||
|
|
||||||
|
t_end = SDL_GetTicks();
|
||||||
|
delta_time = (t_end - t_start) / 1000.0;
|
||||||
|
|
||||||
|
t_start = t_end;
|
||||||
|
}
|
Reference in a new issue