Initial commit
This commit is contained in:
commit
e22b4910d5
|
@ -0,0 +1,2 @@
|
|||
GameOfLife
|
||||
*.o
|
|
@ -0,0 +1,21 @@
|
|||
CC = g++
|
||||
LINK = `sdl-config --libs` -lGL -lGLU -lSDL_image -Wl,-rpath,.
|
||||
OBJ = `sdl-config --cflags` -Wall -c -I../libsegl
|
||||
LIBS = libsegl.so.1
|
||||
|
||||
prog: life.o gameoflife.o
|
||||
$(CC) $(LINK) $+ -o GameOfLife $(LIBS)
|
||||
|
||||
run: prog
|
||||
./GameOfLife
|
||||
|
||||
life.o: gameoflife.o
|
||||
|
||||
%.o: %.cpp %.h
|
||||
$(CC) $(OBJ) $<
|
||||
|
||||
%.o: %.cpp
|
||||
$(CC) $(OBJ) $<
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
|
@ -0,0 +1,14 @@
|
|||
13 13 1
|
||||
0000000000000
|
||||
0000000000000
|
||||
0000000000000
|
||||
0000011100000
|
||||
0000010100000
|
||||
0000010100000
|
||||
0000000000000
|
||||
0000010100000
|
||||
0000010100000
|
||||
0000011100000
|
||||
0000000000000
|
||||
0000000000000
|
||||
0000000000000
|
|
@ -0,0 +1,571 @@
|
|||
#include "gameoflife.h"
|
||||
|
||||
GameOfLife::GameOfLife(int _x, int _y) {
|
||||
init();
|
||||
x = _x;
|
||||
y = _y;
|
||||
allocate();
|
||||
}
|
||||
|
||||
GameOfLife::GameOfLife(std::string file) {
|
||||
init();
|
||||
load(file);
|
||||
}
|
||||
|
||||
GameOfLife::GameOfLife(int _x, int _y, int r_life, int r_dead) {
|
||||
init();
|
||||
fillRandom(_x, _y, r_life, r_dead);
|
||||
}
|
||||
|
||||
void GameOfLife::init() {
|
||||
view3d = true;
|
||||
feld = 0;
|
||||
x = y = 0;
|
||||
generation = 0;
|
||||
thickness = 0.5f;
|
||||
cellwidth = 1.0f;
|
||||
torus = true;
|
||||
fullcelluse = true;
|
||||
radius = 0.3f;
|
||||
height = 1.0f;
|
||||
parts = 12;
|
||||
sectobuild = 0.91f;
|
||||
b_secdone = 0.0f;
|
||||
secpertick = 1.0f;
|
||||
t_secdone = 0.0f;
|
||||
editmode = false;
|
||||
|
||||
// Calc cylinder sinvals
|
||||
sinval = new float[parts];
|
||||
cosval = new float[parts];
|
||||
|
||||
for(int i=0; i<parts; i++) {
|
||||
sinval[i] = radius * sin(segl::deg2rad(360.0f/parts*i));
|
||||
cosval[i] = radius * cos(segl::deg2rad(360.0f/parts*i));
|
||||
}
|
||||
|
||||
quad = gluNewQuadric();
|
||||
}
|
||||
|
||||
void GameOfLife::allocate() {
|
||||
feld = new State*[x];
|
||||
for(int i=0; i<x; i++) {
|
||||
feld[i] = new State[y];
|
||||
|
||||
// clean it
|
||||
for(int j=0; j<y; j++)
|
||||
feld[i][j] = dead;
|
||||
}
|
||||
}
|
||||
|
||||
void GameOfLife::cleanup() {
|
||||
if(feld) {
|
||||
for(int i=0; i<x; i++) {
|
||||
delete[](feld[i]);
|
||||
}
|
||||
delete(feld);
|
||||
feld = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GameOfLife::renderBrett() {
|
||||
float x1 = cellwidth*x / 2.0f;
|
||||
float y1 = thickness / 2.0f;
|
||||
float z1 = cellwidth*y / 2.0f;
|
||||
|
||||
// Brettquader
|
||||
GLfloat mat_diffuse[] = { 1.0f, 0.0f, 0.0f, 1.0f };
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
|
||||
glColor3f(1.0f, 0.0f, 0.0f);
|
||||
glBegin(GL_QUADS);
|
||||
// Platte
|
||||
glNormal3f(0.0f, 1.0f, 0.0f);
|
||||
glVertex3f(-x1, y1, -z1);
|
||||
glVertex3f( x1, y1, -z1);
|
||||
glVertex3f( x1, y1, z1);
|
||||
glVertex3f(-x1, y1, z1);
|
||||
|
||||
// Boden
|
||||
glNormal3f(0.0f,-1.0f, 0.0f);
|
||||
glVertex3f(-x1, -y1, -z1);
|
||||
glVertex3f( x1, -y1, -z1);
|
||||
glVertex3f( x1, -y1, z1);
|
||||
glVertex3f(-x1, -y1, z1);
|
||||
|
||||
// Seiten
|
||||
glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
glVertex3f(-x1, -y1, z1);
|
||||
glVertex3f( x1, -y1, z1);
|
||||
glVertex3f( x1, y1, z1);
|
||||
glVertex3f(-x1, y1, z1);
|
||||
|
||||
glNormal3f(0.0f, 0.0f,-1.0f);
|
||||
glVertex3f(-x1, -y1,-z1);
|
||||
glVertex3f( x1, -y1,-z1);
|
||||
glVertex3f( x1, y1,-z1);
|
||||
glVertex3f(-x1, y1,-z1);
|
||||
|
||||
glNormal3f(-1.0f, 0.0f, 0.0f);
|
||||
glVertex3f(-x1, -y1, z1);
|
||||
glVertex3f(-x1, y1, z1);
|
||||
glVertex3f(-x1, y1,-z1);
|
||||
glVertex3f(-x1, -y1,-z1);
|
||||
|
||||
glNormal3f(1.0f, 0.0f, 0.0f);
|
||||
glVertex3f( x1, -y1, z1);
|
||||
glVertex3f( x1, y1, z1);
|
||||
glVertex3f( x1, y1,-z1);
|
||||
glVertex3f( x1, -y1,-z1);
|
||||
glEnd();
|
||||
|
||||
//Gitter
|
||||
glPushMatrix();
|
||||
|
||||
|
||||
mat_diffuse[0] = 0.0f;
|
||||
mat_diffuse[1] = 1.0f;
|
||||
mat_diffuse[2] = 0.0f;
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
|
||||
|
||||
glColor3f(0.0f, 1.0f, 0.0f);
|
||||
for(int a=0; a<1; a++) {
|
||||
glTranslatef(0.0f, 0.01f, 0.0f);
|
||||
glBegin(GL_LINES);
|
||||
glNormal3f(0.0f, 1.0f, 0.0f);
|
||||
for(float i=-x1; i<=x1; i+=cellwidth) {
|
||||
glVertex3f(i, y1, -z1);
|
||||
glVertex3f(i, y1, z1);
|
||||
}
|
||||
|
||||
for(float i=-z1; i<=z1; i+=cellwidth) {
|
||||
glVertex3f(-x1, y1, i);
|
||||
glVertex3f( x1, y1, i);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void GameOfLife::renderStein(State s) {
|
||||
float sin1, sin2 = sinval[0], cos1, cos2 = cosval[0];
|
||||
|
||||
float height2 = 0.0f;
|
||||
switch(s) {
|
||||
case alife:
|
||||
height2 = height;
|
||||
break;
|
||||
case born:
|
||||
height2 = height * (b_secdone/sectobuild);
|
||||
break;
|
||||
case dies:
|
||||
height2 = height * ((sectobuild-b_secdone)/sectobuild);
|
||||
break;
|
||||
case dead:
|
||||
// unlikely to happen...
|
||||
height2 = 0.0f;
|
||||
break;
|
||||
}
|
||||
if(height2<0.001f)
|
||||
return;
|
||||
|
||||
glColor3f(0.2f, 0.2, 0.9f);
|
||||
|
||||
// for(float i=0, step=360.0f/parts; i<360.0f; i+= step) {
|
||||
for(int i=0; i<parts; i++) {
|
||||
sin1 = sin2;
|
||||
cos1 = cos2;
|
||||
sin2 = sinval[(i+1)%parts];
|
||||
cos2 = cosval[(i+1)%parts];
|
||||
// sin2 = radius * sin(deg2rad(i+step));
|
||||
// cos2 = radius * cos(deg2rad(i+step));
|
||||
GLfloat mat_diffuse[] = { 0.2f, 0.2, 0.9f, 1.0f };
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
|
||||
|
||||
/*
|
||||
glPushMatrix();
|
||||
glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
|
||||
gluCylinder(quad, radius, radius, height2, 12, 1);
|
||||
glTranslatef(0.0f, 0.0f, height2);
|
||||
gluDisk(quad, 0.0f, radius, 12, 1);
|
||||
glPopMatrix();
|
||||
*/
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glNormal3f(0.0f, 0.0f,-1.0f);
|
||||
glVertex3f(-radius, 0.0f, -radius);
|
||||
glVertex3f(-radius, height2,-radius);
|
||||
glVertex3f( radius, height2,-radius);
|
||||
glVertex3f( radius, 0.0f, -radius);
|
||||
|
||||
glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
glVertex3f( radius, 0.0f, radius);
|
||||
glVertex3f( radius, height2, radius);
|
||||
glVertex3f(-radius, height2, radius);
|
||||
glVertex3f(-radius, 0.0f, radius);
|
||||
|
||||
glNormal3f(-1.0f, 0.0f, 0.0f);
|
||||
glVertex3f(-radius, 0.0f, -radius);
|
||||
glVertex3f(-radius, 0.0f, radius);
|
||||
glVertex3f(-radius, height2, radius);
|
||||
glVertex3f(-radius, height2,-radius);
|
||||
|
||||
glNormal3f( 1.0f, 0.0f, 0.0f);
|
||||
glVertex3f( radius, 0.0f, radius);
|
||||
glVertex3f( radius, 0.0f, -radius);
|
||||
glVertex3f( radius, height2,-radius);
|
||||
glVertex3f( radius, height2, radius);
|
||||
|
||||
glNormal3f(0.0f, 1.0f, 0.0f);
|
||||
glVertex3f(-radius, height2, radius);
|
||||
glVertex3f( radius, height2, radius);
|
||||
glVertex3f( radius, height2,-radius);
|
||||
glVertex3f(-radius, height2,-radius);
|
||||
|
||||
|
||||
glEnd();
|
||||
/*
|
||||
glBegin(GL_TRIANGLES);
|
||||
// Boden Unten
|
||||
glNormal3f(0.0f,-1.0f, 0.0f);
|
||||
glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
glVertex3f(sin1, 0.0f, cos1);
|
||||
glVertex3f(sin2, 0.0f, cos2);
|
||||
|
||||
// Boden Oben
|
||||
glNormal3f(0.0f, 1.0f, 0.0f);
|
||||
glVertex3f(0.0f, height2, 0.0f);
|
||||
glVertex3f(sin1, height2, cos1);
|
||||
glVertex3f(sin2, height2, cos2);
|
||||
|
||||
//Seite
|
||||
glNormal3f((sin1+sin2)/2.0f, 0.0f, (cos1+cos2)/2.0f);
|
||||
glVertex3f(sin1, 0.0f, cos1);
|
||||
glVertex3f(sin2, 0.0f, cos2);
|
||||
glVertex3f(sin2, height2, cos2);
|
||||
|
||||
glNormal3f((sin1+sin2)/2.0f, 0.0f, (cos1+cos2)/2.0f);
|
||||
glVertex3f(sin2, height2, cos2);
|
||||
glVertex3f(sin1, height2, cos1);
|
||||
glVertex3f(sin1, 0.0f, cos1);
|
||||
glEnd();
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
void GameOfLife::translateTo(int _x, int _y) {
|
||||
glTranslatef(-cellwidth/2.0f*x+cellwidth*_x+cellwidth/2.0f, thickness/2.0f, -cellwidth/2.0f*y+cellwidth*_y+cellwidth/2.0f);
|
||||
}
|
||||
|
||||
void GameOfLife::lockStates() {
|
||||
for(int i=0; i<x; i++) {
|
||||
for(int j=0; j<y; j++) {
|
||||
if(feld[i][j]==dies)
|
||||
feld[i][j] = dead;
|
||||
else if(feld[i][j]==born)
|
||||
feld[i][j] = alife;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameOfLife::set3D(bool on) {
|
||||
view3d = on;
|
||||
}
|
||||
|
||||
bool GameOfLife::load(std::string file) {
|
||||
std::ifstream data(file.c_str());
|
||||
if(!data)
|
||||
return false;
|
||||
|
||||
std::string tmp;
|
||||
data >> x;
|
||||
data >> y;
|
||||
data >> torus;
|
||||
if(x<=0 || y <=0)
|
||||
return false;
|
||||
|
||||
cleanup();
|
||||
allocate();
|
||||
int j=0;
|
||||
getline(data, tmp); // Remove \n
|
||||
while(getline(data, tmp) && j<y) {
|
||||
for(int i=0; i<x && i<(int)tmp.length(); i++) {
|
||||
feld[i][j] = (tmp[i]=='1') ? born : dead;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameOfLife::save(std::string file) {
|
||||
std::ofstream data(file.c_str());
|
||||
if(!data)
|
||||
return false;
|
||||
|
||||
data << x << " " << y << " " << (torus?1:0) << std::endl;
|
||||
for(int j=0; j<y; j++) {
|
||||
for(int i=0; i<x; i++) {
|
||||
data << ((feld[i][j]==alife||feld[i][j]==born) ? '1' : '0');
|
||||
}
|
||||
data << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameOfLife::fillRandom(int _x, int _y, int r_life, int r_dead) {
|
||||
cleanup();
|
||||
|
||||
x = _x;
|
||||
y = _y;
|
||||
allocate();
|
||||
|
||||
srand(time(0));
|
||||
if(r_life+r_dead==0) {
|
||||
r_life = rand()%100 + 1;
|
||||
r_dead = rand()%100 + 1;
|
||||
}
|
||||
|
||||
float ratio = r_life/(float)(r_life+r_dead);
|
||||
|
||||
for(int i=0; i<x; i++) {
|
||||
for(int j=0; j<y; j++) {
|
||||
if((rand()%100)/100.0f < ratio) {
|
||||
feld[i][j] = born;
|
||||
} else {
|
||||
// should be set to dead, but to be sure...
|
||||
feld[i][j] = dead;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// void GameOfLife::toggle(int _x, int _y, State stat) {
|
||||
// if(feld && _x>=0 && _x<x && _y>=0 && _y<y) {
|
||||
// feld[_x][_y] = stat;
|
||||
// }
|
||||
// }
|
||||
|
||||
// const bool** GameOfLife::getFeld() {
|
||||
// return (const bool**)feld;
|
||||
// }
|
||||
|
||||
void GameOfLife::setEditMode(bool e) {
|
||||
editmode = e;
|
||||
if(e) {
|
||||
lockStates();
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void GameOfLife::move(int up, int right) {
|
||||
if(up>0)
|
||||
setpos.y = ((int)setpos.y+y+1)%y;
|
||||
else if(up<0)
|
||||
setpos.y = ((int)setpos.y+y-1)%y;
|
||||
if(right>0)
|
||||
setpos.x = ((int)setpos.x+x+1)%x;
|
||||
else if(right<0)
|
||||
setpos.x = ((int)setpos.x+x-1)%x;
|
||||
|
||||
}
|
||||
|
||||
void GameOfLife::toggle() {
|
||||
if(feld[(int)setpos.x][(int)setpos.y]==born||feld[(int)setpos.x][(int)setpos.y]==alife) {
|
||||
feld[(int)setpos.x][(int)setpos.y] = dead;
|
||||
} else {
|
||||
feld[(int)setpos.x][(int)setpos.y] = alife;
|
||||
}
|
||||
}
|
||||
|
||||
void GameOfLife::render(float sec) {
|
||||
if(!feld)
|
||||
return;
|
||||
|
||||
// Cylinder-building-timer
|
||||
if(b_secdone<=sectobuild) {
|
||||
b_secdone += sec;
|
||||
if(b_secdone>=sectobuild) {
|
||||
lockStates();
|
||||
}
|
||||
}
|
||||
|
||||
// Tick-timer
|
||||
t_secdone += sec;
|
||||
if(t_secdone>=secpertick) {
|
||||
tick();
|
||||
t_secdone = 0.0f;
|
||||
b_secdone = 0.0f;
|
||||
}
|
||||
|
||||
if(view3d) {
|
||||
renderBrett();
|
||||
|
||||
for(int j=0; j<y; j++) {
|
||||
for(int i=0; i<x; i++) {
|
||||
if(feld[i][j]!=dead) {
|
||||
glPushMatrix();
|
||||
translateTo(i, j);
|
||||
renderStein(feld[i][j]);
|
||||
glPopMatrix();
|
||||
}
|
||||
if(editmode) {
|
||||
if(i==setpos.x && j==setpos.y) {
|
||||
glPushMatrix();
|
||||
float mat_diffuse[3] = { 0.0f, 1.0f, 0.0f };
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
|
||||
translateTo(i, j);
|
||||
glTranslatef(0.0f, 0.01f, 0.0f);
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(0.0f, 1.0f, 0.0f);
|
||||
glNormal3f(0.0f, 1.0f, 0.0f);
|
||||
glVertex3f(-cellwidth/2.0f, 0.0f, cellwidth/2.0f);
|
||||
glVertex3f( cellwidth/2.0f, 0.0f, cellwidth/2.0f);
|
||||
glVertex3f( cellwidth/2.0f, 0.0f,-cellwidth/2.0f);
|
||||
glVertex3f(-cellwidth/2.0f, 0.0f,-cellwidth/2.0f);
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SDL_Surface *screen = SDL_GetVideoSurface();
|
||||
float wperp = screen->w /(float)x;
|
||||
float hperp = screen->h /(float)y;
|
||||
float border;
|
||||
|
||||
glPushMatrix();
|
||||
if(wperp<hperp) {
|
||||
glTranslatef(0.0f, (hperp-wperp)*y/2.0f, 0.0f);
|
||||
hperp = wperp;
|
||||
} else {
|
||||
glTranslatef((wperp-hperp)*x/2.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
border = 0.0f;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
for(int j=0; j<y; j++) {
|
||||
for(int i=0; i<x; i++) {
|
||||
if(feld[i][j]==alife||feld[i][j]==born) {
|
||||
glColor3f(0.0f, 0.0f, 1.0f);
|
||||
} else {
|
||||
glColor3f(1.0f, 0.0f, 0.0f);
|
||||
}
|
||||
glVertex2f(hperp*i+border, hperp*j+border);
|
||||
glVertex2f(hperp*i+border, hperp*(j+1)-border);
|
||||
glVertex2f(hperp*(i+1)-border, hperp*(j+1)-border);
|
||||
glVertex2f(hperp*(i+1)-border, hperp*j+border);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
if(editmode) {
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(0.0f, 1.0f, 0.0f);
|
||||
glVertex2f(hperp*setpos.x+border, hperp*setpos.y+border);
|
||||
glVertex2f(hperp*setpos.x+border, hperp*(setpos.y+1)-border);
|
||||
glVertex2f(hperp*(setpos.x+1)-border, hperp*(setpos.y+1)-border);
|
||||
glVertex2f(hperp*(setpos.x+1)-border, hperp*setpos.y+border);
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
|
||||
// glTranslatef(0.0f, 0.0f, 0.1f);
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
glBegin(GL_LINES);
|
||||
for(float i=0; i<x; i+=1.0f) {
|
||||
glVertex2f(i*hperp, 0);
|
||||
glVertex2f(i*hperp, y*hperp);
|
||||
}
|
||||
|
||||
for(float i=0; i<y; i+=1.0f) {
|
||||
glVertex2f(0, i*hperp);
|
||||
glVertex2f(x*hperp, i*hperp); }
|
||||
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float GameOfLife::getTickSec() {
|
||||
return secpertick;
|
||||
}
|
||||
|
||||
float GameOfLife::getBuildSec() {
|
||||
return sectobuild;
|
||||
}
|
||||
|
||||
void GameOfLife::setTickSec(float s) {
|
||||
std::cout << "Set to " << s << std::endl;
|
||||
secpertick = s;
|
||||
}
|
||||
|
||||
void GameOfLife::setBuildSec(float s) {
|
||||
sectobuild = s;
|
||||
}
|
||||
|
||||
void GameOfLife::setTorus(bool t) {
|
||||
torus = t;
|
||||
}
|
||||
|
||||
unsigned long GameOfLife::getGeneration() {
|
||||
return generation;
|
||||
}
|
||||
|
||||
void GameOfLife::tick() {
|
||||
if(sectobuild>secpertick)
|
||||
lockStates();
|
||||
|
||||
int near;
|
||||
int x1, y1;
|
||||
for(int i=0; i<x; i++) {
|
||||
for(int j=0; j<y; j++) {
|
||||
near = 0;
|
||||
for(int a=i-1; a<=(i+1); a++) {
|
||||
for(int b=j-1; b<=(j+1); b++) {
|
||||
if((a==i && b==j) || (!torus && (a<0 || b<0 || a>=x || b>=y)))
|
||||
continue;
|
||||
if(torus) {
|
||||
x1 = (a+x)%x;
|
||||
y1 = (b+y)%y;
|
||||
} else {
|
||||
x1 = a;
|
||||
y1 = b;
|
||||
}
|
||||
|
||||
if(feld[x1][y1]==alife || (fullcelluse && (feld[x1][y1]==dies)))
|
||||
near++;
|
||||
}
|
||||
}
|
||||
|
||||
if(feld[i][j]==alife) {
|
||||
if(near!=2 && near!=3)
|
||||
feld[i][j] = dies;
|
||||
} else if(feld[i][j]==dead) {
|
||||
if(near==3)
|
||||
feld[i][j] = born;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(sectobuild<0.1f)
|
||||
lockStates();
|
||||
generation++;
|
||||
}
|
||||
|
||||
void GameOfLife::clear() {
|
||||
for(int i=0; i<x; i++) {
|
||||
for(int j=0; j<y; j++) {
|
||||
feld[i][j] = dead;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GameOfLife::~GameOfLife() {
|
||||
cleanup();
|
||||
delete[](sinval);
|
||||
delete[](cosval);
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
#ifndef __GAMEOFLIFE_H
|
||||
#define __GAMEOFLIFE_H
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <SDL_opengl.h>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <SDL.h>
|
||||
#include "emath.h"
|
||||
#include "punkt2d.h"
|
||||
|
||||
typedef enum { dead=0, alife, dies, born } State;
|
||||
|
||||
class GameOfLife {
|
||||
private:
|
||||
State **feld;
|
||||
int x, y;
|
||||
bool torus;
|
||||
bool fullcelluse;
|
||||
unsigned long generation;
|
||||
|
||||
GLUquadricObj *quad;
|
||||
|
||||
// Brett
|
||||
float thickness;
|
||||
float cellwidth;
|
||||
|
||||
// Cylinder
|
||||
float radius;
|
||||
float height;
|
||||
int parts;
|
||||
float *sinval;
|
||||
float *cosval;
|
||||
|
||||
//render
|
||||
bool view3d;
|
||||
float sectobuild;
|
||||
float b_secdone;
|
||||
float secpertick;
|
||||
float t_secdone;
|
||||
|
||||
// Edit
|
||||
segl::Punkt2D setpos;
|
||||
bool editmode;
|
||||
|
||||
void init();
|
||||
void allocate();
|
||||
void cleanup();
|
||||
|
||||
void renderBrett();
|
||||
void renderStein(State s);
|
||||
|
||||
void translateTo(int _x, int _y);
|
||||
void lockStates();
|
||||
public:
|
||||
GameOfLife(int _x, int _y);
|
||||
GameOfLife(int _x, int _y, int r_life, int r_dead);
|
||||
GameOfLife(std::string file);
|
||||
~GameOfLife();
|
||||
|
||||
void set3D(bool on);
|
||||
bool load(std::string file);
|
||||
bool save(std::string file);
|
||||
|
||||
void fillRandom(int _x, int _y, int r_life, int r_dead);
|
||||
// void toggle(int _x, int _y);
|
||||
|
||||
void setEditMode(bool e);
|
||||
void move(int up, int right);
|
||||
void toggle();
|
||||
|
||||
float getTickSec();
|
||||
float getBuildSec();
|
||||
void setTickSec(float s);
|
||||
void setBuildSec(float s);
|
||||
void setTorus(bool t);
|
||||
unsigned long getGeneration();
|
||||
|
||||
// const bool** getFeld();
|
||||
void tick();
|
||||
void render(float sec);
|
||||
void clear();
|
||||
};
|
||||
|
||||
#endif
|
Binary file not shown.
|
@ -0,0 +1,386 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <SDL.h>
|
||||
#include <SDL_opengl.h>
|
||||
#include "gameoflife.h"
|
||||
#include "glcamera.h"
|
||||
#include "fpsmanager.h"
|
||||
#include "glfontengine.h"
|
||||
|
||||
void setVideo(bool view3d, int width, int height);
|
||||
void displayUsage();
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int width = 1024;
|
||||
int height= 768;
|
||||
bool view3d = true;
|
||||
bool renderosd = true;
|
||||
bool paused = false;
|
||||
bool editmode = false;
|
||||
// bool showcam2d = false;
|
||||
GameOfLife feld(20, 20, 1, 2);
|
||||
|
||||
{
|
||||
std::string loadfile = "";
|
||||
int feld_x = 20;
|
||||
int feld_y = 20;
|
||||
int rand_alife = 1;
|
||||
int rand_dead = 3;
|
||||
bool torus = true;
|
||||
for(int i=1; i<argc; i++) {
|
||||
std::string arg1(argv[i]);
|
||||
|
||||
if(arg1=="-h"||arg1=="--help") {
|
||||
displayUsage();
|
||||
return 0;
|
||||
} else if(arg1=="-v"||arg1=="--version") {
|
||||
std::cout << "Conway's \"Game of Life\" in 2d/3d v1.0" << std::endl <<
|
||||
"Written by seba (www.seba-geek.de)" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//cmds mit parametern
|
||||
if(i==argc-1) {
|
||||
std::cerr << "Error: Unknown option or no parameter given" << std::endl << "Use --help for help" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(arg1=="-fx"||arg1=="--field-x") {
|
||||
feld_x = atoi(argv[i+1]);
|
||||
if(feld_x<=0)
|
||||
feld_x = 20;
|
||||
} else if(arg1=="-fy"||arg1=="--field-y") {
|
||||
feld_y = atoi(argv[i+1]);
|
||||
if(feld_y<=0)
|
||||
feld_y = 20;
|
||||
} else if(arg1=="-l"||arg1=="--load") {
|
||||
loadfile = argv[i+1];
|
||||
} else if(arg1=="-rd"||arg1=="--rand-dead") {
|
||||
rand_dead = atoi(argv[i+1]);
|
||||
if(rand_dead<0)
|
||||
rand_dead = 3;
|
||||
} else if(arg1=="-ra"||arg1=="--rand-alife") {
|
||||
rand_alife = atoi(argv[i+1]);
|
||||
if(rand_alife<0)
|
||||
rand_alife = 1;
|
||||
} else if(arg1=="-t"||arg1=="--torus") {
|
||||
torus = (bool)atoi(argv[i+1]);
|
||||
} else {
|
||||
std::cerr << "Error: Unknown option '" << arg1 << "'" << std::endl << "Use --help for help" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
i++; // parameter used
|
||||
}
|
||||
if(loadfile=="") {
|
||||
feld.fillRandom(feld_x, feld_y, rand_alife, rand_dead);
|
||||
feld.setTorus(torus);
|
||||
} else {
|
||||
if(!feld.load(loadfile)) {
|
||||
std::cerr << "Error while loading \"" << loadfile << "\", no field loaded" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// SDL Initialisieren
|
||||
if(SDL_Init(SDL_INIT_VIDEO)==-1) {
|
||||
std::cerr << "SDL konnte nicht initialisiert werden: " << SDL_GetError() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_EnableKeyRepeat(150, 50);
|
||||
|
||||
// Videomode setzen
|
||||
int videoflags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;
|
||||
|
||||
|
||||
// if(fullscreen)
|
||||
// videoflags |= SDL_FULLSCREEN;
|
||||
|
||||
if(!SDL_SetVideoMode(width, height, 32, videoflags)) {
|
||||
std::cerr << "Konnte Videomode nicht setzen: " << SDL_GetError() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// OpenGL
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
|
||||
glClearDepth(1.0f);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.2f, 100.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
// Licht
|
||||
|
||||
GLfloat mat_diffuse[] = { 1.0f, 0.0f, 0.2f, 1.0f };
|
||||
// GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
// GLfloat mat_shininess[] = { 50.0f };
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
|
||||
// glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
|
||||
// glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
|
||||
|
||||
GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
// GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
GLfloat light_position[] = { 100.0f,100.0f, 0.0f };
|
||||
// GLfloat spot_direction[] = { 1.0f, -1.0f, 0.0f };
|
||||
|
||||
glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
|
||||
// glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction);
|
||||
// glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 2.0f);
|
||||
// glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 45.0f);
|
||||
// glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, light_position);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT1);
|
||||
|
||||
/*
|
||||
GLfloat light1_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
|
||||
GLfloat light1_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
|
||||
GLfloat light1_specular[] = { 1.0, 1.0, 1.0, 1.0 };
|
||||
GLfloat light1_position[] = { -2.0, 2.0, 1.0, 1.0 };
|
||||
GLfloat spot_direction[] = { -1.0, -1.0, 0.0 };
|
||||
glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
|
||||
glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
|
||||
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.5);
|
||||
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.5);
|
||||
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.2);
|
||||
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 45.0);
|
||||
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction);
|
||||
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 2.0);
|
||||
glEnable(GL_LIGHT1);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
*/
|
||||
|
||||
// Font
|
||||
|
||||
|
||||
if(!segl::GLFontEngine::addFont("defaultfont.png", "default")) {
|
||||
std::cerr << "\"defaultfont.png\" not found! No fonts will be displayed!" << std::endl;
|
||||
}
|
||||
segl::GLFontEngine fontengine("default");
|
||||
fontengine.setSize(21);
|
||||
|
||||
// SDL/Spielvariablen
|
||||
SDL_Event event;
|
||||
bool quit = false;
|
||||
segl::FPSManager fpsman(60);
|
||||
segl::GLCamera camera;
|
||||
camera.setPosDirNorm(segl::Punkt3D(0.0f, 5.0f, 15.0f), segl::Punkt3D(0.0f, 0.0f, -1.0f), segl::Punkt3D(0.0f, 1.0f, 0.0f));
|
||||
Uint32 lastframe = SDL_GetTicks(), thisframe = SDL_GetTicks();
|
||||
|
||||
while(!quit) {
|
||||
if(SDL_PollEvent(&event)) {
|
||||
switch(event.type) {
|
||||
case SDL_QUIT:
|
||||
quit = true;
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
switch(event.key.keysym.sym) {
|
||||
case SDLK_t:
|
||||
view3d = !view3d;
|
||||
setVideo(view3d, width, height);
|
||||
feld.set3D(view3d);
|
||||
if(view3d)
|
||||
glEnable(GL_LIGHTING);
|
||||
else
|
||||
glDisable(GL_LIGHTING);
|
||||
break;
|
||||
case SDLK_p:
|
||||
paused = !paused;
|
||||
break;
|
||||
case SDLK_o:
|
||||
renderosd = !renderosd;
|
||||
break;
|
||||
case SDLK_c:
|
||||
if(editmode && event.key.keysym.mod & KMOD_SHIFT) {
|
||||
feld.clear();
|
||||
} else if(!view3d) {
|
||||
|
||||
}
|
||||
break;
|
||||
case SDLK_b:
|
||||
if(feld.getBuildSec()==0.0f) {
|
||||
if(feld.getTickSec()<0.1f)
|
||||
feld.setBuildSec(feld.getTickSec()-0.01f);
|
||||
else
|
||||
feld.setBuildSec(feld.getTickSec()-0.1f);
|
||||
} else {
|
||||
feld.setBuildSec(0.0f);
|
||||
}
|
||||
break;
|
||||
case SDLK_ESCAPE:
|
||||
quit = true;
|
||||
break;
|
||||
case SDLK_PLUS:
|
||||
if(feld.getTickSec()>=0.1f) {
|
||||
feld.setTickSec(feld.getTickSec()+0.1f);
|
||||
if(feld.getBuildSec()!=0.0f)
|
||||
feld.setBuildSec(feld.getBuildSec()+0.1f);
|
||||
} else {
|
||||
feld.setTickSec(feld.getTickSec()+0.01f);
|
||||
if(feld.getBuildSec()!=0.0f)
|
||||
feld.setBuildSec(feld.getBuildSec()+0.01f);
|
||||
}
|
||||
break;
|
||||
case SDLK_MINUS:
|
||||
if(feld.getTickSec()>0.1f) {
|
||||
feld.setTickSec(feld.getTickSec()-0.1f);
|
||||
if(feld.getBuildSec()!=0.0f)
|
||||
feld.setBuildSec(feld.getBuildSec()-0.1f);
|
||||
} else if(feld.getTickSec()>=0.01f) {
|
||||
feld.setTickSec(feld.getTickSec()-0.01f);
|
||||
if(feld.getBuildSec()!=0.0f)
|
||||
feld.setBuildSec(feld.getBuildSec()-0.01f);
|
||||
}
|
||||
break;
|
||||
case SDLK_e:
|
||||
editmode = !editmode;
|
||||
feld.setEditMode(editmode);
|
||||
if(editmode)
|
||||
paused = true;
|
||||
else
|
||||
paused = false;
|
||||
break;
|
||||
// Edit Mode Stuff
|
||||
case SDLK_SPACE:
|
||||
if(editmode)
|
||||
feld.toggle();
|
||||
break;
|
||||
case SDLK_UP:
|
||||
if(editmode && (!view3d || event.key.keysym.mod&KMOD_SHIFT))
|
||||
feld.move(-1, 0);
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
if(editmode && (!view3d || event.key.keysym.mod&KMOD_SHIFT))
|
||||
feld.move(1, 0);
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
if(editmode && (!view3d || event.key.keysym.mod&KMOD_SHIFT))
|
||||
feld.move(0, 1);
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
if(editmode && (!view3d || event.key.keysym.mod&KMOD_SHIFT))
|
||||
feld.move(0, -1);
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_VIDEORESIZE:
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Set scene stuff
|
||||
lastframe = thisframe;
|
||||
thisframe = SDL_GetTicks();
|
||||
float sec = (thisframe-lastframe)/1000.0f;
|
||||
if(view3d) {
|
||||
Uint8 *keystate = SDL_GetKeyState(NULL);
|
||||
if(!keystate[SDLK_LSHIFT]&&!keystate[SDLK_RSHIFT])
|
||||
camera.handleKeys(sec);
|
||||
}
|
||||
|
||||
//Render scene
|
||||
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glLoadIdentity();
|
||||
|
||||
if(view3d)
|
||||
camera.setCamera();
|
||||
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, light_position);
|
||||
// glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
|
||||
|
||||
feld.render(sec*(!paused));
|
||||
|
||||
|
||||
if(renderosd) {
|
||||
if(view3d) {
|
||||
glDisable(GL_LIGHTING);
|
||||
fontengine.prepare2DbyPushingMatrix();
|
||||
}
|
||||
|
||||
std::stringstream txt;
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
if(paused)
|
||||
fontengine.renderLine(" Paused...", width/2, 0, true);
|
||||
if(editmode)
|
||||
fontengine.renderLine("Edit mode", width/2, 21, true);
|
||||
txt << "Sec/Build: ";
|
||||
if(feld.getBuildSec()!=0.0f)
|
||||
txt << feld.getBuildSec();
|
||||
else
|
||||
txt << "Off";
|
||||
fontengine.renderLine(txt.str(), width/3, height-21, true);
|
||||
txt.str("");
|
||||
txt.clear();
|
||||
txt << "Sec/Tick: " << feld.getTickSec();
|
||||
fontengine.renderLine(txt.str(), width*2/3, height-21, true);
|
||||
txt.str("");
|
||||
txt << "Generation: " << feld.getGeneration();
|
||||
if(!paused)
|
||||
fontengine.renderLine(txt.str(), width/2, 0, true);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if(view3d) {
|
||||
glEnable(GL_LIGHTING);
|
||||
fontengine.regain3DbyPoppingMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
SDL_GL_SwapBuffers();
|
||||
fpsman.delay();
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setVideo(bool view3d, int width, int height) {
|
||||
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
if(view3d)
|
||||
gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.2f, 100.0f);
|
||||
else
|
||||
glOrtho(0, width, height, 0, -1, 1);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void displayUsage() {
|
||||
std::cout << "Usage: GameOfLife [options]" << std::endl <<
|
||||
std::endl <<
|
||||
"Options: " << std:: endl <<
|
||||
" -fx, --field-x <w> Set field width (Default: 20)" << std::endl <<
|
||||
" -fy, --field-y <h> Set field height (Default: 20)" << std::endl <<
|
||||
" -t, --torus <1/0> Enable/Disable Torus (Default: 1)" << std::endl <<
|
||||
" -l, --load <file> Load field from textfile" << std::endl <<
|
||||
" -rd, --rand-dead <int> Defines dead-cellratio for random fill (Default: 3)" << std::endl <<
|
||||
" -ra, --rand-alife <int> Defines alife-cellratio for random fill (Default: 1)" << std::endl <<
|
||||
" -h, --help Shows this help and exits" << std::endl <<
|
||||
" -v, --version Displays versioninfo and exits" << std::endl <<
|
||||
std::endl <<
|
||||
"Read the readme.txt supplied with this program for further information" << std::endl;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
Conway's "Game of Life" in 2d/3d
|
||||
written by seba (www.seba-geek.de)
|
||||
|
||||
- Write a field-file
|
||||
Begin with a header in the first line
|
||||
<x (width)> <y (height)> <torus>
|
||||
For example "21 21 1" would be a 21x21 field torus
|
||||
|
||||
After the header follows the field-definition,
|
||||
col => x-axis, row => y-axis
|
||||
0 is a dead cell
|
||||
1 is a living cell
|
||||
|
||||
Look at the example.fld for further explaination
|
||||
|
||||
|
||||
- Controls
|
||||
t Toggle 2d/3d mode
|
||||
p Pause
|
||||
o Toggle OSD
|
||||
e Toggle Edit-Mode
|
||||
Move with shift + arrows
|
||||
Toggle fieldstate withs Space
|
||||
Clear field with shift + c
|
||||
b Toggle buildup of cells
|
||||
-/+ In- or decrease speed
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
21 21 1
|
||||
000000000000000000000
|
||||
001000000000001000000
|
||||
011100000000011100000
|
||||
001000000000001000000
|
||||
000000000000000000000
|
||||
000000000000000000000
|
||||
000000000000000000000
|
||||
000000000111000000000
|
||||
000000000101000000000
|
||||
000000000101000000000
|
||||
000000000000000000000
|
||||
000000000101000000000
|
||||
000000000101000000000
|
||||
000000000111000000000
|
||||
000000000000000000000
|
||||
000000000000000000000
|
||||
001000000000000100000
|
||||
011100000000001110000
|
||||
001000000000000100000
|
||||
000000000000000000000
|
||||
000000000000000000000
|
Loading…
Reference in New Issue