sdlbomber/src/menu.c

388 lines
7.6 KiB
C
Raw Normal View History

#include "menu.h"
#include "announce.h"
#include "bomber.h"
#include "draw.h"
#include "game.h"
#include "gfx.h"
#include "network.h"
#include "sound.h"
#include "utils.h"
GameOptions configopts = {2, 1, 0, 2};
/* Generic menu */
typedef enum { MENU_ANY = -1, MENU_MAIN = 0, MENU_CONFIG = 2, MENU_JOIN = 3 } menuname;
2009-08-09 17:10:35 +00:00
#define MENU_SELECT(x) ((menuname)(-x - 1))
2009-08-09 17:10:35 +00:00
static int menuhistory[32] = {0};
2009-08-09 17:10:35 +00:00
static char menustring[1024];
static char *menuput, *menuitems[40], *menutitle;
2009-08-09 17:10:35 +00:00
static int menunum, menuexit;
static int menudelta;
static void drawmenu(int selected) {
int i, j;
int tx, ty;
clear();
j = strlen(menutitle) * bigfontxsize;
drawbigstring((IXSIZE - j) >> 1, 20, menutitle);
ty = ((IYSIZE - (bigfontysize * menunum)) >> 1) - (IYSIZE >> 3);
for (i = 0; i < menunum; ++i) {
j = strlen(menuitems[i]) * bigfontxsize;
tx = (IXSIZE - j) >> 1;
if (i == selected) {
greyrect(0, ty - 1, tx - 5, bigfontysize);
greyrect(tx + j + 3, ty - 1, IXSIZE - (tx + j + 3), bigfontysize);
}
drawbigstring(tx, ty, menuitems[i]);
ty += bigfontyspace;
}
}
2009-08-09 17:10:35 +00:00
static int domenu(menuname whichmenu, int (*pause)(void)) {
char redraw;
int selected;
int mcount = 0;
if (whichmenu >= 0)
selected = menuhistory[whichmenu];
else
selected = -whichmenu - 1;
2009-08-09 17:10:35 +00:00
if (!pause) pause = mypause;
redraw = 1;
clearspritelist();
while (!exitflag) {
if (redraw) {
drawmenu(selected);
redraw = 0;
}
2009-08-09 17:10:35 +00:00
if (!pause()) return -1;
scaninput();
++mcount;
clearsprites();
clearspritelist();
addsprite(IXSIZE / 2 - 50 - 20, IYSIZE - 80, walking[2] + (30 + mcount % 15));
addsprite(IXSIZE / 2 + 50 - 20, IYSIZE - 80, walking[3] + (30 + (mcount + 7) % 15));
plotsprites();
copyup();
if (anydown()) playsound(3);
while (anydown()) {
switch (takedown()) {
case MYLEFT:
menudelta = -1;
return selected;
case MYRIGHT:
case ' ':
case 13:
menudelta = 1;
return selected;
case 'k':
case MYUP:
if (selected)
--selected;
else
selected = menunum - 1;
if (whichmenu >= 0) menuhistory[whichmenu] = selected;
redraw = 1;
break;
case 'j':
case MYDOWN:
++selected;
if (selected == menunum) selected = 0;
if (whichmenu >= 0) menuhistory[whichmenu] = selected;
redraw = 1;
break;
case 0x1b:
2009-08-09 17:10:35 +00:00
if (MENU_MAIN == whichmenu && menuexit != selected) {
selected = menuexit;
redraw = 1;
break;
}
2009-08-09 17:10:35 +00:00
menudelta = 1;
return menuexit;
}
}
}
2009-08-09 22:02:13 +00:00
menudelta = 0;
return menuexit;
}
static void menustart() {
menunum = -1;
menuput = menustring;
*menuput = 0;
2009-08-09 17:10:35 +00:00
menuexit = 0;
}
static void additem_s(char* item, int len) {
if (len < 0 || (menustring + sizeof(menustring) - menuput <= len)) return;
if (menunum < 0)
menutitle = menuput;
else
menuitems[menunum] = menuput;
++menunum;
memcpy(menuput, item, len + 1);
menuput += len + 1;
2009-08-09 17:10:35 +00:00
}
static void additem(char* item, ...) {
2009-08-09 17:10:35 +00:00
char output[256];
va_list ap;
int len;
va_start(ap, item);
len = vsnprintf(output, sizeof(output), item, ap);
2009-08-09 17:10:35 +00:00
if (len >= 256) len = 255; /* truncated string */
additem_s(output, len);
}
static void addexit(char* item, ...) {
2009-08-09 17:10:35 +00:00
char output[256];
va_list ap;
int len;
va_start(ap, item);
len = vsnprintf(output, sizeof(output), item, ap);
2009-08-09 17:10:35 +00:00
if (len >= 256) len = 255; /* truncated string */
menuexit = menunum;
additem_s(output, len);
}
2009-08-09 17:10:35 +00:00
/* end generic menu */
/* game menues */
static const char* densities[] = {"PACKED", "HIGH", "MEDIUM", "LOW"};
static const char* generosities[] = {"LOW", "MEDIUM", "HIGH", "RIDICULOUS"};
static const char* dis_en_abled[] = {"DISABLED", "ENABLED"};
static void config_menu(void) {
int sel;
2009-08-09 22:02:13 +00:00
while (!exitflag) {
menustart();
additem("GAME OPTIONS");
additem("RETURN TO MAIN MENU");
additem("DENSITY: %s", densities[configopts.density]);
additem("GENEROSITY: %s", generosities[configopts.generosity]);
additem("INITIAL FLAME LENGTH: %d", configopts.flames + 1);
additem("INITIAL NUMBER OF BOMBS: %d", configopts.bombs + 1);
2009-08-28 20:06:06 +00:00
additem("SOUND: %s", dis_en_abled[sound_enabled]);
sel = domenu(MENU_CONFIG, NULL);
2009-08-09 22:02:13 +00:00
switch (sel) {
case 0:
return;
case 1:
configopts.density += menudelta;
configopts.density &= 3;
2009-08-09 22:02:13 +00:00
break;
case 2:
configopts.generosity += menudelta;
configopts.generosity &= 3;
2009-08-09 22:02:13 +00:00
break;
case 3:
configopts.flames += menudelta;
configopts.flames &= 7;
2009-08-09 22:02:13 +00:00
break;
case 4:
configopts.bombs += menudelta;
configopts.bombs &= 7;
2009-08-09 22:02:13 +00:00
break;
2009-08-28 20:06:06 +00:00
case 5:
sound_enabled = 1 - sound_enabled;
break;
}
}
}
static void draw_host_game(void) {
int i;
char* name;
char temp[64];
#define M3X (IXSIZE / 3)
#define M3Y (IYSIZE / 4)
clear();
centerbig(20, "HOST NETWORK GAME");
drawbigstring(M3X, M3Y, "SLOT NAME");
for (i = 0; i < MAXNETNODES; ++i) {
if (!netnodes[i].used) continue;
name = netnodes[i].name;
snprintf(temp, sizeof(temp), " %d %s", i + 1, name);
drawbigstring(M3X, M3Y + (i + 2) * bigfontyspace, temp);
}
copyup();
}
static void host_game(void) {
2009-08-09 17:10:35 +00:00
create_seed_unique();
if (!start_network_game()) {
failure("COULD NOT REGISTER GAME");
return;
}
draw_host_game();
for (;;) {
scaninput();
while (anydown()) {
switch (takedown()) {
case 0x1b:
unregistergame();
cancel_network_game();
return;
case ' ':
case 13:
unregistergame();
if (begin_network_game()) {
2009-08-09 22:02:13 +00:00
run_network_game();
return;
}
send_invites();
draw_host_game();
}
}
if (!handle_joins()) continue;
send_invites();
draw_host_game();
}
2009-08-09 22:02:13 +00:00
}
2009-08-09 22:02:13 +00:00
static void drawjoinscreen(void) {
int i;
char name[17];
char temp[64];
#define JX (IXSIZE / 3)
#define JY (IYSIZE / 4)
2009-08-09 22:02:13 +00:00
clear();
centerbig(20, "JOIN NETWORK GAME");
drawbigstring(JX, JY, "SLOT NAME");
2009-08-09 22:02:13 +00:00
for (i = 0; i < MAXNETNODES; ++i) {
if (!netnodes[i].used) continue;
memmove(name, netnodes[i].name, 16);
name[16] = 0;
snprintf(temp, sizeof(temp), " %d %s", i + 1, name);
drawbigstring(JX, JY + (i + 1) * bigfontyspace, temp);
2009-08-09 22:02:13 +00:00
}
}
static int tryjoin(int which) {
int res;
if (0 == (res = send_join(&gamelistentries[which].netname, playername))) { return 0; }
2009-08-09 22:02:13 +00:00
while (!exitflag) {
switch (res) {
case 1:
failure("Game closed");
return 0;
case 2:
drawjoinscreen();
copyup();
break;
case 3:
return 1;
default:
break;
2009-08-09 22:02:13 +00:00
}
scaninput();
while (anydown()) {
switch (takedown()) {
2009-08-09 22:02:13 +00:00
case 0x1b:
send_quit();
return 0;
}
}
res = scaninvite(200);
2009-08-09 22:02:13 +00:00
}
return 0;
}
2009-08-09 17:10:35 +00:00
static int join_game_pause(void) {
if (find_more_games()) return 0;
mypause();
return 1;
}
static void join_game(void) {
int i;
2009-08-09 17:10:35 +00:00
int sel = -1;
if (!searchgames()) { return; }
2009-08-09 17:10:35 +00:00
menuhistory[MENU_JOIN] = 0;
2009-08-09 17:10:35 +00:00
while (-1 == sel) {
menustart();
if (gamelistsize == 0) {
additem("JOIN NETWORK GAME - NO GAMES AVAILABLE");
addexit("EXIT");
} else {
additem("JOIN NETWORK GAME");
for (i = 0; i < gamelistsize; i++) { additem(gamelistentries[i].name); }
2009-08-09 17:10:35 +00:00
addexit("EXIT");
}
sel = domenu(MENU_JOIN, join_game_pause);
2009-08-09 22:02:13 +00:00
if (menudelta < 0) sel = -1;
}
2009-08-09 17:10:35 +00:00
stop_search();
if (menuexit == sel || !gamelistsize) { return; }
if (!tryjoin(sel)) { return; }
2009-08-09 22:02:13 +00:00
run_network_game();
}
void mainloop(void) {
2009-08-09 22:02:13 +00:00
int sel;
exitflag = 0;
while (!exitflag) {
2009-08-09 22:02:13 +00:00
menustart();
additem("BOMBER MAIN MENU");
additem("EXIT GAME");
additem("START SINGLE PLAYER GAME");
additem("OPTIONS");
// additem("REMAP MOVEMENT KEYS");
2009-08-09 22:02:13 +00:00
additem("START NETWORK GAME");
additem("JOIN NETWORK GAME");
sel = domenu(MENU_MAIN, NULL);
2009-08-09 22:02:13 +00:00
if (menudelta < 0) sel = -1;
switch (sel) {
case 0:
return;
case 1:
run_single_player();
break;
case 2:
config_menu();
break;
case 3:
host_game();
break;
case 4:
join_game();
break;
}
}
}