#include "GLee/GLee.h"
#include <GL/glu.h>
#include <SDL/SDL.h>
#include <SDL/SDL_net.h>
#include <time.h>
#include <stdlib.h>
#include <iostream>
#include <signal.h>
#include <FTGL/ftgl.h>
using namespace std;
#include "game/engine.h"
#include "globals.h"
#include "types.h"
int width;
int height;
int desktopAspect[2];
int mapX, mapY;
GLuint texture = 0;
float fps = 0;
const SDL_VideoInfo* video;
FTGLPixmapFont *textFont;
float FLEET_SPEED = FLEET_SPEED_DEFAULT;
float PRODUCTION_SPEED = PRODUCTION_SPEED_DEFAULT;
Uint8 NUM_PLANET_TEXTURES = 0;
Uint8 NUM_PLANET_NAMES = 0;
Engine *engine;
void drawFrame();
void initSDL();
void quit(int a=0);
void setupGL();
BITMAPINFOHEADER_U *readBitmap(const char *filename);
GLuint loadTexture(const char *filename);
GLuint loadTexture(BITMAPINFOHEADER_U *bitmap);
void ReduceFraction(int &Num, int &Denom);
int main(int argc, char **argv) {
signal(SIGABRT, quit);
signal(SIGTERM, quit);
srand( time( NULL ) );
engine = NULL;
initSDL();
setupGL();
engine = new Engine();
engine->run();
quit(EXIT_SUCCESS);
return 0;
}
void initSDL() {
printf("Initializing SDL...\n");
/* Initialize SDL video subsystem */
if((SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)) {
printf("Could not initialize SDL: %s.\n", SDL_GetError());
exit(EXIT_FAILURE);
}
printf("SDL initialized...\n\n");
atexit(SDL_Quit);
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_EnableUNICODE(true);
SDL_WM_SetCaption("Solism","SOLISM");
video = SDL_GetVideoInfo();
if( video == NULL ) {
fprintf(stderr, "Couldn't get video information: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
desktopAspect[0] = video->current_w;
desktopAspect[1] = video->current_h;
ReduceFraction(desktopAspect[0], desktopAspect[1]);
if(desktopAspect[0] == 4 && desktopAspect[1] == 3) {
width = 1024;
height = 768;
} else if(desktopAspect[0] == 16 && desktopAspect[1] == 9) {
width = 1280;
height = 720;
} else {
width = 1024;
height = 768;
}
if( SDL_SetVideoMode( width, height, video->vfmt->BitsPerPixel, SDL_DOUBLEBUF | SDL_OPENGL | SDL_HWSURFACE | SDL_RESIZABLE) == 0 ) {
fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
}
void quit(int status) {
if(engine != NULL)
delete engine;
delete textFont;
printf("\nQuitting SDL...\n");
SDL_Quit();
printf("Exiting...\n");
exit(status);
}
void setupGL() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float aspect = (float)width / (float)height;
gluPerspective(60.0, aspect, 0.1, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0., 0. ,0., 0.);
glEnable (GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glEnable (GL_TEXTURE_2D);
glEnable (GL_VERTEX_ARRAY);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Create a pixmap font for regular text
textFont = new FTGLPixmapFont("resources/fonts/DejaVuSans-Bold.ttf");
if(textFont->Error()) { //Error
cout << "Cannot load font file: resources/fonts/DejaVuSans-Bold.ttf" << endl;
quit(EXIT_FAILURE);
}
}
/**
Create a new texture from the given bitmap file.
**/
GLuint loadTexture(const char *filename) {
BITMAPINFOHEADER_U *bitmap = readBitmap(filename);
return loadTexture(bitmap);
}
/**
Create a new texture from the given bitmap data.
**/
GLuint loadTexture(BITMAPINFOHEADER_U *bitmap) {
if(bitmap == NULL) return 0;
glBindTexture(GL_TEXTURE_2D, ++texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
if(bitmap->biBitCount == 24) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmap->biWidth, bitmap->biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmap->data);
} else if (bitmap->biBitCount == 32) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->biWidth, bitmap->biHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap->data);
}
free(bitmap->data); //Free memory as texture has been uploaded to the gpu
free(bitmap);
return texture;
}
/**
Reads a bitmap file and retrieves the relevant header info and the raw pixel data.
**/
BITMAPINFOHEADER_U *readBitmap(const char *filename) {
FILE *file;
char tmp;
long i;
int Bpp, offset;
BITMAPINFOHEADER_U *raw = (BITMAPINFOHEADER_U *)malloc(sizeof(BITMAPINFOHEADER_U));
file = fopen(filename, "rb");
if(file==NULL) {
cout << "Cannot open texture file: " << filename << endl;
return NULL;
}
fseek(file, 10, SEEK_CUR); //Skip to pixel offset
fread(&offset, sizeof(int), 1, file); //Read pixel offset
fseek(file, 4, SEEK_CUR); //Skip to width and height
fread(&raw->biWidth, sizeof(int), 1, file); //Read width
fread(&raw->biHeight, sizeof(int), 1, file); //Read height
fread(&raw->biPlanes, sizeof(short int), 1, file);
if (raw->biPlanes != 1) { //Only legal value (why check?)
cout << "Error: too many/few planes in texture file." << endl;
return NULL;
}
fread(&raw->biBitCount, sizeof(unsigned short int), 1, file); //Read the pixel depth
if (raw->biBitCount != 8 && raw->biBitCount != 24 && raw->biBitCount != 32) { //These are the only depths we support
cout << "Error: Bpp not 8, 24 or 32 in texture file." << endl;
return NULL;
}
Bpp = raw->biBitCount/8; //Get bytes per pixel (or colour values per pixel (I, RGB or RGBA)
fseek(file, offset, SEEK_SET); //Skip to data at offset
raw->data = (unsigned char *) malloc(raw->biWidth * raw->biHeight * Bpp); //Allocate memory
if (raw->data == NULL) { //Exit if out of memory
cout << "Error allocating memory." << endl;
return NULL;
}
if ((i = fread(raw->data, raw->biWidth * raw->biHeight * Bpp, 1, file)) != 1) { //Exit if the file cannot be read
cout << "Error reading image data from texture file." << endl;
free(raw->data); //Free memory from previous allocation
return NULL;
}
if(raw->biBitCount != 8)
for (i=0; i<(raw->biWidth * raw->biHeight * Bpp); i+=Bpp) { //Mirror the colour info from BGR(A) to RGB(A)
tmp = raw->data[i];
raw->data[i] = raw->data[i+2];
raw->data[i+2] = tmp;
}
fclose(file); //Close file
return raw;
}
unsigned int manhattanDistance(Pointi a, Pointi b) {
return (unsigned int)sqrt(pow((double)abs(a.x - b.x), 2) + pow((double)abs(a.y - b.y), 2));
}
/**
Reduces a fraction.
from: http://www.cplusplus.com/src/
**/
void ReduceFraction(int &Num, int &Denom) {
int a = 0;
int b = 0;
int i = 0;
a = Denom;
b = Num;
for (i = 50; i > 1; i--)
{
if ((a % i == 0) && (b % i == 0))
{
a /= i;
b /= i;
}
}
Denom = a;
Num = b;
}