Added a basic options menu. Doesn't save to the config yet.
This commit is contained in:
parent
056e3bdae8
commit
599d5a8d82
11 changed files with 457 additions and 36 deletions
|
@ -32,6 +32,7 @@ set(SRCs
|
|||
fbo.c
|
||||
menu/menu.c
|
||||
menu/mainmenu.c
|
||||
menu/options.c
|
||||
menu/ingamemenu.c
|
||||
menu/gameovermenu.c
|
||||
menu/difficulty.c
|
||||
|
|
51
src/global.c
51
src/global.c
|
@ -11,22 +11,55 @@
|
|||
|
||||
Global global;
|
||||
|
||||
void init_global() {
|
||||
memset(&global, 0, sizeof(global));
|
||||
srand(time(0));
|
||||
|
||||
load_resources();
|
||||
printf("- fonts:\n");
|
||||
init_fonts();
|
||||
|
||||
if(!tconfig.intval[NO_SHADER]) {
|
||||
void _init_fbo()
|
||||
{
|
||||
if(!tconfig.intval[NO_SHADER] && !global.fbo_initialized) {
|
||||
printf("init_fbo():\n");
|
||||
init_fbo(&global.fbg);
|
||||
init_fbo(&global.fsec);
|
||||
printf("-- finished\n");
|
||||
global.fbo_initialized = True;
|
||||
}
|
||||
}
|
||||
|
||||
void init_alut()
|
||||
{
|
||||
if(!tconfig.intval[NO_AUDIO] && !global.alut_initialized)
|
||||
{
|
||||
if(!alutInit(&global.argc, global.argv))
|
||||
{
|
||||
warnx("Error initializing audio: %s", alutGetErrorString(alutGetError()));
|
||||
tconfig.intval[NO_AUDIO] = 1;
|
||||
printf("-- ALUT\n");
|
||||
global.alut_initialized = False;
|
||||
return;
|
||||
}
|
||||
|
||||
tconfig.intval[NO_AUDIO] = 0;
|
||||
global.alut_initialized = True;
|
||||
}
|
||||
}
|
||||
|
||||
void init_global(int argc, char **argv) {
|
||||
memset(&global, 0, sizeof(global));
|
||||
srand(time(0));
|
||||
|
||||
global.fbo_initialized = False;
|
||||
global.textures_loaded = False;
|
||||
global.shaders_loaded = False;
|
||||
global.sounds_loaded = False;
|
||||
global.alut_initialized = False;
|
||||
|
||||
global.argc = argc;
|
||||
global.argv = argv;
|
||||
|
||||
load_resources();
|
||||
printf("- fonts:\n");
|
||||
init_fonts();
|
||||
_init_fbo();
|
||||
init_alut();
|
||||
}
|
||||
|
||||
void game_over() {
|
||||
global.game_over = GAMEOVER_DEFEAT;
|
||||
printf("Game Over!\n");
|
||||
|
|
|
@ -101,6 +101,12 @@ typedef struct {
|
|||
FBO fbg;
|
||||
FBO fsec;
|
||||
|
||||
int fbo_initialized;
|
||||
int alut_initialized;
|
||||
int sounds_loaded;
|
||||
int textures_loaded;
|
||||
int shaders_loaded;
|
||||
|
||||
Boss *boss;
|
||||
MenuData *menu;
|
||||
Dialog *dialog;
|
||||
|
@ -114,6 +120,9 @@ typedef struct {
|
|||
|
||||
int fullscreenhotkey_state;
|
||||
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
FPSCounter fps;
|
||||
|
||||
} Global;
|
||||
|
|
11
src/main.c
11
src/main.c
|
@ -79,16 +79,9 @@ int main(int argc, char** argv) {
|
|||
|
||||
printf("-- GLEW\n");
|
||||
init_gl();
|
||||
|
||||
printf("-- GL\n");
|
||||
|
||||
if(!tconfig.intval[NO_AUDIO] && !alutInit(&argc, argv)) {
|
||||
warnx("Error initializing audio: %s", alutGetErrorString(alutGetError()));
|
||||
tconfig.intval[NO_AUDIO] = 1;
|
||||
printf("-- ALUT\n");
|
||||
}
|
||||
|
||||
init_global();
|
||||
init_global(argc, argv);
|
||||
printf("initialization complete.\n");
|
||||
MenuData menu;
|
||||
create_main_menu(&menu);
|
||||
|
@ -99,4 +92,4 @@ int main(int argc, char** argv) {
|
|||
shutdown();
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,13 @@ troll:
|
|||
stage0_loop();
|
||||
}
|
||||
|
||||
void enter_options(void *arg)
|
||||
{
|
||||
MenuData m;
|
||||
create_options_menu(&m);
|
||||
options_menu_loop();
|
||||
}
|
||||
|
||||
void create_main_menu(MenuData *m) {
|
||||
create_menu(m);
|
||||
|
||||
|
@ -43,7 +50,8 @@ void create_main_menu(MenuData *m) {
|
|||
|
||||
add_menu_entry(m, "Start Story", start_story, NULL);
|
||||
add_menu_entry(m, "Start Extra", NULL, NULL);
|
||||
add_menu_entry(m, "Options", NULL, NULL);
|
||||
//add_menu_entry(m, "Options", NULL, NULL);
|
||||
add_menu_entry(m, "Options", enter_options, NULL);
|
||||
add_menu_entry(m, "Quit", quit_menu, m);
|
||||
}
|
||||
|
||||
|
@ -99,4 +107,4 @@ void draw_main_menu(MenuData *menu) {
|
|||
|
||||
void main_menu_loop(MenuData *menu) {
|
||||
menu_loop(menu, NULL, draw_main_menu);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,4 +17,4 @@ void draw_main_menu_bg(MenuData *m);
|
|||
void draw_main_menu(MenuData *m);
|
||||
void main_menu_loop(MenuData *m);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,9 @@ void add_menu_entry(MenuData *menu, char *name, void (*action)(void *), void *ar
|
|||
void destroy_menu(MenuData *menu) {
|
||||
int i;
|
||||
|
||||
if(menu->ondestroy)
|
||||
menu->ondestroy(menu);
|
||||
|
||||
for(i = 0; i < menu->ecount; i++)
|
||||
free(menu->entries[i].name);
|
||||
|
||||
|
@ -31,6 +34,7 @@ void create_menu(MenuData *menu) {
|
|||
|
||||
menu->fade = 1;
|
||||
menu->selected = -1;
|
||||
menu->ondestroy = NULL;
|
||||
}
|
||||
|
||||
void menu_input(MenuData *menu) {
|
||||
|
|
|
@ -39,6 +39,9 @@ typedef struct MenuData{
|
|||
float fade;
|
||||
|
||||
float drawdata[4];
|
||||
|
||||
void *context;
|
||||
void (*ondestroy)(void*);
|
||||
} MenuData;
|
||||
|
||||
void add_menu_entry(MenuData *menu, char *name, void (*action)(void *), void *arg);
|
||||
|
@ -51,4 +54,4 @@ void menu_input(MenuData *menu);
|
|||
int menu_loop(MenuData *menu, void (*input)(MenuData*), void (*draw)(MenuData*));
|
||||
|
||||
void fade_out(float f);
|
||||
#endif
|
||||
#endif
|
||||
|
|
329
src/menu/options.c
Normal file
329
src/menu/options.c
Normal file
|
@ -0,0 +1,329 @@
|
|||
|
||||
#include "menu.h"
|
||||
#include "options.h"
|
||||
#include "global.h"
|
||||
|
||||
void do_nothing(void *arg)
|
||||
{
|
||||
printf("NOTHING happened!\n");
|
||||
}
|
||||
|
||||
void backtomain(void *arg)
|
||||
{
|
||||
MenuData *m = arg;
|
||||
m->quit = 2;
|
||||
}
|
||||
|
||||
void allocate_bindings(MenuData *m)
|
||||
{
|
||||
OptionBinding *binds = malloc(m->ecount * sizeof(OptionBinding));
|
||||
int i;
|
||||
|
||||
for(i = 0; i < m->ecount; ++i)
|
||||
{
|
||||
binds[i].values = NULL;
|
||||
binds[i].getter = NULL;
|
||||
binds[i].setter = NULL;
|
||||
binds[i].selected = -1;
|
||||
binds[i].valcount = 0;
|
||||
binds[i].configentry = -1;
|
||||
binds[i].enabled = False;
|
||||
}
|
||||
|
||||
m->context = (void*)binds;
|
||||
}
|
||||
|
||||
void free_bindings(void *menu)
|
||||
{
|
||||
MenuData *m = (MenuData*)menu;
|
||||
OptionBinding *binds = (OptionBinding*)m->context;
|
||||
|
||||
int i, j;
|
||||
for(i = 0; i < m->ecount; ++i)
|
||||
{
|
||||
OptionBinding *bind = &(binds[i]);
|
||||
if(!bind->enabled)
|
||||
continue;
|
||||
|
||||
if(bind->values) for(j = 0; j < bind->valcount; ++j)
|
||||
free(bind->values[j]);
|
||||
free(bind->optname);
|
||||
}
|
||||
free(binds);
|
||||
}
|
||||
|
||||
OptionBinding* bind_option_to_entry(MenuData *m, int entry, char *optname, int cfgentry, BindingGetter getter, BindingSetter setter)
|
||||
{
|
||||
OptionBinding *binds = (OptionBinding*)m->context;
|
||||
OptionBinding *bind = &(binds[entry]);
|
||||
|
||||
bind->getter = getter;
|
||||
bind->setter = setter;
|
||||
bind->configentry = cfgentry;
|
||||
bind->optname = malloc((strlen(optname) + 1) * sizeof(char));
|
||||
strcpy(bind->optname, optname);
|
||||
bind->enabled = True;
|
||||
|
||||
return bind;
|
||||
}
|
||||
|
||||
int bind_addvalue(OptionBinding *b, char *val)
|
||||
{
|
||||
if(!b->values)
|
||||
b->values = malloc(++b->valcount * sizeof(char));
|
||||
else
|
||||
b->values = realloc(b->values, ++b->valcount * sizeof(char));
|
||||
|
||||
b->values[b->valcount-1] = malloc((strlen(val) + 1) * sizeof(char));
|
||||
strcpy(b->values[b->valcount-1], val);
|
||||
return b->valcount-1;
|
||||
}
|
||||
|
||||
int binding_setvalue(OptionBinding *b, int v)
|
||||
{
|
||||
return b->selected = b->setter(b, v);
|
||||
}
|
||||
|
||||
int binding_setnext(OptionBinding *b)
|
||||
{
|
||||
int s = b->selected + 1;
|
||||
if(s >= b->valcount)
|
||||
s = 0;
|
||||
|
||||
return binding_setvalue(b, s);
|
||||
}
|
||||
|
||||
int binding_setprev(OptionBinding *b)
|
||||
{
|
||||
int s = b->selected - 1;
|
||||
if(s < 0)
|
||||
s = b->valcount - 1;
|
||||
|
||||
return binding_setvalue(b, s);
|
||||
}
|
||||
|
||||
void bindings_initvalues(MenuData *m)
|
||||
{
|
||||
OptionBinding *binds = (OptionBinding*)m->context;
|
||||
|
||||
int i;
|
||||
for(i = 0; i < m->ecount; ++i)
|
||||
if(binds[i].enabled)
|
||||
binds[i].selected = binds[i].getter(&(binds[i]));
|
||||
}
|
||||
|
||||
int bind_common_onoffget(void *b)
|
||||
{
|
||||
return !tconfig.intval[((OptionBinding*)b)->configentry];
|
||||
}
|
||||
|
||||
int bind_common_onoffset(void *b, int v)
|
||||
{
|
||||
return !(tconfig.intval[((OptionBinding*)b)->configentry] = !v);
|
||||
}
|
||||
|
||||
int bind_common_onoffget_inverted(void *b)
|
||||
{
|
||||
return tconfig.intval[((OptionBinding*)b)->configentry];
|
||||
}
|
||||
|
||||
int bind_common_onoffset_inverted(void *b, int v)
|
||||
{
|
||||
return tconfig.intval[((OptionBinding*)b)->configentry] = v;
|
||||
}
|
||||
|
||||
int bind_fullscreen_set(void *b, int v)
|
||||
{
|
||||
toggle_fullscreen();
|
||||
return bind_common_onoffset(b, v);
|
||||
}
|
||||
|
||||
int bind_noaudio_set(void *b, int v)
|
||||
{
|
||||
int i = bind_common_onoffset_inverted(b, v);
|
||||
|
||||
if(!v)
|
||||
{
|
||||
init_alut();
|
||||
load_resources();
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int bind_noshader_set(void *b, int v)
|
||||
{
|
||||
int i = bind_common_onoffset_inverted(b, v);
|
||||
|
||||
if(!v)
|
||||
{
|
||||
_init_fbo();
|
||||
load_resources();
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void create_options_menu(MenuData *m) {
|
||||
OptionBinding* b;
|
||||
|
||||
create_menu(m);
|
||||
m->type = MT_Persistent;
|
||||
m->ondestroy = free_bindings;
|
||||
|
||||
add_menu_entry(m, "Fullscreen", do_nothing, NULL);
|
||||
add_menu_entry(m, "Audio", do_nothing, NULL);
|
||||
add_menu_entry(m, "Shader", do_nothing, NULL);
|
||||
add_menu_entry(m, " ", NULL, NULL);
|
||||
add_menu_entry(m, "Customize controls", NULL, NULL);
|
||||
add_menu_entry(m, "Back", backtomain, m);
|
||||
|
||||
allocate_bindings(m);
|
||||
|
||||
b = bind_option_to_entry(m, 0, "fullscreen", FULLSCREEN, bind_common_onoffget, bind_fullscreen_set);
|
||||
bind_addvalue(b, "on");
|
||||
bind_addvalue(b, "off");
|
||||
|
||||
b = bind_option_to_entry(m, 1, "disable_audio", NO_AUDIO, bind_common_onoffget_inverted,
|
||||
bind_noaudio_set);
|
||||
bind_addvalue(b, "on");
|
||||
bind_addvalue(b, "off");
|
||||
|
||||
b = bind_option_to_entry(m, 2, "disable_shader", NO_SHADER, bind_common_onoffget_inverted,
|
||||
bind_noshader_set);
|
||||
bind_addvalue(b, "on");
|
||||
bind_addvalue(b, "off");
|
||||
|
||||
bindings_initvalues(m);
|
||||
}
|
||||
|
||||
void draw_options_menu(MenuData *menu) {
|
||||
glColor4f(0.3, 0.3, 0.3, 1);
|
||||
draw_texture(SCREEN_W/2, SCREEN_H/2, "mainmenu/mainmenubgbg");
|
||||
glColor4f(1,0.6,0.5,0.6 + 0.1*sin(menu->frames/100.0));
|
||||
draw_texture(SCREEN_W/2, SCREEN_H/2, "mainmenu/mainmenubg");
|
||||
glColor4f(1,1,1,1);
|
||||
|
||||
draw_text(AL_Right, 140*(1-menu->fade), 30, "Options", _fonts.mainmenu);
|
||||
|
||||
//glColor4f(1,1,1,0.7);
|
||||
//draw_texture(SCREEN_W/2+40, SCREEN_H/2, "mainmenu/gate");
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(100, 100, 0);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(0, menu->drawdata[2], 0);
|
||||
glColor4f(0,0,0,0.5);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex3f(0, -10, 0);
|
||||
glVertex3f(0, 10, 0);
|
||||
glVertex3f(SCREEN_W - 200, 10, 0);
|
||||
glVertex3f(SCREEN_W - 200, -10, 0);
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
|
||||
OptionBinding *binds = (OptionBinding*)menu->context;
|
||||
OptionBinding *bind;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < menu->ecount; i++) {
|
||||
float s = 0;
|
||||
|
||||
float grey = 1;
|
||||
if(menu->entries[i].action == NULL)
|
||||
grey = 0.5;
|
||||
|
||||
if(i == menu->cursor)
|
||||
{
|
||||
glColor4f(1,1,0,0.7);
|
||||
s = 5*sin(menu->frames/80.0 + 20*i);
|
||||
}
|
||||
else
|
||||
glColor4f(grey,grey,grey,0.7);
|
||||
|
||||
draw_text(AL_Left, 20 + s, 20*i, menu->entries[i].name, _fonts.standard);
|
||||
|
||||
bind = &(binds[i]);
|
||||
|
||||
if(bind->enabled && bind->valcount > 0)
|
||||
{
|
||||
int len = 0, j;
|
||||
for(j = bind->valcount - 1; j+1; --j)
|
||||
{
|
||||
len += strlen(bind->values[j]);
|
||||
|
||||
if(bind->selected == j)
|
||||
glColor4f(1,1,0,0.7);
|
||||
else
|
||||
glColor4f(0.5,0.5,0.5,0.7);
|
||||
|
||||
draw_text(AL_Right, SCREEN_W - 200 - (len*20), 20*i, bind->values[j], _fonts.standard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
glPopMatrix();
|
||||
menu->drawdata[2] += (20*menu->cursor - menu->drawdata[2])/10.0;
|
||||
|
||||
fade_out(menu->fade);
|
||||
|
||||
glColor4f(1,1,1,1);
|
||||
}
|
||||
|
||||
void options_menu_input(MenuData *menu) {
|
||||
SDL_Event event;
|
||||
|
||||
global_input();
|
||||
|
||||
while(SDL_PollEvent(&event)) {
|
||||
int sym = event.key.keysym.sym;
|
||||
if(event.type == SDL_KEYDOWN) {
|
||||
if(sym == tconfig.intval[KEY_DOWN]) {
|
||||
menu->drawdata[3] = 10;
|
||||
while(!(menu->entries[++menu->cursor].action));
|
||||
} else if(sym == tconfig.intval[KEY_UP]) {
|
||||
menu->drawdata[3] = 10;
|
||||
while(!(menu->entries[--menu->cursor].action));
|
||||
} else if((sym == tconfig.intval[KEY_SHOT] || sym == SDLK_RETURN) && menu->entries[menu->cursor].action) {
|
||||
menu->selected = menu->cursor;
|
||||
|
||||
// hack hack
|
||||
if(menu->entries[menu->selected].action == backtomain)
|
||||
menu->quit = 1;
|
||||
|
||||
OptionBinding *binds = (OptionBinding*)menu->context;
|
||||
OptionBinding *bind = &(binds[menu->selected]);
|
||||
|
||||
if(bind->enabled)
|
||||
binding_setnext(bind);
|
||||
} else if(sym == tconfig.intval[KEY_LEFT]) {
|
||||
menu->selected = menu->cursor;
|
||||
OptionBinding *binds = (OptionBinding*)menu->context;
|
||||
OptionBinding *bind = &(binds[menu->selected]);
|
||||
|
||||
if(bind->enabled)
|
||||
binding_setprev(bind);
|
||||
} else if(sym == tconfig.intval[KEY_RIGHT]) {
|
||||
menu->selected = menu->cursor;
|
||||
OptionBinding *binds = (OptionBinding*)menu->context;
|
||||
OptionBinding *bind = &(binds[menu->selected]);
|
||||
|
||||
if(bind->enabled)
|
||||
binding_setnext(bind);
|
||||
} else if(sym == SDLK_ESCAPE) {
|
||||
menu->quit = 2;
|
||||
}
|
||||
|
||||
menu->cursor = (menu->cursor % menu->ecount) + menu->ecount*(menu->cursor < 0);
|
||||
} else if(event.type == SDL_QUIT) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int options_menu_loop(MenuData *menu) {
|
||||
return menu_loop(menu, options_menu_input, draw_options_menu);
|
||||
}
|
||||
|
27
src/menu/options.h
Normal file
27
src/menu/options.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
|
||||
#ifndef OPTMENU_H
|
||||
#define OPTMENU_H
|
||||
|
||||
#include "menu.h"
|
||||
|
||||
void create_options_menu(MenuData *m);
|
||||
|
||||
void draw_options_menu(MenuData *m);
|
||||
int options_menu_loop(MenuData *m);
|
||||
|
||||
typedef int (*BindingGetter)(void*);
|
||||
typedef int (*BindingSetter)(void*, int);
|
||||
|
||||
typedef struct OptionBinding {
|
||||
char **values;
|
||||
int valcount;
|
||||
BindingGetter getter;
|
||||
BindingSetter setter;
|
||||
int selected;
|
||||
int configentry;
|
||||
int enabled;
|
||||
char *optname;
|
||||
} OptionBinding;
|
||||
|
||||
#endif
|
||||
|
|
@ -52,28 +52,42 @@ void recurse_dir(char *path) {
|
|||
void load_resources() {
|
||||
printf("load_resources():\n");
|
||||
char *path = malloc(strlen(get_prefix())+7);
|
||||
|
||||
printf("- textures:\n");
|
||||
strcpy(path, get_prefix());
|
||||
strcat(path, "gfx");
|
||||
recurse_dir(path);
|
||||
|
||||
if(!tconfig.intval[NO_AUDIO]) {
|
||||
if(!global.textures_loaded)
|
||||
{
|
||||
printf("- textures:\n");
|
||||
strcpy(path, get_prefix());
|
||||
strcat(path, "gfx");
|
||||
recurse_dir(path);
|
||||
|
||||
global.textures_loaded = True;
|
||||
}
|
||||
|
||||
if(!global.sounds_loaded && !tconfig.intval[NO_AUDIO]) {
|
||||
printf("- sounds:\n");
|
||||
alGenSources(SNDSRC_COUNT, global.sndsrc);
|
||||
strcpy(path, get_prefix());
|
||||
strcat(path, "sfx");
|
||||
recurse_dir(path);
|
||||
|
||||
global.sounds_loaded = True;
|
||||
}
|
||||
|
||||
if(!tconfig.intval[NO_SHADER]) {
|
||||
printf("- shader:\n");
|
||||
strcpy(path, get_prefix());
|
||||
strcat(path, "shader");
|
||||
recurse_dir(path);
|
||||
} else {
|
||||
printf("- shader: disabled.\n");
|
||||
if(!global.shaders_loaded)
|
||||
{
|
||||
if(!tconfig.intval[NO_SHADER]) {
|
||||
printf("- shader:\n");
|
||||
strcpy(path, get_prefix());
|
||||
strcat(path, "shader");
|
||||
recurse_dir(path);
|
||||
|
||||
global.shaders_loaded = True;
|
||||
} else {
|
||||
printf("- shader: disabled.\n");
|
||||
}
|
||||
}
|
||||
|
||||
free(path);
|
||||
}
|
||||
|
||||
Texture *get_tex(char *name) {
|
||||
|
@ -307,4 +321,4 @@ void fill_screen_p(float xoff, float yoff, float ratio, Texture *tex) {
|
|||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue