369 lines
8.9 KiB
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);
|
|
}
|
|
|