Skip to content

Instantly share code, notes, and snippets.

@Equinox-
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Equinox-/8995189 to your computer and use it in GitHub Desktop.
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.
#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