// Filename : MENU.C // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : B2 menu system #include "menu.h" // Variables defined in other modules extern OBJECT_LIST_HEADER objects_list,paused_objects; extern SPRITE_DATA_INFO font_sprite_info; extern BRIGHTNESS brightness[]; extern PROGRAM_DATA pd; extern GAME_DATA gd; extern SOUND_DATA *sounds; extern VOLUME menu_volume; // Variables for this module MENU menus[MAX_NO_MENUS]={{0,0,200,100,4,0,40,MT_NONE,1}, {0,0,200,100,4,0,40,MT_MAIN,1}, {0,0,200,100,3,0,40,MT_OPTIONS,1}, {0,0,200,100,4,0,40,MT_OPTIONS,1}, {0,0,200,100,2,0,40,MT_MCARD,1}, {0,0,200,100,3,0,40,MT_NONE,1}, {0,0,200,100,3,0,40,MT_PAUSE,1}, {0,0,200,100,4,0,40,MT_POPTIONS,1}, {0,0,200,100,4,0,40,MT_POPTIONS,1}}; MENU_ITEM menu_items[MAX_NO_MENUS*MAX_NO_MENU_ITEMS]={{"Play Game",MenuPlayGame,MT_NONE,1}, {"About Bouncer 2",MenuAboutB2,MT_NONE,1}, {"Options",0,MT_OPTIONS,1}, {"Help",MenuInstructions,MT_NONE,1}, {0,0,MT_NONE,0}, {"Position Screen",MenuPositionScreen,MT_NONE,1}, {"Difficulty",0,MT_DIFFICULTY,1}, {"Memory Card",0,MT_MCARD,1}, {"Main Menu",0,MT_MAIN,1}, {0,0,MT_NONE,0}, {"Easy",MenuEasy,MT_MAIN,1}, {"Medium",MenuMedium,MT_MAIN,1}, {"Hard",MenuHard,MT_MAIN,1}, {0,0,MT_NONE,0}, {0,0,MT_NONE,0}, {"Save Game",MenuSaveGame,MT_SMCARD,1}, {"Load Game",MenuLoadGame,MT_SMCARD,1}, {"Format",MenuFormatCard,MT_SMCARD,1}, {"Main Menu",0,MT_MAIN,1}, {0,0,MT_NONE,0}, {"Memory Card 1",MenuMemoryCard1,MT_NONE,1}, {"Memory Card 2",MenuMemoryCard2,MT_NONE,1}, {0,0,MT_NONE,0}, {0,0,MT_NONE,0}, {0,0,MT_NONE,0}, {"Resume Game",MenuResumeGame,MT_NONE,1}, {"Options",0,MT_POPTIONS,1}, {"Exit Game",MenuExitGame,MT_NONE,1}, {0,0,MT_NONE,0}, {0,0,MT_NONE,0}, {"Position Screen",MenuPositionScreen,MT_NONE,1}, {"Memory Card",0,MT_PMCARD,1}, {"Back",0,MT_PAUSE,1}, {0,0,MT_NONE,0}, {0,0,MT_NONE,0}, {"Easy",MenuEasy,MT_PAUSE,1}, {"Medium",MenuMedium,MT_PAUSE,1}, {"Hard",MenuHard,MT_PAUSE,1}, {0,0,MT_NONE,0}, {0,0,MT_NONE,0}, {"Save Game",MenuSaveGame,MT_SMCARD,1}, {"Load Game",MenuLoadGame,MT_SMCARD,1}, {"Format",MenuFormatCard,MT_SMCARD,1}, {"Back",0,MT_POPTIONS,1}, {0,0,MT_NONE,0}}; OBJECT_LIST_HEADER menu_objects; OBJECT_STRING *menu_strings; VECTOR menu_pos={60,-100,0}; u_word current_menu=0; u_byte menus_active=0; FONT_INFO menu_font; // Function : CreateMenu() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Create all objects needed for a menu // Parameters : l - object list // pos - top left corner of menu // menu_no - menu to create // Returns : Pointer to objects that make menu strings // Notes : None OBJECT_STRING *CreateMenu(OBJECT_LIST_HEADER *l,VECTOR *pos,u_word menu_no) { static OBJECT_STRING menu_strings[MAX_NO_MENU_ITEMS]; OBJECT *o; VECTOR p; u_word no_items,item,i,j,w; if(gd.cheats_on&CC_MEMORYCARDS_ACTIVE) SetMemoryCardsMenu(1); else SetMemoryCardsMenu(0); p.vx=pos->vx+menus[menu_no].area.x; p.vy=pos->vy; menus[menu_no].menu_pos=0; no_items=menus[menu_no].no_items; for(i=0;ivx+menus[menu_no].area.x+((menus[menu_no].area.w-w)>>1); } PrintString(menu_items[item].string,&menu_font,&p,&menu_strings[i]); p.vy+=menus[menu_no].y_spacing; if(menu_items[item].active) SetMenuObject(&menus[menu_no],&menu_strings[i],menu_no,1); else SetMenuObject(&menus[menu_no],&menu_strings[i],menu_no,0); } // Flag the first object of the first menu option menu_strings[i-1].start->extra[0]=1; return(&menu_strings[0]); } // Function : ShowCurrentMenuItem() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Highlight the current option // Parameters : m - pointer to menus // s - pointer to menu strings // menu_no - number of menu // Returns : None // Notes : None void ShowCurrentMenuItem(MENU *m,OBJECT_STRING *s,u_word menu_no) { OBJECT *o; u_byte i; o=s[m[menu_no].menu_pos].start; for(i=0;iot_offset++; StartObjectFading(o); o->type.gss.attribute=0; if(o->extra[1]) o->direction=2; else o->direction=1; o=o->next; } } // Function : HideCurrentMenuItem() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Hides the current option // Parameters : m - pointer to menus // s - pointer to menu strings // menu_no - number of menu // Returns : None // Notes : None void HideCurrentMenuItem(MENU *m,OBJECT_STRING *s,u_word menu_no) { OBJECT *o; u_byte i; o=s[m[menu_no].menu_pos].start; for(i=0;iot_offset--; o->is_fading=1; if(o->extra[1]) o->direction=2; else o->direction=0; o=o->next; } } // Function : ClearMenu() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Clears all objects used in a menu // Parameters : l - pointer to object list used for menus // Returns : None // Notes : None void ClearMenu(OBJECT_LIST_HEADER *l) { OBJECT *next,*o=l->start; PARTICLE_EXPLOSION explosion; menus_active=0; while(o) { next=o->next; if(!gd.paused) SetParticleExplosion(&explosion,&objects_list,HandleMenuExplosionFragment,5,280,3,3,0,0); else SetParticleExplosion(&explosion,&paused_objects,HandleMenuExplosionFragment,5,280,3,3,0,0); setVECTOR(&explosion.maxvel,4,6,0); setVECTOR(&explosion.acc,0,0.2*FPN24_8,0); explosion.b.r=o->brightness.r; explosion.b.g=o->brightness.g; explosion.b.b=o->brightness.b; setRECT(&explosion.r,o->screen.vx,o->screen.vy,16,16); CreateParticleExplosion(&explosion); RemoveObjectFromList(&menu_objects,o); o=next; } } // Function : StartMenuBouncing() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Starts a menu // Parameters : l - pointer to object list used for menus // Returns : None // Notes : None void StartMenuBouncing(OBJECT_LIST_HEADER *l) { OBJECT *o=l->start; while(o) { o->active=1; o->f=HandleMenuObject; //SetObjectsBrightness(o,&brightness[MENU_TEXT_BRIGHTNESS]); SetObjectsBrightness(o,&brightness[GAME_RED_BRIGHTNESS]); SetObjectsAcceleration(o,0,0.1,0); o->allow_fading=1; o->is_fading=1; //o->direction=0; o=o->next; } } // Function : HandleMenu() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Makes menu operational // Parameters : p - pointer to program data // s - pointer to menu strings // menu_no - number of menu to handle // Returns : None // Notes : None void HandleMenu(PROGRAM_DATA *p,OBJECT_STRING *s,u_word menu_no) { MENU_ITEM *item; // Only allow the user to make a selection when the menu is on screen if(menus_active) { // Move menu up if(p->pad&PADup && !(p->buttons_down&PADup)) { HideCurrentMenuItem(&menus[0],s,menu_no); menus[menu_no].menu_pos--; if(menu_items[(menu_no*MAX_NO_MENU_ITEMS)+menus[menu_no].menu_pos].active==0) menus[menu_no].menu_pos--; if(menus[menu_no].menu_pos<0) menus[menu_no].menu_pos=menus[menu_no].no_items-1; ShowCurrentMenuItem(&menus[0],s,menu_no); PlaySoundEffect(sounds,&menu_volume,SFX_MENU_MOVE); } // move menu down if(p->pad&PADdown && !(p->buttons_down&PADdown)) { HideCurrentMenuItem(&menus[0],s,menu_no); menus[menu_no].menu_pos++; if(menu_items[(menu_no*MAX_NO_MENU_ITEMS)+menus[menu_no].menu_pos].active==0) menus[menu_no].menu_pos++; if(menus[menu_no].menu_pos>menus[menu_no].no_items-1) menus[menu_no].menu_pos=0; ShowCurrentMenuItem(&menus[0],s,menu_no); PlaySoundEffect(sounds,&menu_volume,SFX_MENU_MOVE); } // Select the current menu option item=&menu_items[(menu_no*MAX_NO_MENU_ITEMS)+menus[menu_no].menu_pos]; if(p->pad&PADcross && !(p->buttons_down&PADcross)) { void (*f)(void); if(item->active) { if(f=item->f) { f(); ClearMenu(&menu_objects); } // Does it have a sub menu if(item->next_menu>=0) { ClearMenu(&menu_objects); current_menu=item->next_menu; menu_pos.vy=-(menus[current_menu].no_items*menus[current_menu].y_spacing+30); menu_strings=CreateMenu(&menu_objects,&menu_pos,current_menu); StartMenuBouncing(&menu_objects); menus[current_menu].menu_pos=0; ShowCurrentMenuItem(&menus[0],menu_strings,current_menu); } PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } else PlaySoundEffect(sounds,&menu_volume,SFX_MENU_CANCEL); } // Go back to previous menu if(p->pad&PADtriangle && !(p->buttons_down&PADtriangle)) { if(menus[current_menu].previous>=0) { // Change menus ClearMenu(&menu_objects); current_menu=menus[menu_no].previous; menu_pos.vy=-(menus[current_menu].no_items*menus[current_menu].y_spacing+30); menu_strings=CreateMenu(&menu_objects,&menu_pos,current_menu); StartMenuBouncing(&menu_objects); menus[current_menu].menu_pos=0; ShowCurrentMenuItem(&menus[0],menu_strings,current_menu); PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } } } } // Function : HandleMenuObject() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Control all the objects which make up a menu // Parameters : o - pointer to object to handle // Returns : None // Notes : None void HandleMenuObject(OBJECT *o) { if(o->screen.vy>180) { o->screen.vy=180; o->position.vy=180<velocity.vy=-(5<extra[0]) PlaySoundEffect(sounds,&menu_volume,SFX_MENU_BOUNCE); } if(o->is_fading && o->screen.vy>-32) { switch(o->direction) { case 0: FadeObjectBrightness(o,&brightness[MENU_TEXT_BRIGHTNESS],30<direction) // FadeObjectBrightness(o,&brightness[MENU_MAX_BRIGHTNESS],30<type.p.timer>0) o->type.p.timer--; // Kill fragment if(!o->type.p.timer || !is_fading || o->screen.vx<0 || o->screen.vx>pd.screen.w || o->screen.vy<0 || o->screen.vy>pd.screen.h) { if(!gd.paused) RemoveObjectFromList(&objects_list,o); else RemoveObjectFromList(&paused_objects,o); } } // Function : InitMenus() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Initialise the menus // Parameters : None // Returns : None // Notes : None void InitMenus(void) { InitObjectList(&menu_objects); SetFontInfo(&menu_font,&font_sprite_info,&menu_objects,16,16,&brightness[MENU_TEXT_BRIGHTNESS],ONE*2,ONE*2); } // Function : SortMenus() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Add menus to the ordering table // Parameters : ot - pointer to ordering table // priority - ordering table depth // Returns : None // Notes : None void SortMenus(GsOT *ot,u_word priority) { UpdateObjects(&menu_objects); SortObjects(&menu_objects,ot,priority); } // Function : UpdateMenus() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Gives control to menus // Parameters : p - pointer to program data // Returns : None // Notes : None void UpdateMenus(PROGRAM_DATA *p) { HandleMenu(p,menu_strings,current_menu); } // Function : KillMenus() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Destory all menu objects // Parameters : None // Returns : None // Notes : None void KillMenus(void) { ClearMenu(&menu_objects); } // Function : StartMenus() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Activate menu system // Parameters : None // Returns : None // Notes : None void StartMenus(void) { menu_pos.vy=-(menus[current_menu].no_items*menus[current_menu].y_spacing+30); menu_strings=CreateMenu(&menu_objects,&menu_pos,current_menu); StartMenuBouncing(&menu_objects); ShowCurrentMenuItem(&menus[0],menu_strings,current_menu); } // Function : DisplayMenus() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Display menu system // Parameters : p - pointer to program data // ot - pointer to ordering table // priority - ordering table depth // Returns : None // Notes : None void DisplayMenus(PROGRAM_DATA *p,GsOT *ot,u_word priority) { UpdateMenus(p); SortMenus(ot,priority); } // Function : MenuPlayGame() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Set up a new game // Parameters : None // Returns : None // Notes : None void MenuPlayGame(void) { gd.no_lives=DEFAULT_NO_LIVES; gd.no_bombs=DEFAULT_NO_BOMBS; switch(gd.difficulty) { case EASY: gd.no_lives++; gd.no_bombs++; break; case HARD: gd.no_lives--; gd.no_bombs--; break; } gd.start_level=0; StartGame(); } // Function : MenuEasy() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Set difficulty to easy // Parameters : None // Returns : None // Notes : None void MenuEasy(void) { gd.difficulty=EASY; } // Function : MenuMedium() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Set difficulty to medium // Parameters : None // Returns : None // Notes : None void MenuMedium(void) { gd.difficulty=MEDIUM; } // Function : MenuHard() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Set difficulty to hard // Parameters : None // Returns : None // Notes : None void MenuHard(void) { gd.difficulty=HARD; } // Function : MenuPositionScreen() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Set the screen position // Parameters : None // Returns : None // Notes : None void MenuPositionScreen(void) { gd.message_mode=MM_POSITION_SCREEN; gd.mode=MESSAGES; CreateMessages(MOVE_SCREEN_MESSAGES,30); } // Function : SetCurrentMenu() // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Sets the current menu // Parameters : n - the new current menu // Returns : None // Notes : None void SetCurrentMenu(u_word n) { current_menu=n; } // Function : MenuAboutB2() // Coded by : Scott Evans // Created/Modified : 13/6/98 // Description : Show messages about game // Parameters : None // Returns : None // Notes : None void MenuAboutB2(void) { gd.message_mode=MM_ABOUT_B2; gd.mode=MESSAGES; CreateMessages(ABOUT_B2_MESSAGES,30); } // Function : MenuInstructions() // Coded by : Scott Evans // Created/Modified : 14/6/98 // Description : Show the instructions // Parameters : None // Returns : None // Notes : None void MenuInstructions(void) { gd.message_mode=MM_INSTRUCTIONS; gd.mode=MESSAGES; CreateMessages(INSTRUCTION_MESSAGES,30); } // Function : MenuSaveGame() // Coded by : Scott Evans // Created/Modified : 21/7/98 // Description : Set save game // Parameters : None // Returns : None // Notes : None void MenuSaveGame(void) { gd.mc_mode=SM_SAVE; } // Function : MenuLoadGame() // Coded by : Scott Evans // Created/Modified : 21/7/98 // Description : Set load game // Parameters : None // Returns : None // Notes : None void MenuLoadGame(void) { gd.mc_mode=SM_LOAD; } // Function : MenuMemoryCard1() // Coded by : Scott Evans // Created/Modified : 21/7/98 // Description : Set memory card 1 // Parameters : None // Returns : None // Notes : None void MenuMemoryCard1(void) { gd.mcard=MC_SLOT0; SetMemoryCardMessages(); } // Function : MenuMemoryCard2() // Coded by : Scott Evans // Created/Modified : 21/7/98 // Description : Set memory card 2 // Parameters : None // Returns : None // Notes : None void MenuMemoryCard2(void) { gd.mcard=MC_SLOT1; SetMemoryCardMessages(); } // Function : SetMemoryCardMessages() // Coded by : Scott Evans // Created/Modified : 21/7/98 // Description : Sets up the messages for memory card operations // Parameters : None // Returns : None // Notes : None void SetMemoryCardMessages(void) { switch(gd.mc_mode) { case SM_LOAD: gd.message_mode=MM_LOADGAME; CreateMessages(LOADGAME_MESSAGES,30); break; case SM_SAVE: gd.message_mode=MM_SAVEGAME; CreateMessages(SAVEGAME_MESSAGES,30); break; case SM_FORMAT: gd.message_mode=MM_FORMAT; CreateMessages(FORMAT_MESSAGES,30); break; } gd.mode=MESSAGES; } // Function : MenuFormatCard() // Coded by : Scott Evans // Created/Modified : 22/7/98 // Description : Set format memory card // Parameters : None // Returns : None // Notes : None void MenuFormatCard(void) { gd.mc_mode=SM_FORMAT; } // Function : MenuResumeGame() // Coded by : Scott Evans // Created/Modified : 28/7/98 // Description : Resumes play after game was paused // Parameters : None // Returns : None // Notes : None void MenuResumeGame(void) { ResumeGame(); } // Function : MenuExitGame() // Coded by : Scott Evans // Created/Modified : 28/7/98 // Description : Exit game back to main menu // Parameters : None // Returns : None // Notes : None void MenuExitGame(void) { gd.message_mode=MM_EXITGAME; gd.mode=MESSAGES; CreateMessages(EXITGAME_MESSAGES,30); } void SetMenuObject(MENU *m,OBJECT_STRING *s,u_word menu_no,long enabled) { OBJECT *o; long i; o=s->start; for(i=0;ilength;i++) { if(enabled) { o->direction=0; o->extra[1]=0; } else { o->direction=2; o->extra[1]=1; } o=o->next; } } void SetMemoryCardsMenu(long mode) { long i; i=(1*MAX_NO_MENU_ITEMS)+2; menu_items[i].active=mode; i=(6*MAX_NO_MENU_ITEMS)+1; menu_items[i].active=mode; }