Lephisto/src/lephisto.c

369 lines
8.9 KiB
C

#include <SDL.h>
#include <string.h>
#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?
toolkit_update(); // Simulate key repetition.
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) {
if(dt > 1./30.) {
// Slow timers down and re-run calculations.
pause_delay((unsigned int)dt*1000.);
return;
}
space_update(dt);
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);
}