diff --git a/src/Application.cpp b/src/Application.cpp new file mode 100644 index 0000000..20cd939 --- /dev/null +++ b/src/Application.cpp @@ -0,0 +1,61 @@ +/* + * Application.cpp + * + * Created on: 14.01.2011 + * Author: gmueller + */ + +#include "Application.h" +#include "Time.h" +#include "network.h" + +Application::Application() : + running(false), master(false) { + +} + +Application::~Application() { + +} + +bool Application::isRunning() { + return running; +} + +void Application::start() { + running = true; +} + +void Application::stop() { + running = false; +} + +void Application::initialize(int argc, char ** argv) { + game_setup(&game); + game_reset(&game); + gameUpdateSchudule.setExact(true); + gameUpdateSchudule.setInterval(0.05); + start(); +} + +void Application::shutdown() { + shutdown_network(); +} + +void Application::update() { + // Get time and mouse position + time = PerformanceTimer::get(); + dt = time - lastTime; + lastTime = time; + + service_network(&game); + game_update(&game, dt); + if (master && gameUpdateSchudule.next(time)) { + send_game_updates(&game); + } +} + +void Application::setMaster(bool master) { + this->master = master; + game_set_master(&game, master ? 1 : 0); +} diff --git a/src/Application.h b/src/Application.h new file mode 100644 index 0000000..77319a7 --- /dev/null +++ b/src/Application.h @@ -0,0 +1,48 @@ +/* + * Application.h + * + * Created on: 14.01.2011 + * Author: gmueller + */ + +#ifndef APPLICATION_H_ +#define APPLICATION_H_ + +#include "game.h" + +#include "Schedule.h" + +class Application { +public: + Application(); + virtual ~Application(); + virtual void initialize(int argc, char ** argv); + virtual void update(); + virtual void shutdown(); + + bool isRunning(); + virtual void start(); + virtual void stop(); + + inline bool isMaster() { + return master; + } + void setMaster(bool master); + + inline game_t *getGame() { + return &game; + } + +private: + bool running; + double lastTime; + Schedule gameUpdateSchudule; + bool master; + +protected: + game_t game; + double dt; + double time; +}; + +#endif /* APPLICATION_H_ */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6dafd76..21bedd9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,7 +6,7 @@ if (ENABLE_VIDEO) include_directories (${GREMLIN_SOURCE_DIR}/libs/glfw/include) include_directories (${GREMLIN_SOURCE_DIR}/libs/spark/include) - SET(VIDEO_SOURCES Explosion oglfont) + SET(VIDEO_SOURCES Explosion oglfont Client) endif(ENABLE_VIDEO) include_directories (${GREMLIN_SOURCE_DIR}/libs/enet/include) @@ -15,6 +15,17 @@ include_directories (${GREMLIN_SOURCE_DIR}/src) # define executable add_executable( gremlin + Application + main + game + Time + network + ${VIDEO_SOURCES} +) + +# define executable +add_executable( gremlin_dedicated + Application main game Time diff --git a/src/Client.cpp b/src/Client.cpp new file mode 100644 index 0000000..131e17b --- /dev/null +++ b/src/Client.cpp @@ -0,0 +1,534 @@ +/* + * Client.cpp + * + * Created on: 14.01.2011 + * Author: gmueller + */ + +#include "Client.h" +#include "network.h" +#include "Explosion.h" +#include "Time.h" + +#include + +#include +#include +#include +#include +#include + +GLUquadricObj *quadratic; +Explosion explosion; + +void setup_light() { + GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f }; + GLfloat LightDiffuse[] = { 0.5f, 0.5f, 0.5f, 1.0f }; + GLfloat LightPosition[] = { 1.0f, 1.0f, 1.0f, 0.0f }; + + // setup directional light + glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse); + glLightfv(GL_LIGHT0, GL_POSITION, LightPosition); + glEnable(GL_LIGHT0); + + glEnable(GL_LIGHTING); +} + +void setup_opengl() { + + // Open OpenGL window + if (!glfwOpenWindow(640, 480, 0, 0, 0, 0, 0, 0, GLFW_WINDOW)) { + fprintf(stderr, "Failed to open GLFW window\n"); + glfwTerminate(); + exit(EXIT_FAILURE); + } + //glfwDisable(GLFW_MOUSE_CURSOR); + glfwSetWindowTitle("Gremlin Lan Party Game"); + // Enable sticky keys + glfwEnable(GLFW_STICKY_KEYS); + + // general settings + glShadeModel(GL_SMOOTH); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glEnable(GL_CULL_FACE); + + // setup depth buffer + glClearDepth(1.0f); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + // Enable vertical sync (on cards that support it) + glfwSwapInterval(0); +} + +void draw_team(team_t *team) { + size_t i = 0; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, team->color); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glTranslated(team->x, team->y, team->z); + gluSphere(quadratic, 50.f, 32, 32); + glPopMatrix(); +} + +void draw_player(player_t *player) { + if (player->status == 0) + return; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, player->team->color); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glTranslated(player->x, player->y, player->z); + gluSphere(quadratic, 10.f, 32, 32); + glPopMatrix(); +} + +void draw_bomb(bomb_t *bomb) { + if (bomb->status != 1) + return; + GLfloat red[] = { 1.0f, 0.0f, 0.0f, 1.0f }; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glTranslated(bomb->x, bomb->y, bomb->z); + gluSphere(quadratic, 3.f, 4, 4); + glPopMatrix(); +} +void draw_point(point_t *point) { + if (point->status == 0) + return; + GLfloat red[] = { 0.0f, 0.0f, 1.0f, 1.0f }; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glTranslated(point->x, point->y, point->z); + gluSphere(quadratic, 3.f, 12, 12); + glPopMatrix(); +} + +void setup_explosion() { + + // Loads particle texture + GLuint textures[5]; + + glGenTextures(5, textures); + + glBindTexture(GL_TEXTURE_2D, textures[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glfwLoadTexture2D("data/explosion/explosion.tga", GLFW_ALPHA_MAP_BIT); + + glBindTexture(GL_TEXTURE_2D, textures[1]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glfwLoadTexture2D("data/explosion/flash.tga", 0); + + glBindTexture(GL_TEXTURE_2D, textures[2]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glfwLoadTexture2D("data/explosion/spark.tga", 0); + + glBindTexture(GL_TEXTURE_2D, textures[3]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glfwLoadTexture2D("data/explosion/point.tga", GLFW_ALPHA_MAP_BIT); + + glBindTexture(GL_TEXTURE_2D, textures[4]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glfwLoadTexture2D("data/explosion/wave.tga", 0); + + explosion.initialize(textures[0], textures[1], textures[2], textures[3], + textures[4]); +} + +void explosion_callback(double x, double y, double z, void *data) { + explosion.add(x, y, z); +} + +GLuint wallTex = 0; + +void draw_box() { + + if (wallTex == 0) { + glGenTextures(1, &wallTex); + glBindTexture(GL_TEXTURE_2D, wallTex); + glEnable(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR); + glfwLoadTexture2D("data/wall.tga", GLFW_BUILD_MIPMAPS_BIT); + } else { + glBindTexture(GL_TEXTURE_2D, wallTex); + glEnable(GL_TEXTURE_2D); + } + + GLfloat red[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); + + // Enable/Disable features + glPushAttrib(GL_ENABLE_BIT); + glEnable(GL_TEXTURE_2D); + //glDisable( GL_DEPTH_TEST); + // glEnable( GL_LIGHTING); + // glDisable( GL_BLEND); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glTranslated(2000.0, 0.0, 0.0); + //glScaled(5000.0f, 5000.0f, 5000.0f); + float s = 3000.0f, t = 10.0f; + // Just in case we set all vertices to white. + glColor4f(1, 1, 1, 1); + + // Render the front quad + glBegin(GL_QUADS); + glTexCoord2f(0, t); + glNormal3f(0.0, 0.0, 1.0); + glVertex3f(-s, s, -s); + + glTexCoord2f(0, 0); + glNormal3f(0.0, 0.0, 1.0); + glVertex3f(-s, -s, -s); + + glTexCoord2f(t, 0); + glNormal3f(0.0, 0.0, 1.0); + glVertex3f(s, -s, -s); + + glTexCoord2f(t, t); + glNormal3f(0.0, 0.0, 1.0); + glVertex3f(s, s, -s); + glEnd(); + + // Render the left quad + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex3f(s, -s, s); + + glTexCoord2f(0, t); + glVertex3f(s, s, s); + + glTexCoord2f(t, t); + glVertex3f(s, s, -s); + + glTexCoord2f(t, 0); + glVertex3f(s, -s, -s); + glEnd(); + + // Render the back quad + // glBindTexture(GL_TEXTURE_2D, _skybox[2]); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex3f(-s, -s, s); + glTexCoord2f(0, t); + glVertex3f(-s, s, s); + glTexCoord2f(t, t); + glVertex3f(s, s, s); + glTexCoord2f(t, 0); + glVertex3f(s, -s, s); + + glEnd(); + + // Render the right quad + // glBindTexture(GL_TEXTURE_2D, _skybox[3]); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex3f(-s, -s, -s); + glTexCoord2f(0, t); + glVertex3f(-s, s, -s); + glTexCoord2f(t, t); + glVertex3f(-s, s, s); + glTexCoord2f(t, 0); + glVertex3f(-s, -s, s); + glEnd(); + + // Render the top quad + //glBindTexture(GL_TEXTURE_2D, _skybox[4]); + glBegin(GL_QUADS); + glTexCoord2f(0, t); + glVertex3f(-s, s, -s); + + glTexCoord2f(t, t); + glVertex3f(s, s, -s); + + glTexCoord2f(t, 0); + glVertex3f(s, s, s); + + glTexCoord2f(0, 0); + glVertex3f(-s, s, s); + + glEnd(); + + // Render the bottom quad + //glBindTexture(GL_TEXTURE_2D, _skybox[5]); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex3f(-s, -s, -s); + glTexCoord2f(0, t); + glVertex3f(-s, -s, s); + glTexCoord2f(t, t); + glVertex3f(s, -s, s); + glTexCoord2f(t, 0); + glVertex3f(s, -s, -s); + glEnd(); + + // Restore enable bits and matrix + glPopAttrib(); + glPopMatrix(); +} + +void Client::accelerate(double x, double y, double z) { + if (game.local_player == 0) + return; + player_accelerate_message_t msg; + msg.msg_id = MESSAGE_PLAYER_ACCELERATE; + msg.player_id = game.local_player->id; + msg.x = x; + msg.y = y; + msg.z = z; + send_message((uint8_t*) &msg, sizeof(msg), &game); +} + +void Client::drop_bomb(double rx, double ry, double rz, double ttl) { + bomb_drop_meesage_t msg; + msg.msg_id = MESSAGE_BOMB_DROP; + msg.x = game.local_player->x + rx * 20; + msg.y = game.local_player->y + ry * 20; + msg.z = game.local_player->z + rz * 20; + msg.vx = game.local_player->vx + rx * 100; + msg.vy = game.local_player->vy + ry * 100; + msg.vz = game.local_player->vz + rz * 100; + msg.ttl = ttl; + send_message((uint8_t*) &msg, sizeof(msg), &game); +} + +void Client::loadConsoleFont() { + GLuint font_id = 0; + + glGenTextures(1, &font_id); + glBindTexture(GL_TEXTURE_2D, font_id); + + // Set texture parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + // Upload texture from file to texture memory + glfwLoadTexture2D("data/fonts/console.tga", 0); + oglf_load(&font, "data/fonts/console.fnt", font_id); +} + +void Client::prepareFrame(double rx, double ry, double rz) { + // Get window size (may be different than the requested size) + glfwGetWindowSize(&width, &height); + height = height > 0 ? height : 1; + + // Set viewport + glViewport(0, 0, width, height); + + // Clear color buffer + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Select and setup the projection matrix + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(60.0f, (GLfloat) width / (GLfloat) height, 1.0f, 10000.0f); + + // Select and setup the modelview matrix + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(camX, camY, camZ, camX + rx * 10.0f, camY + ry * 10.0f, camZ + rz + * 10.0f, 0.0f, 1.0f, 0.0f); + +} + +void Client::initialize(int argc, char ** argv) { + Application::initialize(argc, argv); + double time, last_player_update; + + std::string arg1; + if (argc > 1) { + arg1 = argv[1]; + if (arg1 == "server") { + setMaster(true); + } else { + setMaster(false); + } + } else { + setMaster(false); + arg1 = "forge.camijo.de"; + } + + // Initialise GLFW + if (!glfwInit()) { + fprintf(stderr, "Failed to initialize GLFW\n"); + exit(EXIT_FAILURE); + } + + + game_setup_explosion_callback(&game, explosion_callback, 0); + setup_opengl(); + setup_explosion(); + quadratic = gluNewQuadric(); + gluQuadricNormals(quadratic, GLU_SMOOTH); + gluQuadricTexture(quadratic, GL_TRUE); + + if (isMaster()) { + setup_network(NULL); + team_t *team = game_team(&game, 0); + game.local_player = game_spawn_player(&game, team); + } else { + setup_network(arg1.c_str()); + } + + size_t i; + last_bomb = time - 5.; + + glfwGetMousePos(&last_x, &last_y); + accelerate_schudule.setExact(true); + accelerate_schudule.setInterval(0.05); + + loadConsoleFont(); +} + +void Client::update() { + + Application::update(); + + int x, y; + glfwGetMousePos(&x, &y); + if (glfwGetMouseButton(GLFW_MOUSE_BUTTON_2) == GLFW_PRESS) { + phi += (x - last_x) * 0.01; + theta += (y - last_y) * -0.01; + if (theta > 1.5) + theta = 1.5; + if (theta < -1.5) + theta = -1.5; + } + last_x = x; + last_y = y; + double rx = cos(phi) * cos(theta); + double ry = sin(theta); + double rz = sin(phi) * cos(theta); + + if (accelerate_schudule.next(time)) { + double t = accelerate_schudule.getInterval(); + double v = 50.0 * t; + if (glfwGetKey('W')) { + accelerate(rx * v, ry * v, rz * v); + } else if (glfwGetKey('S')) { + accelerate(rx * -v, ry * -v, rz * -v); + } + + if (glfwGetKey('A')) { + accelerate(rz * v, 0, -rx * v); + } else if (glfwGetKey('D')) { + accelerate(-rz * v, 0, rx * v); + } + + if (glfwGetKey(GLFW_KEY_SPACE)) { + accelerate(game.local_player->vx * -0.1, game.local_player->vy + * -0.1, game.local_player->vz * -0.1); + } + } + if (glfwGetKey(GLFW_KEY_LCTRL)) { + if (time - last_bomb > 1.0) { + last_bomb = time; + drop_bomb(rx, ry, rz, 5.0); + } + } + + if (game.local_player) { + camX = game.local_player->x; + camY = game.local_player->y; + camZ = game.local_player->z; + } else { + camX = 1000.0; + camY = 1000.0; + camZ = 1000.0; + } + prepareFrame(rx, ry, rz); + setup_light(); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHTING); + glEnable(GL_CULL_FACE); + glDisable(GL_TEXTURE_2D); + for (size_t i = 0; i < GAME_TEAM_COUNT; i++) + draw_team(&game.team[i]); + + for (size_t i = 0; i < GAME_PLAYER_COUNT; i++) + draw_player(&game.player[i]); + + for (size_t i = 0; i < GAME_BOMB_COUNT; i++) + draw_bomb(&game.bomb[i]); + + for (size_t i = 0; i < GAME_POINT_COUNT; i++) + draw_point(&game.point[i]); + + draw_box(); + + glDisable(GL_LIGHT0); + glDisable(GL_LIGHTING); + glDisable(GL_CULL_FACE); + explosion.update(dt * 1000.0, camX, camY, camZ); + explosion.render(); + oglf_begin(&font, width, height); + size_t fy = 1; + if (game.local_player) { + std::stringstream sstr; + sstr << "Points: " << game.local_player->points; + oglf_print(&font, 10, 25 * fy++, sstr.str().c_str()); + + } + + for (size_t i = 0; i < GAME_TEAM_COUNT; i++) { + std::stringstream sstr; + if (game.local_player && &game.team[i] == game.local_player->team) { + sstr << "Team " << i << " (yours) : " << game.team[i].points; + } else { + sstr << "Team " << i << " (other) : " << game.team[i].points; + } + oglf_print(&font, 10, 25 * fy++, sstr.str().c_str()); + } + + { + std::stringstream sstr; + sstr << "FPS: " << (int) (1 / dt) << " Time: " << round(dt * 10000.0) + / 10.0; + oglf_print(&font, 10, 25 * fy++, sstr.str().c_str()); + } + + oglf_end(); + + // Swap buffers + glfwSwapBuffers(); + + // Check if the ESC key was pressed or the window was closed + if (glfwGetKey(GLFW_KEY_ESC)) + stop(); + + if (glfwGetWindowParam(GLFW_OPENED) != GL_TRUE) + stop(); +} + +void Client::shutdown() { + + Application::shutdown(); + + gluDeleteQuadric(quadratic); + oglf_destroy(&font); + glfwTerminate(); +} diff --git a/src/Client.h b/src/Client.h new file mode 100644 index 0000000..6e6c260 --- /dev/null +++ b/src/Client.h @@ -0,0 +1,37 @@ +/* + * Client.h + * + * Created on: 14.01.2011 + * Author: gmueller + */ + +#ifndef CLIENT_H_ +#define CLIENT_H_ + +#include "Application.h" +#include "Schedule.h" +#include "oglfont.h" +#include "game.h" + +class Client: public Application { +public: + void initialize(int argc, char ** argv); + void update(); + void shutdown(); +private: + double last_bomb; //TODO: use bomb schedule; + int last_x, last_y; + double phi, theta; + double camX, camY, camZ; + Schedule accelerate_schudule; + int width, height; + //TrueTyeFont font; + oglf_font_t font; + + void prepareFrame(double rx, double ry, double rz); + void accelerate(double x, double y, double z); + void drop_bomb(double rx, double ry, double rz, double ttl); + void loadConsoleFont(); +}; + +#endif /* CLIENT_H_ */ diff --git a/src/game.cpp b/src/game.cpp index b58a736..67dcf41 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -9,6 +9,32 @@ double rand2() { return 2.0 * (u - 0.5); } +void game_reset_team(team_t *team) { + team->points = 0; +} + +void game_reset_player(player_t *player) { + if (player->team) { + player->x = player->team->x + 100; + player->y = player->team->y; + player->z = player->team->z; + } else { + player->x = 0; + player->y = 0; + player->z = 0; + } + player->vx = 0.; + player->vy = 0.; + player->vz = 0.; +} + +void game_reset_point(point_t *point) { + point->status = 1; + point->x = 1000 + 500.0 * rand2(); + point->y = 500.0 * rand2(); + point->z = 500.0 * rand2(); +} + void game_setup_team(team_t *team, uint8_t id) { team->id = id; team->color[0] = .5f + .5f * (id & (1 << 0)); @@ -28,34 +54,6 @@ void game_setup_player(player_t *player) { player->id = 0; player->status = 0; player->team = NULL; -} - -void game_setup_point(point_t *point) { - point->status = 1; - point->x = 1000 + 500.0 * rand2(); - point->y = 500.0 * rand2(); - point->z = 500.0 * rand2(); -} - -void game_reset_team(team_t *team, uint8_t id) { - team->id = id; - team->color[0] = 1.; - team->color[1] = 1.; - team->color[2] = 1.; - team->color[3] = 1.f; - - team->x = 0.; - team->y = 0.; - team->z = 0.; - - team->points = 0; - team->wins = 0; -} - -void game_reset_player(player_t *player) { - player->id = 0; - player->status = 0; - player->team = NULL; player->x = 0.0; player->y = 0.0; player->z = 0.0; @@ -64,50 +62,56 @@ void game_reset_player(player_t *player) { player->vz = 0.0; } -void game_reset_point(point_t *point) { +void game_setup_point(point_t *point) { point->status = 0; point->x = 0.0; point->y = 0.0; point->z = 0.0; } -void game_reset_bomb(bomb_t *bomb) { +void game_setup_bomb(bomb_t *bomb) { bomb->status = 0; bomb->x = 0.0; bomb->y = 0.0; bomb->z = 0.0; } -void game_setup(game_t *game, int master, void(*explosion_callback)(double x, - double y, double z)) { +void game_setup(game_t *game) { size_t i; + for (i = 0; i < GAME_TEAM_COUNT; i++) game_setup_team(&game->team[i], i); + for (i = 0; i < GAME_BOMB_COUNT; i++) - game_reset_bomb(&game->bomb[i]); + game_setup_bomb(&game->bomb[i]); - if (master) { + for (i = 0; i < GAME_PLAYER_COUNT; i++) + game_setup_player(&game->player[i]); - for (i = 0; i < GAME_PLAYER_COUNT; i++) - game_setup_player(&game->player[i]); + for (i = 0; i < GAME_POINT_COUNT; i++) + game_setup_point(&game->point[i]); - for (i = 0; i < GAME_POINT_COUNT; i++) - game_setup_point(&game->point[i]); - } else { - // for (i = 0; i < GAME_TEAM_COUNT; i++) - // game_reset_team(&game->team[i], i); - - for (i = 0; i < GAME_PLAYER_COUNT; i++) - game_reset_player(&game->player[i]); - - for (i = 0; i < GAME_POINT_COUNT; i++) - game_reset_point(&game->point[i]); - } - - game->explosion_callback = explosion_callback; game->max_player_id = 0; - game->master = master; + game->master = 0; game->updateTime = 0.0; + game->explosion_callback = 0; + game->local_player = 0; +} + +void game_reset(game_t *game) { + size_t i; + + for (i = 0; i < GAME_TEAM_COUNT; i++) + game_reset_team(&game->team[i]); + + for (i = 0; i < GAME_BOMB_COUNT; i++) + game_setup_bomb(&game->bomb[i]); + + for (i = 0; i < GAME_PLAYER_COUNT; i++) + game_reset_player(&game->player[i]); + + for (i = 0; i < GAME_POINT_COUNT; i++) + game_reset_point(&game->point[i]); } player_t *_game_free_player(game_t *game) { @@ -122,14 +126,9 @@ player_t *_game_free_player(game_t *game) { player_t *game_spawn_player(game_t *game, team_t *team) { player_t *player = _game_free_player(game); player->team = team; - player->id = game->max_player_id++; player->status = 1; - player->x = team->x + 100; - player->y = team->y; - player->z = team->z; - player->vx = 0.; - player->vy = 0.; - player->vz = 0.; + player->id = game->max_player_id++; + game_reset_player(player); return player; } @@ -208,7 +207,8 @@ void _explode_bomb(game_t *game, bomb_t *bomb) { - bomb->y, 2) + pow(player->z - bomb->z, 2); if (distance2 < pow(150, 2)) { if (game->explosion_callback) - game->explosion_callback(player->x, player->y, player->z); + game->explosion_callback(player->x, player->y, player->z, + game->explosion_callback_data); player->x = player->team->x + 100; player->y = player->team->y; player->z = player->team->z; @@ -260,7 +260,8 @@ void game_update_bombs(game_t *game, double dt) { if (bomb->ttl < 0) { if (bomb->status == 1) { if (game->explosion_callback) - game->explosion_callback(bomb->x, bomb->y, bomb->z); + game->explosion_callback(bomb->x, bomb->y, bomb->z, + game->explosion_callback_data); bomb->status = 2; } else if (bomb->ttl < -0.2) { if (game->master) { @@ -374,3 +375,13 @@ point_t *game_spawn_point(game_t *game) { } return NULL; } + +void game_setup_explosion_callback(game_t *game, void(*explosion_callback)( + double x, double y, double z, void *data), void *data) { + game->explosion_callback = explosion_callback; + game->explosion_callback_data = data; +} + +void game_set_master(game_t *game, int master) { + game->master = master; +} diff --git a/src/game.h b/src/game.h index 3dfae9d..a73727b 100644 --- a/src/game.h +++ b/src/game.h @@ -51,11 +51,12 @@ struct game_t { int master; double updateTime; player_t *local_player; - void(*explosion_callback)(double x, double y, double z); + void(*explosion_callback)(double x, double y, double z, void *data); + void *explosion_callback_data; }; -extern void game_setup(game_t *game, int master, void(*explosion_callback)(double x, - double y, double z)); +extern void game_setup(game_t *game); +extern void game_reset(game_t *game); extern team_t *game_team_with_least_players(game_t *game); extern player_t *game_spawn_player(game_t *game, team_t *team); extern player_t *game_spawn_player_id(game_t *game, team_t *team, uint16_t id); @@ -68,6 +69,8 @@ extern point_t *game_spawn_point(game_t *game); extern void game_update_bombs(game_t *game, double dt); extern void game_update_points(game_t *game, double dt); extern void game_update(game_t *game, double dt); - - +extern void game_setup_explosion_callback(game_t *game, + void(*explosion_callback)(double x, double y, double z, void *data), + void *data); +extern void game_set_master(game_t *game, int master); #endif diff --git a/src/main.cpp b/src/main.cpp index e5f9cd4..5b400cb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,587 +1,29 @@ -#include -#include -#include -#include +#include "Client.h" -#include -#include -#include +#include -#include "common.h" -#include "game.h" -#include "Explosion.h" -#include "Schedule.h" -#include "oglfont.h" -#include "Time.h" -#include "network.h" - -GLUquadricObj *quadratic; -Explosion explosion; - -void key_callback(int key, int state) { - -} - -void setup_light() { - GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f }; - GLfloat LightDiffuse[] = { 0.5f, 0.5f, 0.5f, 1.0f }; - GLfloat LightPosition[] = { 1.0f, 1.0f, 1.0f, 0.0f }; - - // setup directional light - glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient); - glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse); - glLightfv(GL_LIGHT0, GL_POSITION, LightPosition); - glEnable( GL_LIGHT0); - - glEnable( GL_LIGHTING); -} - -void setup_opengl() { - - // Open OpenGL window - if (!glfwOpenWindow(640, 480, 0, 0, 0, 0, 0, 0, GLFW_WINDOW)) { - fprintf(stderr, "Failed to open GLFW window\n"); - glfwTerminate(); - exit(EXIT_FAILURE); - } - //glfwDisable(GLFW_MOUSE_CURSOR); - glfwSetWindowTitle("Gremlin Lan Party Game"); - glfwSetKeyCallback(key_callback); - // Enable sticky keys - glfwEnable(GLFW_STICKY_KEYS); - - // general settings - glShadeModel( GL_SMOOTH); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - glEnable( GL_CULL_FACE); - - // setup depth buffer - glClearDepth(1.0f); - glEnable( GL_DEPTH_TEST); - glDepthFunc( GL_LEQUAL); - - // Enable vertical sync (on cards that support it) - glfwSwapInterval(0); -} - -void draw_team(team_t *team) { - size_t i = 0; - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, team->color); - glMatrixMode( GL_MODELVIEW); - glPushMatrix(); - glTranslated(team->x, team->y, team->z); - gluSphere(quadratic, 50.f, 32, 32); - glPopMatrix(); -} - -void draw_player(player_t *player) { - if (player->status == 0) - return; - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, player->team->color); - glMatrixMode( GL_MODELVIEW); - glPushMatrix(); - glTranslated(player->x, player->y, player->z); - gluSphere(quadratic, 10.f, 32, 32); - glPopMatrix(); -} - -void draw_bomb(bomb_t *bomb) { - if (bomb->status != 1) - return; - GLfloat red[] = { 1.0f, 0.0f, 0.0f, 1.0f }; - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); - glMatrixMode( GL_MODELVIEW); - glPushMatrix(); - glTranslated(bomb->x, bomb->y, bomb->z); - gluSphere(quadratic, 3.f, 4, 4); - glPopMatrix(); -} -void draw_point(point_t *point) { - if (point->status == 0) - return; - GLfloat red[] = { 0.0f, 0.0f, 1.0f, 1.0f }; - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); - glMatrixMode( GL_MODELVIEW); - glPushMatrix(); - glTranslated(point->x, point->y, point->z); - gluSphere(quadratic, 3.f, 12, 12); - glPopMatrix(); -} - -void setup_explosion() { - - // Loads particle texture - GLuint textures[5]; - - glGenTextures(5, textures); - - glBindTexture(GL_TEXTURE_2D, textures[0]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glfwLoadTexture2D("data/explosion/explosion.tga", GLFW_ALPHA_MAP_BIT); - - glBindTexture(GL_TEXTURE_2D, textures[1]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glfwLoadTexture2D("data/explosion/flash.tga", 0); - - glBindTexture(GL_TEXTURE_2D, textures[2]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glfwLoadTexture2D("data/explosion/spark.tga", 0); - - glBindTexture(GL_TEXTURE_2D, textures[3]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glfwLoadTexture2D("data/explosion/point.tga", GLFW_ALPHA_MAP_BIT); - - glBindTexture(GL_TEXTURE_2D, textures[4]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glfwLoadTexture2D("data/explosion/wave.tga", 0); - - explosion.initialize(textures[0], textures[1], textures[2], textures[3], - textures[4]); -} - -void explosion_callback(double x, double y, double z) { - explosion.add(x, y, z); -} - -GLuint wallTex = 0; - -void draw_box() { - - if (wallTex == 0) { - glGenTextures(1, &wallTex); - glBindTexture(GL_TEXTURE_2D, wallTex); - glEnable( GL_TEXTURE_2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glfwLoadTexture2D("data/wall.tga", GLFW_BUILD_MIPMAPS_BIT); - } else { - glBindTexture(GL_TEXTURE_2D, wallTex); - glEnable( GL_TEXTURE_2D); - } - - GLfloat red[] = { 1.0f, 1.0f, 1.0f, 1.0f }; - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); - - // Enable/Disable features - glPushAttrib( GL_ENABLE_BIT); - glEnable( GL_TEXTURE_2D); - //glDisable( GL_DEPTH_TEST); - // glEnable( GL_LIGHTING); - // glDisable( GL_BLEND); - glMatrixMode( GL_MODELVIEW); - glPushMatrix(); - glTranslated(2000.0, 0.0, 0.0); - //glScaled(5000.0f, 5000.0f, 5000.0f); - float s = 3000.0f, t = 10.0f; - // Just in case we set all vertices to white. - glColor4f(1, 1, 1, 1); - - // Render the front quad - glBegin( GL_QUADS); - glTexCoord2f(0, t); - glNormal3f(0.0, 0.0, 1.0); - glVertex3f(-s, s, -s); - - glTexCoord2f(0, 0); - glNormal3f(0.0, 0.0, 1.0); - glVertex3f(-s, -s, -s); - - glTexCoord2f(t, 0); - glNormal3f(0.0, 0.0, 1.0); - glVertex3f(s, -s, -s); - - glTexCoord2f(t, t); - glNormal3f(0.0, 0.0, 1.0); - glVertex3f(s, s, -s); - glEnd(); - - // Render the left quad - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex3f(s, -s, s); - - glTexCoord2f(0, t); - glVertex3f(s, s, s); - - glTexCoord2f(t, t); - glVertex3f(s, s, -s); - - glTexCoord2f(t, 0); - glVertex3f(s, -s, -s); - glEnd(); - - // Render the back quad - // glBindTexture(GL_TEXTURE_2D, _skybox[2]); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex3f(-s, -s, s); - glTexCoord2f(0, t); - glVertex3f(-s, s, s); - glTexCoord2f(t, t); - glVertex3f(s, s, s); - glTexCoord2f(t, 0); - glVertex3f(s, -s, s); - - glEnd(); - - // Render the right quad - // glBindTexture(GL_TEXTURE_2D, _skybox[3]); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex3f(-s, -s, -s); - glTexCoord2f(0, t); - glVertex3f(-s, s, -s); - glTexCoord2f(t, t); - glVertex3f(-s, s, s); - glTexCoord2f(t, 0); - glVertex3f(-s, -s, s); - glEnd(); - - // Render the top quad - //glBindTexture(GL_TEXTURE_2D, _skybox[4]); - glBegin(GL_QUADS); - glTexCoord2f(0, t); - glVertex3f(-s, s, -s); - - glTexCoord2f(t, t); - glVertex3f(s, s, -s); - - glTexCoord2f(t, 0); - glVertex3f(s, s, s); - - glTexCoord2f(0, 0); - glVertex3f(-s, s, s); - - glEnd(); - - // Render the bottom quad - //glBindTexture(GL_TEXTURE_2D, _skybox[5]); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex3f(-s, -s, -s); - glTexCoord2f(0, t); - glVertex3f(-s, -s, s); - glTexCoord2f(t, t); - glVertex3f(s, -s, s); - glTexCoord2f(t, 0); - glVertex3f(s, -s, -s); - glEnd(); - - // Restore enable bits and matrix - glPopAttrib(); - glPopMatrix(); -} - -class Application { +class Server : public Application { public: - void initialize(int argc, char ** argv); - void update(); - void shutdown(); - bool isRunning(); -private: - bool running; - double last_time, last_bomb; //TODO: use bomb schedule; - int last_x, last_y; - double phi, theta; - double camX, camY, camZ; - Schedule accelerate_schudule; - Schedule game_update_schudule; - game_t game; - int server; - int width, height; - //TrueTyeFont font; - oglf_font_t font; - - void prepareFrame(double rx, double ry, double rz); - void accelerate(double x, double y, double z); - void drop_bomb(double rx, double ry, double rz, double ttl); - void loadConsoleFont(); + virtual void initialize(int argc, char ** argv) { + Application::initialize(argc, argv); + setMaster(true); + } }; -void Application::accelerate(double x, double y, double z) { - if (game.local_player == 0) - return; - player_accelerate_message_t msg; - msg.msg_id = MESSAGE_PLAYER_ACCELERATE; - msg.player_id = game.local_player->id; - msg.x = x; - msg.y = y; - msg.z = z; - send_message((uint8_t*) &msg, sizeof(msg), &game); -} - -void Application::drop_bomb(double rx, double ry, double rz, double ttl) { - bomb_drop_meesage_t msg; - msg.msg_id = MESSAGE_BOMB_DROP; - msg.x = game.local_player->x + rx * 20; - msg.y = game.local_player->y + ry * 20; - msg.z = game.local_player->z + rz * 20; - msg.vx = game.local_player->vx + rx * 100; - msg.vy = game.local_player->vy + ry * 100; - msg.vz = game.local_player->vz + rz * 100; - msg.ttl = ttl; - send_message((uint8_t*) &msg, sizeof(msg), &game); -} - -void Application::loadConsoleFont() { - GLuint font_id = 0; - - glGenTextures(1, &font_id); - glBindTexture(GL_TEXTURE_2D, font_id); - - // Set texture parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - // Upload texture from file to texture memory - glfwLoadTexture2D("data/fonts/console.tga", 0); - oglf_load(&font, "data/fonts/console.fnt", font_id); -} - -void Application::prepareFrame(double rx, double ry, double rz) { - // Get window size (may be different than the requested size) - glfwGetWindowSize(&width, &height); - height = height > 0 ? height : 1; - - // Set viewport - glViewport(0, 0, width, height); - - // Clear color buffer - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // Select and setup the projection matrix - glMatrixMode( GL_PROJECTION); - glLoadIdentity(); - gluPerspective(60.0f, (GLfloat) width / (GLfloat) height, 1.0f, 10000.0f); - - // Select and setup the modelview matrix - glMatrixMode( GL_MODELVIEW); - glLoadIdentity(); - gluLookAt(camX, camY, camZ, camX + rx * 10.0f, camY + ry * 10.0f, camZ + rz - * 10.0f, 0.0f, 1.0f, 0.0f); - -} - -void Application::initialize(int argc, char ** argv) { - server = 0; - double time, last_player_update; - - std::string arg1; - if (argc > 1) { - arg1 = argv[1]; - if (arg1 == "server") { - server = 1; - } else { - server = 0; - } - } else { - server = 0; - arg1 = "forge.camijo.de"; - } - - // Initialise GLFW - if (!glfwInit()) { - fprintf(stderr, "Failed to initialize GLFW\n"); - exit(EXIT_FAILURE); - } - - game_setup(&game, server, explosion_callback); - - setup_opengl(); - setup_explosion(); - quadratic = gluNewQuadric(); - gluQuadricNormals(quadratic, GLU_SMOOTH); - gluQuadricTexture(quadratic, GL_TRUE); - - if (server) { - setup_network(NULL); - team_t *team = game_team(&game, 0); - game.local_player = game_spawn_player(&game, team); - } else { - setup_network(arg1.c_str()); - } - - size_t i; - running = GL_TRUE; - last_time = PerformanceTimer::get(); - last_player_update = last_time; - last_bomb = last_time - 5.; - - glfwGetMousePos(&last_x, &last_y); - accelerate_schudule.setExact(true); - accelerate_schudule.setInterval(0.05); - - game_update_schudule.setExact(true); - game_update_schudule.setInterval(0.05); - - loadConsoleFont(); -} - -void Application::update() { - - // Get time and mouse position - double time = PerformanceTimer::get(); - double dt = time - last_time; - - int x, y; - glfwGetMousePos(&x, &y); - if (glfwGetMouseButton(GLFW_MOUSE_BUTTON_2) == GLFW_PRESS) { - phi += (x - last_x) * 0.01; - theta += (y - last_y) * -0.01; - if (theta > 1.5) - theta = 1.5; - if (theta < -1.5) - theta = -1.5; - } - last_x = x; - last_y = y; - double rx = cos(phi) * cos(theta); - double ry = sin(theta); - double rz = sin(phi) * cos(theta); - service_network(&game); - game_update(&game, dt); - if (server && game_update_schudule.next(time)) { - send_game_updates(&game); - } - - if (accelerate_schudule.next(time)) { - double t = accelerate_schudule.getInterval(); - double v = 50.0 * t; - if (glfwGetKey('W')) { - accelerate(rx * v, ry * v, rz * v); - } else if (glfwGetKey('S')) { - accelerate(rx * -v, ry * -v, rz * -v); - } - - if (glfwGetKey('A')) { - accelerate(rz * v, 0, -rx * v); - } else if (glfwGetKey('D')) { - accelerate(-rz * v, 0, rx * v); - } - - if (glfwGetKey(GLFW_KEY_SPACE)) { - accelerate(game.local_player->vx * -0.1, game.local_player->vy - * -0.1, game.local_player->vz * -0.1); - } - } - if (glfwGetKey(GLFW_KEY_LCTRL)) { - if (time - last_bomb > 1.0) { - last_bomb = time; - drop_bomb(rx, ry, rz, 5.0); - } - } - - if (game.local_player) { - camX = game.local_player->x; - camY = game.local_player->y; - camZ = game.local_player->z; - } else { - camX = 1000.0; - camY = 1000.0; - camZ = 1000.0; - } - prepareFrame(rx, ry, rz); - setup_light(); - glEnable( GL_LIGHT0); - glEnable( GL_LIGHTING); - glEnable( GL_CULL_FACE); - glDisable( GL_TEXTURE_2D); - for (size_t i = 0; i < GAME_TEAM_COUNT; i++) - draw_team(&game.team[i]); - - for (size_t i = 0; i < GAME_PLAYER_COUNT; i++) - draw_player(&game.player[i]); - - for (size_t i = 0; i < GAME_BOMB_COUNT; i++) - draw_bomb(&game.bomb[i]); - - for (size_t i = 0; i < GAME_POINT_COUNT; i++) - draw_point(&game.point[i]); - - draw_box(); - - glDisable(GL_LIGHT0); - glDisable(GL_LIGHTING); - glDisable(GL_CULL_FACE); - explosion.update(dt * 1000.0, camX, camY, camZ); - explosion.render(); - oglf_begin(&font, width, height); - size_t fy = 1; - if (game.local_player) { - std::stringstream sstr; - sstr << "Points: " << game.local_player->points; - oglf_print(&font, 10, 25 * fy++, sstr.str().c_str()); - - } - - for (size_t i = 0; i < GAME_TEAM_COUNT; i++) { - std::stringstream sstr; - if (game.local_player && &game.team[i] == game.local_player->team) { - sstr << "Team " << i << " (yours) : " << game.team[i].points; - } else { - sstr << "Team " << i << " (other) : " << game.team[i].points; - } - oglf_print(&font, 10, 25 * fy++, sstr.str().c_str()); - } - - { - std::stringstream sstr; - sstr << "FPS: " << (int) (1 / dt) << " Time: " << round(dt * 10000.0) - / 10.0; - oglf_print(&font, 10, 25 * fy++, sstr.str().c_str()); - } - - oglf_end(); - - // Swap buffers - glfwSwapBuffers(); - // Check if the ESC key was pressed or the window was closed - running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam(GLFW_OPENED); - - last_time = time; - -} - -void Application::shutdown() { - - gluDeleteQuadric(quadratic); - oglf_destroy(&font); - - shutdown_network(); - // Close OpenGL window and terminate GLFW - glfwTerminate(); -} - -bool Application::isRunning() { - return running; -} - int main(int argc, char ** argv) { - Application app; - app.initialize(argc, argv); - while (app.isRunning()) - app.update(); - app.shutdown(); - return 0; + try { + Client app; + app.initialize(argc, argv); + while (app.isRunning()) + app.update(); + app.shutdown(); + return 0; + } catch (const char *str) { + std::cerr << "Exception: " << str << std::endl; + return 1; + } catch (const std::exception &e) { + std::cerr << "Exception: " << e.what() << std::endl; + return 1; + } } diff --git a/src/network.cpp b/src/network.cpp index d2f1ee4..9de6a46 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -17,8 +17,7 @@ ENetPeer *client_peer = 0; void setup_network(const char *remote) { if (enet_initialize() != 0) { - fprintf(stderr, "An error occurred while initializing ENet.\n"); - exit( EXIT_FAILURE); + throw "failed to initialize enet"; } if (remote == NULL) { diff --git a/src/server.cpp b/src/server.cpp new file mode 100644 index 0000000..6a144f9 --- /dev/null +++ b/src/server.cpp @@ -0,0 +1,22 @@ +#include "Application.h" + +#include + +int main(int argc, char ** argv) { + try { + Application app; + app.setMaster(); + app.initialize(argc, argv); + while (app.isRunning()) + app.update(); + app.shutdown(); + return 0; + } catch (const char *str) { + std::cerr << "Exception: " << str << std::endl; + return 1; + } catch (const std::exception &e) { + std::cerr << "Exception: " << e.what() << std::endl; + return 1; + } +} +