Lephisto/src/main.c
2013-02-03 14:44:03 +00:00

281 lines
7.1 KiB
C

#include <SDL.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <unistd.h>
#include <string.h>
#include "def.h"
#include "log.h"
#include "physics.h"
#include "opengl.h"
#include "ship.h"
#include "pilot.h"
#include "player.h"
#include "joystick.h"
#include "space.h"
#include "rng.h"
#include "ai.h"
#include "pilot.h"
#define WINDOW_CAPTION "Lephisto"
#define CONF_FILE "conf"
#define MINIMUM_FPS 0.5
extern const char* keybindNames[]; // Keybindings.
static int quit = 0; // Primary loop.
static unsigned int time = 0; // Calculate FPS and movement.
// Prototypes.
static void print_usage(char** argv);
static void display_fps(const double dt);
// Update.
static void update_all(void);
// Usage.
static void print_usage(char** argv) {
LOG("USAGE: %s [-f] [-j n | -J s] [-hv]", argv[0]);
LOG("Options are:");
LOG("\t-f - Fullscreen");
LOG("\t-w n - Set width to (n)");
LOG("\t-h n - Set height to (n)");
LOG("\t-j n - Use joystick (n)");
LOG("\t-J s - Use joystick whose name contains (s)");
LOG("\t-h - Display this message and exit.");
LOG("\t-v - Print the version and exit");
}
int main(int argc, char** argv) {
int i;
// Initialize SDL for possible warnings.
SDL_Init(0);
// Default values..
gl_screen.w = 800;
gl_screen.h = 640;
gl_screen.fullscreen = 0;
// Joystick.
int indjoystick = -1;
char* namjoystick = NULL;
// input.
input_init();
input_setKeybind("accel", KEYBIND_KEYBOARD, SDLK_w, 0);
input_setKeybind("left", KEYBIND_KEYBOARD, SDLK_a, 0);
input_setKeybind("right", KEYBIND_KEYBOARD, SDLK_d, 0);
// Use Lua to parse configuration file.
lua_State* L = luaL_newstate();
if(luaL_dofile(L, CONF_FILE) == 0) { // Conf file exists.
// OpenGL properties.
lua_getglobal(L, "width");
if(lua_isnumber(L, -1))
gl_screen.w = (int)lua_tonumber(L, -1);
lua_getglobal(L, "height");
if(lua_isnumber(L, -1))
gl_screen.h = (int)lua_tonumber(L, -1);
lua_getglobal(L, "fullscreen");
if(lua_isnumber(L, -1))
if((int)lua_tonumber(L, -1) == 1)
gl_screen.fullscreen = 1;
// Joystick.
lua_getglobal(L, "joystick");
if(lua_isnumber(L, -1))
indjoystick = (int)lua_tonumber(L, -1);
else if(lua_isstring(L, -1))
namjoystick = strdup((char*)lua_tostring(L, -1));
// Grab the keybindings if there are any.
char* str;
int type, key, reverse;
for(i = 0; keybindNames[i]; i++) {
lua_getglobal(L, keybindNames[i]);
str = NULL;
key = -1;
reverse = 0;
if(lua_istable(L, -1)) { // It's a table alright.
// Get the event type.
lua_pushstring(L, "type");
lua_gettable(L, -2);
if(lua_isstring(L, -1))
str = (char*)lua_tostring(L, -1);
// Get the key.
lua_pushstring(L, "key");
lua_gettable(L, -3);
if(lua_isnumber(L, -1))
key = (int)lua_tonumber(L, -1);
// Is it reversed? Only useful for axis.
lua_pushstring(L, "reverse");
lua_gettable(L, -4);
if(lua_isnumber(L, -1))
reverse = 1;
if(key != -1 && str != NULL) { // Keybind is valid!
// Get the type.
if(strcmp(str, "null")==0) type = KEYBIND_NULL;
else if(strcmp(str, "keyboard")==0) type = KEYBIND_KEYBOARD;
else if(strcmp(str, "jaxis")==0) type = KEYBIND_JAXIS;
else if(strcmp(str, "jbutton")==0) type = KEYBIND_JBUTTON;
else {
WARN("Unknown keybinding of type %s", str);
continue;
}
// Set the keybind.
input_setKeybind((char*)keybindNames[i], type, key, reverse);
} else WARN("Malformed keybind in %s", CONF_FILE);
}
}
}
lua_close(L);
// Parse arguments.
int c = 0;
while((c = getopt(argc, argv, "fJ:j:hv")) != -1) {
switch(c) {
case 'f':
gl_screen.fullscreen = 1;
break;
case 'j':
indjoystick = atoi(optarg);
break;
case 'J':
namjoystick = strdup(optarg);
break;
case 'v':
LOG("Lephisto: version %d.%d.%d\n", VMAJOR, VMINOR, VREV);
case 'h':
print_usage(argv);
exit(EXIT_SUCCESS);
}
}
// Random numbers.
rng_init();
if(gl_init()) {
// Initializes video output.
WARN("Error initializing video output, exiting...");
exit(EXIT_FAILURE);
}
// Window.
SDL_WM_SetCaption(WINDOW_CAPTION, NULL);
// Input.
if(indjoystick >= 0 || namjoystick != NULL) {
if(joystick_init())
WARN("Error initializing joystick input");
if(namjoystick != NULL) {
joystick_use(joystick_get(namjoystick));
free(namjoystick);
}
else if(indjoystick >= 0)
joystick_use(indjoystick);
}
// Misc.
if(ai_init())
WARN("Error initializing AI");
gl_fontInit(NULL, "../gfx/fonts/FreeSans.ttf", 16);
// Data loading.
ships_load();
// Testing.
pilot_create(get_ship("Ship"), "Player", NULL, NULL, PILOT_PLAYER);
gl_bindCamera(&player->solid->pos);
space_init();
pilot_create(get_ship("Miss. Test"), NULL, NULL, NULL, 0);
time = SDL_GetTicks();
// Main looops.
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.
input_handle(&event); // handles all the events the player keybinds.
}
update_all();
}
// Unload data.
space_exit(); // Clean up the universe!!!
pilots_free(); // Free the pilots, they where locked up D:
ships_free();
gl_freeFont(NULL);
// Exit subsystems.
ai_exit(); // Stop the Lua AI magicness.
joystick_exit(); // Release joystick.
input_exit(); // Clean up keybindings.
gl_exit(); // Kills video output.
exit(EXIT_SUCCESS);
}
// == Update everything. ==================================
// Blitting order. (layers)
//
// BG | Stars and planets.
// | Background particles.
// X
// N | NPC ships.
// | Normal layer particles (above ships).
// X
// FG | Player.
// | Foreground particles.
// | Text and GUI.
// ========================================================
static void update_all(void) {
// dt in us.
double dt = (double)(SDL_GetTicks() - time) / 1000.;
time = SDL_GetTicks();
if(dt > MINIMUM_FPS) {
Vec2 pos;
vect_cset(&pos, 10., (double)(gl_screen.h-40));
gl_print(NULL, &pos, "FPS is really low! Skipping frames.");
SDL_GL_SwapBuffers();
return;
}
glClear(GL_COLOR_BUFFER_BIT);
space_render(dt);
pilots_update(dt);
display_fps(dt);
SDL_GL_SwapBuffers();
}
// Spit this out on display.
static double fps = 0.;
static double fps_cur = 0.;
static double fps_dt = 1.;
static void display_fps(const double dt) {
fps_dt += dt;
fps_cur += 1.;
if(fps_dt > 1.) {
fps = fps_cur / fps_dt;
fps_dt = fps_cur = 0.;
}
Vec2 pos;
vect_cset(&pos, 10., (double)(gl_screen.h-20));
gl_print(NULL, &pos, "%3.2f", fps);
}