Last active
August 29, 2015 13:56
-
-
Save Equinox-/8995189 to your computer and use it in GitHub Desktop.
Conway's Game of Life, written in C/OpenGL. Uses bitmasking for optimization. Build with -lglut -lGL.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <gl.h> | |
#include <freeglut.h> | |
#define LIVE_MASK 0b10000 | |
#define WIDTH 1366 | |
#define HEIGHT 768 | |
short ** front; | |
short ** back; | |
int i, j; | |
int o, k; | |
short surr; | |
int milliTime() { | |
struct timeval tv; | |
gettimeofday(&tv, NULL ); | |
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); | |
} | |
inline short* get(short ** map, int x, int y) { | |
if (x < 0) { | |
x += WIDTH; | |
} else if (x >= WIDTH) { | |
x -= WIDTH; | |
} | |
if (y < 0) { | |
y += HEIGHT; | |
} else if (y >= HEIGHT) { | |
y -= HEIGHT; | |
} | |
return &(map[x][y]); | |
} | |
void genBuffers() { | |
front = malloc(WIDTH * sizeof(short*)); | |
back = malloc(WIDTH * sizeof(short*)); | |
for (i = 0; i < WIDTH; i++) { | |
front[i] = malloc(HEIGHT * sizeof(short)); | |
back[i] = malloc(HEIGHT * sizeof(short)); | |
for (j = 0; j < HEIGHT; j++) { | |
front[i][j] = rand() & LIVE_MASK; | |
back[i][j] = 0; | |
} | |
} | |
} | |
void clearSurr(short ** map) { | |
for (i = 0; i < WIDTH; i++) { | |
for (j = 0; j < HEIGHT; j++) { | |
map[i][j] &= LIVE_MASK; | |
} | |
} | |
} | |
void updateSurr(short ** map) { | |
for (i = 0; i < WIDTH; i++) { | |
for (j = 0; j < HEIGHT; j++) { | |
if ((map[i][j] & LIVE_MASK) == LIVE_MASK) { | |
for (o = -1; o <= 1; o++) { | |
for (k = -1; k <= 1; k++) { | |
if (o || k) { | |
*(get(map, i + o, j + k)) += 1; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
void reshape(int width, int height) { | |
glMatrixMode(GL_PROJECTION); | |
glOrtho(0.0, WIDTH, 0.0, HEIGHT, -1.0, 1.0); | |
} | |
void render(void) { | |
glClear(GL_COLOR_BUFFER_BIT); | |
glBegin(GL_QUADS); | |
for (i = 0; i < WIDTH; i++) { | |
for (j = 0; j < HEIGHT; j++) { | |
surr = front[i][j] & ~LIVE_MASK; | |
if ((surr > 0 && rand() < RAND_MAX / 1000) || surr == 3 | |
|| ((front[i][j] & LIVE_MASK) && surr == 2)) { | |
glColor3f(((float) i) / ((float) WIDTH), 1.0, | |
((float) j) / ((float) HEIGHT)); | |
glVertex2f(i, j); | |
glVertex2f(i, j + 1); | |
glVertex2f(i + 1, j + 1); | |
glVertex2f(i + 1, j); | |
back[i][j] |= LIVE_MASK; | |
/* | |
* UNROLLED | |
* for (o = -1; o <= 1; ++o) { | |
* for (k = -1; k <= 1; ++k) { | |
* if (o || k) { | |
* *(get(back, i + o, j + k)) += 1; | |
* } | |
* } | |
* } | |
*/ | |
*(get(back, i + 1, j)) += 1; | |
*(get(back, i - 1, j)) += 1; | |
*(get(back, i - 1, j - 1)) += 1; | |
*(get(back, i, j - 1)) += 1; | |
*(get(back, i + 1, j - 1)) += 1; | |
*(get(back, i - 1, j + 1)) += 1; | |
*(get(back, i, j + 1)) += 1; | |
*(get(back, i + 1, j + 1)) += 1; | |
} | |
front[i][j] = 0; | |
} | |
} | |
glEnd(); | |
glFlush(); | |
short ** temp = back; | |
back = front; | |
front = temp; | |
} | |
void keyPress(unsigned char c, int x, int y) { | |
if (c == 'f') { | |
glutFullScreen(); | |
} else if (c == 'w') { | |
glutIconifyWindow(); | |
} | |
} | |
int main(int argc, char ** argv) { | |
glutInit(&argc, argv); | |
genBuffers(); | |
updateSurr(front); | |
glutInitWindowPosition(0, 0); | |
glutInitWindowSize(WIDTH, HEIGHT); | |
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); | |
glutCreateWindow("Test"); | |
//glutReshapeFunc(reshape); | |
glutDisplayFunc(render); | |
glutKeyboardUpFunc(keyPress); | |
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, | |
GLUT_ACTION_GLUTMAINLOOP_RETURNS); | |
reshape(WIDTH, HEIGHT); | |
glutIdleFunc(glutPostRedisplay); | |
glutMainLoop(); | |
for (i = 0; i < WIDTH; i++) { | |
free(front[i]); | |
free(back[i]); | |
} | |
free(front); | |
free(back); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment