Nie możesz wybrać więcej, niż 25 tematów
Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
408 wiersze
12 KiB
408 wiersze
12 KiB
/* GameOfLife - Conway's Game of Life in 3D
|
|
*
|
|
* Copyright (c) 2008 by Sebastian Lohff, seba@seba-geek.de
|
|
* http://www.seba-geek.de
|
|
*
|
|
* This file is part of GameOfLife.
|
|
*
|
|
* GameOfLife is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* GameOfLife is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with GameOfLife. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#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_WM_SetCaption("Seba's 2D/3D Game of Life", "Seba's 2D/3D Game of Life");
|
|
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;
|
|
}
|