Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

408 lignes
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;
}