sdlbomber/menu.c
2009-08-10 00:02:13 +02:00

398 lines
7.1 KiB
C

#include "bomber.h"
#include "menu.h"
#include "draw.h"
#include "gfx.h"
#include "utils.h"
#include "sound.h"
#include "network.h"
#include "announce.h"
#include "game.h"
GameOptions configopts = { 2, 1, 0, 2 };
/* Generic menu */
typedef enum {
MENU_ANY = -1,
MENU_MAIN = 0,
MENU_CONFIG = 2,
MENU_JOIN = 3
} menuname;
#define MENU_SELECT(x) ((menuname) (-x-1))
static int menuhistory[32]={0};
static char menustring[1024];
static char *menuput,*menuitems[40],*menutitle;
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;
}
}
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;
if (!pause) pause=mypause;
redraw=1;
clearspritelist();
while(!exitflag) {
if(redraw) {
drawmenu(selected);
redraw=0;
}
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:
if (MENU_MAIN == whichmenu && menuexit != selected) {
selected = menuexit;
redraw = 1;
break;
}
menudelta = 1;
return menuexit;
}
}
}
menudelta = 0;
return menuexit;
}
static void menustart() {
menunum=-1;
menuput=menustring;
*menuput=0;
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;
}
static void additem(char *item,...) {
char output[256];
va_list ap;
int len;
va_start(ap, item);
len = vsnprintf(output,sizeof(output),item,ap);
if (len >= 256) len = 255; /* truncated string */
additem_s(output, len);
}
static void addexit(char *item,...) {
char output[256];
va_list ap;
int len;
va_start(ap, item);
len = vsnprintf(output,sizeof(output),item,ap);
if (len >= 256) len = 255; /* truncated string */
menuexit = menunum;
additem_s(output, len);
}
/* end generic menu */
/* game menues */
char *densities[]={"PACKED","HIGH","MEDIUM","LOW"};
char *generosities[]={"LOW","MEDIUM","HIGH","RIDICULOUS"};
static void config_menu(void) {
int sel;
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);
sel=domenu(MENU_CONFIG, NULL);
switch (sel) {
case 0:
return;
case 1:
configopts.density+=menudelta;
configopts.density&=3;
break;
case 2:
configopts.generosity+=menudelta;
configopts.generosity&=3;
break;
case 3:
configopts.flames+=menudelta;
configopts.flames&=7;
break;
case 4:
configopts.bombs+=menudelta;
configopts.bombs&=7;
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;
sprintf(temp," %d %s",i+1,name);
drawbigstring(M3X,M3Y+(i+2)*bigfontyspace,temp);
}
copyup();
}
static void host_game(void) {
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()) {
run_network_game();
return;
}
send_invites();
draw_host_game();
}
}
if (!handle_joins()) continue;
send_invites();
draw_host_game();
}
}
static void drawjoinscreen(void) {
int i;
char name[17];
char temp[64];
#define JX (IXSIZE/3)
#define JY (IYSIZE/4)
clear();
centerbig(20,"JOIN NETWORK GAME");
drawbigstring(JX,JY,"SLOT NAME");
for (i = 0; i < MAXNETNODES; ++i) {
if(!netnodes[i].used) continue;
memmove(name,netnodes[i].name,16);
name[16]=0;
sprintf(temp," %d %s",i+1,name);
drawbigstring(JX,JY+(i+1)*bigfontyspace,temp);
}
}
static int tryjoin(int which) {
int res;
if (0 == (res = send_join(&gamelistentries[which].netname, playername))) {
return 0;
}
while (!exitflag) {
switch (res) {
case 1:
failure("Game closed");
return 0;
case 2:
drawjoinscreen();
copyup();
break;
case 3: return 1;
default: break;
}
scaninput();
while(anydown()) {
switch(takedown()) {
case 0x1b:
send_quit();
return 0;
}
}
res=scaninvite(200);
}
return 0;
}
static int join_game_pause(void) {
if (find_more_games()) return 0;
mypause();
return 1;
}
static void join_game(void) {
int i;
int sel = -1;
if (!searchgames()) {
return;
}
menuhistory[MENU_JOIN] = 0;
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);
}
addexit("EXIT");
}
sel = domenu(MENU_JOIN, join_game_pause);
if (menudelta < 0) sel = -1;
}
stop_search();
if(menuexit == sel || !gamelistsize) {
return;
}
if(!tryjoin(sel)) {
return;
}
run_network_game();
}
void mainloop(void) {
int sel;
exitflag = 0;
while(!exitflag) {
menustart();
additem("BOMBER MAIN MENU");
additem("EXIT GAME");
additem("START SINGLE PLAYER GAME");
additem("OPTIONS");
// additem("REMAP MOVEMENT KEYS");
additem("START NETWORK GAME");
additem("JOIN NETWORK GAME");
sel=domenu(MENU_MAIN, NULL);
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;
}
}
}