Initial commit

This commit is contained in:
seba 2009-01-21 01:15:42 +01:00
commit e22b4910d5
11 changed files with 1136 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
GameOfLife
*.o

21
Makefile Normal file
View File

@ -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

BIN
defaultfont.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

14
example.fld Normal file
View File

@ -0,0 +1,14 @@
13 13 1
0000000000000
0000000000000
0000000000000
0000011100000
0000010100000
0000010100000
0000000000000
0000010100000
0000010100000
0000011100000
0000000000000
0000000000000
0000000000000

571
gameoflife.cpp Normal file
View File

@ -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);
}

86
gameoflife.h Normal file
View File

@ -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

BIN
libsegl.so.1 Executable file

Binary file not shown.

386
life.cpp Normal file
View File

@ -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;
}

27
readme.txt Normal file
View File

@ -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

22
start.fld Normal file
View File

@ -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

7
waves.fld Normal file
View File

@ -0,0 +1,7 @@
20 6 1
00000000010000000000
00000000010000000000
00000000010000000000
00000000010000000000
00000000010000000000
00000000010000000000