#include #include #include "lephisto.h" #include "conf.h" #include "log.h" #include "physics.h" #include "opengl.h" #include "font.h" #include "ship.h" #include "pilot.h" #include "player.h" #include "input.h" #include "joystick.h" #include "space.h" #include "rng.h" #include "ai.h" #include "outfit.h" #include "pack.h" #include "weapon.h" #include "faction.h" #include "xml.h" #include "pause.h" #include "toolkit.h" #include "pilot.h" #include "sound.h" #include "spfx.h" #include "music.h" #define XML_START_ID "Start" #define START_DATA "../dat/start.xml" #define CONF_FILE "conf" #define VERSION_FILE "VERSION" #define VERSION_LEN 10 #define MINIMUM_FPS 0.5 #define FONT_SIZE 12 #define FONT_SIZE_SMALL 10 static int quit = 0; // Primary loop. unsigned int gtime = 0; // Calculate FPS and movement. static char version[VERSION_LEN]; // Just some default crap. #define DATA_NAME_LEN 25 // Max length of data name. char* data = NULL; char dataname[DATA_NAME_LEN]; int nosound = 0; int show_fps = 1; // Default - True. int max_fps = 0; int indjoystick = -1; char* namjoystick = NULL; // Prototypes. static void display_fps(const double dt); static void window_caption(void); static void data_name(void); // Update. static void fps_control(void); static void update_space(void); static void render_space(void); #ifdef WIN32 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { int argc = 0; char *argv[] = { NULL }; #else int main(int argc, char** argv) { #endif // Print the version. snprintf(version, VERSION_LEN, "%d.%d.%d", VMAJOR, VMINOR, VREV); LOG(" "APPNAME" v%s", version); // Initialize SDL for possible warnings. SDL_Init(0); // Input must be initialized for config to work. input_init(); // Set the configuration. conf_setDefaults(); // Default config values. conf_loadConfig(CONF_FILE); // Have Lua parse config. conf_parseCLI(argc, argv); // Parse CLI arguments. // Load the data basics. data_name(); LOG(" %s", dataname); DEBUG(); // Random numbers. rng_init(); if(gl_init()) { // Initializes video output. ERR("Initializing video output failed, exiting..."); SDL_Quit(); exit(EXIT_FAILURE); } // See if the data file is valid. if(pack_check(data)) { ERR("Data file '%s' not found", DATA); WARN("You can specify what data file you want to use with '-d'"); WARN("See -h or -- help for more infoamtion."); SDL_Quit(); exit(EXIT_FAILURE); } window_caption(); // OpenAL sound. if(nosound) LOG("Sound is disabled!"); else { if(sound_init()) WARN("Problem setting up sound!"); music_load("Machina"); music_play(); } // Input. if((indjoystick >= 0) || (namjoystick != NULL)) { if(joystick_init()) WARN("Error initializing joystick input"); if(namjoystick != NULL) { // Use a joystick name to find joystick. if(joystick_use(joystick_get(namjoystick))) { WARN("Failure to open any joystick, falling back to default keybinds"); input_setDefault(); } free(namjoystick); } else if(indjoystick >= 0) // Must be using an id instead. if(joystick_use(indjoystick)) { WARN("Failure to open any joystick, falling back to default keybinds"); input_setDefault(); } } // Misc. if(ai_init()) WARN("Error initializing AI"); // Misc openGL init stuff. gl_fontInit(NULL, NULL, FONT_SIZE); // Init default font size. gl_fontInit(&gl_smallFont, NULL, FONT_SIZE_SMALL); // Small font. gui_init(); // Init the GUI crap. toolkit_init(); // Init the toolkit. // Data loading. factions_load(); spfx_load(); outfit_load(); ships_load(); fleet_load(); space_load(); // Create new player. TODO: Start menu. player_new(); gtime = SDL_GetTicks(); // Init the time. // Main loop. SDL_Event event; // flushes the event loop, since I notices that when the joystick is loaded, it // creates button events that results in the player starting out accelerating. while(SDL_PollEvent(&event)); while(!quit) { // Event loop. while(SDL_PollEvent(&event)) { if(event.type == SDL_QUIT) quit = 1; // Handle quit. // Pause the game if it is unfocused. if(event.type == SDL_ACTIVEEVENT) { if(event.active.state != SDL_APPMOUSEFOCUS) { // We don't need the mouse focus. if((event.active.gain == 0) && !paused) pause(); else if((event.active.gain == 1) && paused) unpause(); } } input_handle(&event); // handles all the events the player keybinds. } sound_update(); // Do the sound stuff. glClear(GL_COLOR_BUFFER_BIT); fps_control(); // Who doesn't love FPS control? if(!paused && !toolkit) update_space(); // Update the game. render_space(); if(toolkit) toolkit_render(); SDL_GL_SwapBuffers(); } // Unload data. weapon_exit(); // Destroy all active weapons. space_exit(); // Clean up the universe!!! pilots_free(); // Free the pilots, they where locked up D: gui_free(); // Free up the gui. fleet_free(); ships_free(); outfit_free(); spfx_free(); // Remove the special effects. factions_free(); gl_freeFont(&gl_smallFont); gl_freeFont(NULL); // Exit subsystems. toolkit_exit(); // Kill the toolkit. ai_exit(); // Stop the Lua AI magicness. joystick_exit(); // Release joystick. input_exit(); // Clean up keybindings. gl_exit(); // Kills video output. sound_exit(); // Kills the sound. SDL_Quit(); // Quits SDL. // All is good. exit(EXIT_SUCCESS); } // Updates the game. static double fps_dt = 1.; static double dt = 0.; static void fps_control(void) { // dt in ms/1000. dt = (double)(SDL_GetTicks() - gtime) / 1000.; gtime = SDL_GetTicks(); if(paused) SDL_Delay(10); // Drop paused FPS to be nice to the CPU. // If the fps is limited.. if((max_fps != 0) && (dt < 1./max_fps)) { double delay = 1./max_fps - dt; SDL_Delay(delay); fps_dt += delay; // Make sure it displays the propper FPS. } } // Update the game. static void update_space(void) { weapons_update(dt); spfx_update(dt); pilots_update(dt); } // == Renders the game. ================================== // Blitting order. (layers) // // BG | Stars and planets. // | Background player stuff (planet targetting) // | Background particles. // | Back layer weapons. // X // N | NPC ships. // | Front layer weapons. // | Normal layer particles (above ships). // X // FG | Player. // | Foreground particles. // | Text and GUI. // ======================================================== static void render_space(void) { // BG. space_render(dt); planets_render(); player_renderBG(); weapons_render(WEAPON_LAYER_BG); // N. pilots_render(); weapons_render(WEAPON_LAYER_FG); spfx_render(SPFX_LAYER_BACK); // FG. player_render(); spfx_render(SPFX_LAYER_FRONT); display_fps(dt); } // Spit this out on display. static double fps = 0.; static double fps_cur = 0.; static void display_fps(const double dt) { double x, y; fps_dt += dt; fps_cur += 1.; if(fps_dt > 1.) { // Recalculate every second. fps = fps_cur / fps_dt; fps_dt = fps_cur = 0.; } x = 10.; y = (double)(gl_screen.h - 20); if(show_fps) gl_print(NULL, x, y, NULL, "%3.2f", fps); } static void data_name(void) { uint32_t bufsize; char* buf; // Check if data file is valid. if(pack_check(DATA)) { ERR("Data file '%s' not found", data); WARN("You should specify which data file to use with '-d'"); WARN("See -h or --help for more information"); SDL_Quit(); exit(EXIT_FAILURE); } // Check the version. buf = pack_readfile(DATA, VERSION_FILE, &bufsize); if(strncmp(buf, version, bufsize) != 0) { WARN("Lephisto version and data module version differ!"); WARN("Lephisto is v%s, data is for v%s", version, buf); } free(buf); // Load the datafiles name. buf = pack_readfile(DATA, START_DATA, &bufsize); xmlNodePtr node; xmlDocPtr doc = xmlParseMemory(buf, bufsize); node = doc->xmlChildrenNode; if(!xml_isNode(node, XML_START_ID)) { ERR("Maformed '"START_DATA"' file: missing root element '"XML_START_ID"'"); return; } node = node->xmlChildrenNode; // First node. if(node == NULL) { ERR("Malformed '"START_DATA"' file: does not contain elements"); return; } do { if(xml_isNode(node, "name")) strncpy(dataname, xml_get(node), DATA_NAME_LEN); } while((node = node->next)); xmlFreeDoc(doc); free(buf); xmlCleanupParser(); } static void window_caption(void) { char tmp[DATA_NAME_LEN+10]; snprintf(tmp, DATA_NAME_LEN+10, APPNAME" - %s", dataname); SDL_WM_SetCaption(tmp, NULL); }