[Add] Dynamic key bindind loading from configuration file.

This commit is contained in:
Allanis 2013-02-02 21:13:25 +00:00
parent 57bebe1403
commit 54beb595dc
8 changed files with 269 additions and 130 deletions

15
bin/conf.example Normal file
View File

@ -0,0 +1,15 @@
--WINDOW.
width = 800
height = 640
fullscreen = 0
-- JOYSTICK.
-- Can be number or substring of joystick name.
joystick = "Precision"
-- KEYBINDINGS.
-- Type can be keyboard, jaxis or jbutton.
accel = { type = "jbutton", key = 0 }
left = { type = "jaxis", key = 0 }
right = { type = "jaxis", key = 0 }

View File

@ -4,6 +4,7 @@
#define LOG(str, args...)(fprintf(stdout, str"\n", ## args))
#define WARN(str, args...)(fprintf(stderr, "[%d] "str"\n", SDL_GetTicks(), ## args))
#define ERR(str, args...) (fprintf(stderr, "%s:%d: "str"\n", __FILE__, __LINE__, ## args))
#ifdef DEBUG
# undef DEBUG

View File

@ -18,14 +18,14 @@
#include "ai.h"
#include "pilot.h"
#define WINDOW_CAPTION "Lephisto"
#define CONF_FILE "conf"
#define WINDOW_CAPTION "Lephisto"
#define CONF_FILE "conf"
#define MINIMUM_FPS 0.5
static gl_font fdefault;
extern const char* keybindNames[]; // Keybindings.
static int quit = 0;
static unsigned int time = 0;
static int quit = 0; // Primary loop.
static unsigned int time = 0; // Calculate FPS and movement.
// Prototypes.
@ -49,6 +49,9 @@ static void print_usage(char** argv) {
}
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;
@ -57,10 +60,19 @@ int main(int argc, char** argv) {
int indjoystick = -1;
char* namjoystick = NULL;
// input.
input_init();
input_setKeybind("accel", KEYBIND_KEYBOARD, SDLK_UP, 0);
input_setKeybind("accel", KEYBIND_KEYBOARD, SDLK_w, 0);
input_setKeybind("left", KEYBIND_KEYBOARD, SDLK_LEFT, 0);
input_setKeybind("left", KEYBIND_KEYBOARD, SDLK_a, 0);
input_setKeybind("right", KEYBIND_KEYBOARD, SDLK_RIGHT, 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) {
// OpenGL.
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);
@ -78,6 +90,45 @@ int main(int argc, char** argv) {
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))
str = (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;
// Set the keybind.
input_setKeybind((char*)keybindNames[i], type, key, reverse);
} else WARN("Malformed keybind in %s", CONF_FILE);
}
}
}
lua_close(L);
@ -105,8 +156,6 @@ int main(int argc, char** argv) {
// Random numbers.
rng_init();
// SDL_Init is first called here, so it's important to be
// initialized first.
if(gl_init()) {
// Initializes video output.
WARN("Error initializing video output, exiting...");
@ -132,7 +181,7 @@ int main(int argc, char** argv) {
if(ai_init())
WARN("Error initializing AI");
gl_fontInit(&fdefault, "../gfx/fonts/FreeSans.ttf", 16);
gl_fontInit(NULL, "../gfx/fonts/FreeSans.ttf", 16);
// Data loading.
ships_load();
@ -149,35 +198,51 @@ int main(int argc, char** argv) {
// 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.
handle_input(&event);
input_handle(&event); // handles all the events the player keybinds.
}
update_all();
}
space_exit();
// Unload data.
pilots_free();
space_exit(); // Clean up the universe!!!
pilots_free(); // Free the pilots, they where locked up D:
ships_free();
gl_freeFont(&fdefault);
gl_freeFont(NULL);
// Exit subsystems.
joystick_exit();
gl_exit(); // Kills video output.
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 all the things.
// Space:
// -- Stars.
// -- Movement.
// -- Render.
// Pilots:
// -- Think (ai).
// -- Solid.
static void update_all(void) {
double dt = (double)(SDL_GetTicks() - time) / 1000.0;
time = SDL_GetTicks();
if(dt > MINIMUM_FPS) {
Vec2 pos = { .x = 10., .y = gl_screen.h-40 };
gl_print(NULL, &pos, "FPS is really low! Skipping frames.");
SDL_GL_SwapBuffers();
}
glClear(GL_COLOR_BUFFER_BIT);
space_render(dt);
@ -188,6 +253,8 @@ static void update_all(void) {
SDL_GL_SwapBuffers();
}
// Spit this out on display.
static double fps = 0.;
static double fps_cur = 0.;
static double fps_dt = 1.;
@ -199,6 +266,6 @@ static void display_fps(const double dt) {
fps_dt = fps_cur = 0.;
}
Vec2 pos = { .x = 10., .y = (double)(gl_screen.h-20) };
gl_print(&fdefault, &pos, "%3.2f", fps);
gl_print(NULL, &pos, "%3.2f", fps);
}

View File

@ -20,9 +20,12 @@ gl_info gl_screen;
// Our precious camera.
Vec2* gl_camera;
// Default font.
gl_font gl_defFont;
// Misc.
static int flip_surface(SDL_Surface* surface);
static int pot(int n);
static int _flip_surface(SDL_Surface* surface);
static int _pot(int n);
// gl_texture.
static GLuint gl_loadSurface(SDL_Surface* surface, int* rw, int* rh);
// Gl font.
@ -33,7 +36,7 @@ static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* te
// ================
// Get me the closest power of two plox.
static int pot(int n) {
static int _pot(int n) {
int i = 1;
while(i < n)
i<<=1;
@ -41,7 +44,7 @@ static int pot(int n) {
}
// Flips the surface vertically. Return 0 on success.
static int flip_surface(SDL_Surface* surface) {
static int _flip_surface(SDL_Surface* surface) {
// Flip the image.
Uint8* rowhi, *rowlo, *tmpbuf;
int y;
@ -80,8 +83,8 @@ static GLuint gl_loadSurface(SDL_Surface* surface, int* rw, int* rh) {
int potw, poth;
// Make size power of two.
potw = pot(surface->w);
poth = pot(surface->h);
potw = _pot(surface->w);
poth = _pot(surface->h);
if(rw)*rw = potw;
if(rh)*rh = poth;
@ -198,7 +201,7 @@ gl_texture* gl_newImage(const char* path) {
SDL_FreeSurface(tmp); // Free the temp surface.
if(flip_surface(surface)) {
if(_flip_surface(surface)) {
WARN("Error flipping surface");
return NULL;
}
@ -301,11 +304,14 @@ void gl_bindCamera(const Vec2* pos) {
}
// Print text on screen! YES!!!! Just like printf! But different!
// Defaults ft_font to gl_defFont if NULL.
void gl_print(const gl_font* ft_font, const Vec2* pos, const char* fmt, ...) {
//float h = ft_font->h / .63; // Slightly increases font size.
char text[256];
va_list ap;
if(ft_font == NULL) ft_font = &gl_defFont;
if(fmt == NULL) return;
else {
// convert the symbols to text.
@ -353,8 +359,8 @@ static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* te
bitmap = bitmap_glyph->bitmap; // To simplify.
// Need the POT wrapping for GL.
w = pot(bitmap.width);
h = pot(bitmap.rows);
w = _pot(bitmap.width);
h = _pot(bitmap.rows);
// Memory for textured data.
// Bitmap is useing two channels, one for luminosity and one for alpha.
@ -406,6 +412,8 @@ static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* te
}
void gl_fontInit(gl_font* font, const char* fname, unsigned int h) {
if(font == NULL) font = &gl_defFont;
font->textures = malloc(sizeof(GLuint)*128);
font->h = h;
@ -438,6 +446,7 @@ void gl_fontInit(gl_font* font, const char* fname, unsigned int h) {
}
void gl_freeFont(gl_font* font) {
if(font == NULL) font = &gl_defFont;
glDeleteLists(font->list_base, 128);
glDeleteTextures(128, font->textures);
free(font->textures);
@ -455,7 +464,7 @@ int gl_init(void) {
flags |= SDL_FULLSCREEN * gl_screen.fullscreen;
// Initializes video.
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
if(SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
WARN("Unable to initialize SDL: %s", SDL_GetError());
return -1;
}

View File

@ -45,6 +45,7 @@ typedef struct {
} gl_font;
// gl_font loading/freeing.
// If font is NULL it uses the internal default font, same with gl_print
void gl_fontInit(gl_font* font, const char* fname, unsigned int h);
void gl_freeFont(gl_font* font);

View File

@ -1,139 +1,188 @@
#include <malloc.h>
#include "def.h"
#include "pilot.h"
#include "log.h"
#include "player.h"
Pilot* player = NULL;
static unsigned int player_flags = PLAYER_FLAG_NULL;
#define KEY_PRESS 1.
#define KEY_RELEASE -1.
static double player_turn = 0.;
static double player_acc = 0.;
// Keybind structure.
typedef struct {
char* name; // Keybinding name, taken from keybindNames[]
KeybindType type; // type, defined in player.h.
int key; // Key/axis/button event number.
double reverse; // 1. if normal, -1 if reversed, only useful for joystick axis.
} Keybind;
static Keybind** player_input; // Contains the players keybindings.
// Name of each keybinding.
const char* keybindNames[] = { "accel", "left", "right" };
// To be used in pilot.c
Pilot* player = NULL; // extern in pilot.h
static double player_turn = 0.; // Turn velocity from input.
static double player_acc = 0.; // Accel velocity from input.
// Used in pilot.c
// Basically uses keyboard input instead of AI input.
void player_think(Pilot* player, const double dt) {
player->solid->dir_vel = 0.;
if(player_turn)
player->solid->dir_vel -= player->ship->turn*player_turn/(double)(1<<15);
#if 0
if(player_isFlag(PLAYER_FLAG_MOV_LEFT))
player->solid->dir_vel += player->ship->turn;
if(player_isFlag(PLAYER_FLAG_MOV_RIGHT))
player->solid->dir_vel -= player->ship->turn;
#endif
player->solid->dir_vel -= player->ship->turn * player_turn;
player->solid->force = player->ship->thrust*player_acc/(double)(1<<15);
player->solid->force = player->ship->thrust * player_acc;
}
// Flag manipulationz.
int player_isFlag(unsigned int flag) {
return player_flags & flag;
// Initialization/exit functions (does not assign keys).
void input_init(void) {
Keybind* tmp;
int i;
for(i = 0; keybindNames[i]; i++); // Get number of bindings.
player_input = (Keybind**)malloc(i*sizeof(Keybind*));
// Create a null keybinding for each.
for(i = 0; keybindNames[i]; i++) {
tmp = MALLOC_L(Keybind);
tmp->name = (char*)keybindNames[i];
tmp->type = KEYBIND_NULL;
tmp->key = 0;
tmp->reverse = 1.;
player_input[i] = tmp;
}
}
void player_setFlag(unsigned int flag) {
if(!player_isFlag(flag))
player_flags |= flag;
void input_exit(void) {
int i;
for(i = 0; keybindNames[i]; i++)
free(player_input[i]);
free(player_input);
}
void player_rmFlag(unsigned int flag) {
if(player_isFlag(flag))
player_flags ^= flag;
// Binds key of type [type] to action keybind.
void input_setKeybind(char* keybind, KeybindType type, int key, int reverse) {
int i;
for(i = 0; keybindNames[i]; i++) {
if(strcmp(keybind, player_input[i]->name)==0) {
player_input[i]->type = type;
player_input[i]->key = key;
player_input[i]->reverse = reverse ? -1. : 1.;
return;
}
}
}
// == Run input method. ================================================
// keynum : Index of the player_input keybind.
// value : Value of keypress (defined above).
// abs : Whether or not it's an abs value (For those pesky joysticks.
// =====================================================================
static void input_key(int keynum, double value, int abs) {
if(strcmp(player_input[keynum]->name, "accel")==0) {
if(abs)player_acc = value;
else player_acc += value;
}
else if(strcmp(player_input[keynum]->name, "left")==0) {
if(abs)player_turn = -value;
else player_turn -= value;
}
else if(strcmp(player_input[keynum]->name, "right")==0) {
if(abs) player_turn = value;
else player_turn += value;
}
//Make sure values are sane.
player_acc = ABS(player_acc);
if(player_acc > 1.) player_acc = 1.;
if(player_turn > 1.) player_turn = 1.;
else if(player_turn < -1.) player_turn = -1.;
}
// --Events--
static void input_joyaxis(int axis, int value);
static void input_joydown(int button);
static void input_joyup(int button);
static void input_keydown(SDLKey key);
static void input_keyup(SDLKey key);
// Joystick.
static void handle_joyaxis(int axis, int value) {
switch(axis) {
case 0:
player_turn = (double)value;
break;
case 1:
if(value <= 0)
player_acc = (double)-value;
break;
}
// Axis.
static void input_joyaxis(int axis, int value) {
int i;
for(i = 0; keybindNames[i]; i++)
if(player_input[i]->type == KEYBIND_JAXIS && player_input[i]->key == axis) {
input_key(i, -(player_input[i]->reverse) * (double)value / 32767., 1);
return;
}
}
static void handle_joydown(int button) {
switch(button) {
case 0:
player_acc += (double)(1<<15);
break;
case 1:
break;
}
// Joystick button down.
static void input_joydown(int button) {
int i;
for(i = 0; keybindNames[i]; i++)
if(player_input[i]->type == KEYBIND_JBUTTON && player_input[i]->key == button) {
input_key(i, KEY_RELEASE, 0);
return;
}
}
static void handle_joyup(int button) {
switch(button) {
case 0:
player_acc -=(double)(1<<15);
break;
case 1:
break;
}
// Joystick button up.
static void input_joyup(int button) {
int i;
for(i = 0; keybindNames[i]; i++)
if(player_input[i]->type == KEYBIND_JBUTTON && player_input[i]->key == button) {
input_key(i, KEY_RELEASE, 0);
return;
}
}
// Keyboard.
static void handle_keydown(SDLKey key) {
// Key down.
static void input_keydown(SDLKey key) {
int i;
for(i = 0; keybindNames[i]; i++)
if(player_input[i]->type == KEYBIND_KEYBOARD && player_input[i]->key == key) {
input_key(i, KEY_PRESS, 0);
return;
}
// Fire Escape.
SDL_Event quit;
switch(key) {
case SDLK_ESCAPE:
quit.type = SDL_QUIT;
SDL_PushEvent(&quit);
break;
case SDLK_LEFT:
case SDLK_a:
player_turn -= (double)(1<<15);
break;
case SDLK_RIGHT:
case SDLK_d:
player_turn += (double)(1<<15);
break;
case SDLK_UP:
case SDLK_w:
player_acc += (double)(1<<15);
break;
default:
break;
if(key == SDLK_ESCAPE) {
quit.type = SDL_QUIT;
SDL_PushEvent(&quit);
}
}
static void handle_keyup(SDLKey key) {
switch(key) {
case SDLK_LEFT:
case SDLK_a:
player_turn += (double)(1<<15);
break;
case SDLK_RIGHT:
case SDLK_d:
player_turn -= (double)(1<<15);
break;
case SDLK_UP:
case SDLK_w:
player_acc -= (double)(1<<15);
//break;
default:
break;
}
// Key up.
static void input_keyup(SDLKey key) {
int i;
for(i = 0; keybindNames[i]; i++)
if(player_input[i]->type == KEYBIND_KEYBOARD && player_input[i]->key == key) {
input_key(i, KEY_RELEASE, 0);
return;
}
}
// Global input.
void handle_input(SDL_Event* event) {
// Just seperates the event types.
void input_handle(SDL_Event* event) {
switch(event->type) {
case SDL_JOYAXISMOTION:
handle_joyaxis(event->jaxis.axis, event->jaxis.value);
input_joyaxis(event->jaxis.axis, event->jaxis.value);
break;
case SDL_JOYBUTTONDOWN:
handle_joydown(event->jbutton.button);
input_joydown(event->jbutton.button);
break;
case SDL_JOYBUTTONUP:
handle_joyup(event->jbutton.button);
input_joyup(event->jbutton.button);
case SDL_KEYDOWN:
handle_keydown(event->key.keysym.sym);
input_keydown(event->key.keysym.sym);
break;
case SDL_KEYUP:
handle_keyup(event->key.keysym.sym);
input_keyup(event->key.keysym.sym);
break;
}
}

View File

@ -1,16 +1,15 @@
#pragma once
#include <SDL.h>
// Flags.
#define PLAYER_FLAG_NULL (1<<0)
#define PLAYER_FLAG_MOV_LEFT (1<<1)
#define PLAYER_FLAG_MOV_RIGHT (1<<2)
#define PLAYER_FLAG_MOV_ACC (1<<3)
typedef enum { KEYBIND_NULL, KEYBIND_KEYBOARD, KEYBIND_JAXIS, KEYBIND_JBUTTON } KeybindType;
int player_isFlag(unsigned int flag);
void player_setFlag(unsigned int flag);
void player_rmFlag(unsigned int flag);
// Input.
void handle_input(SDL_Event* event);
void input_init(void);
void input_exit(void);
void input_set_Keybind(char* keybind, KeybindType type, int key, int reverse);
void input_handle(SDL_Event* event);

View File

@ -1,5 +1,3 @@
#include <SDL.h>
#include <SDL_opengl.h>
#include "log.h"
#include "physics.h"
#include "opengl.h"
@ -21,9 +19,9 @@ void space_init(void) {
nstars = (500*gl_screen.w*gl_screen.h + STAR_BUF*STAR_BUF)/(800*640);;
stars = malloc(sizeof(Star)*nstars);
for(i = 0; i < nstars; i++) {
stars[i].brightness = (float)RNG(50, 200)/256.;
stars[i].pos.x = (float)RNG(-STAR_BUF, gl_screen.w + STAR_BUF);
stars[i].pos.y = (float)RNG(-STAR_BUF, gl_screen.h + STAR_BUF);
stars[i].brightness = (double)RNG(50, 200)/256.;
stars[i].pos.x = (double)RNG(-STAR_BUF, gl_screen.w + STAR_BUF);
stars[i].pos.y = (double)RNG(-STAR_BUF, gl_screen.h + STAR_BUF);
}
}