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