// Filename : BOUNCER.C // Coded by : Scott Evans // Created/Modified : 6/3/98 // Description : Bouncer 2 #include "bouncer.h" // Variables in other modules extern PERFORMANCE pbloke; extern MENU menus[]; extern OBJECT_LIST_HEADER sound_objects; extern LSGAME_DATA lsgd; // Variables in this module PROGRAM_DATA pd; GAME_DATA gd; BLOKE_DATA bd; DBUFFER *db[2]; OBJECT_LIST_HEADER objects_list,wind_objects_list,paused_objects,info_objects,gun_objects,platform_objects,fan_objects; OBJECT *bat,*bloke,*start_block,*bonus_object; SprImgInfo texture_info[MAX_TEXTURES]; BACKGRND bg; SPRITE_DATA_INFO font_sprite_info,map_blocks_info,game_sprites_info; BRIGHTNESS default_brightness; FONT_INFO game_font,game_info_font; LEVEL_TIMER level_timer; COUNTER *diamond_counter,*score_counter,*block_counter,*max_block_counter,*bonus_counter; OBJECT *diamond_counter_icon,*bonus_counter_icon; SOUND_DATA *sounds; VOLUME game_volume,menu_volume={SFX_MENU_VOLUME,SFX_MENU_VOLUME}; u_long extra_life_score; #ifdef NO_MALLOC GsOT wot[2]; GsOT_TAG wtags[2][1<pb); // Clear ordering table GsClearOt(0,0,db[1]->ot); // Handle the sound objects UpdateSoundEffects(); // When in demo mode, change between menu and highscore table UpdateGameMode(); // Quit the program if(pd.pad&PADstart && !(pd.buttons_down&PADstart)) { if(pd.pad&PADselect) { pd.exit=1; InitLeaving(); } } // Check for the skip level cheat LevelSkipCheat(); // Update objects and add them to the ordering table UpdateAndSortGameObjects(); // Shake the screen MoveScreen(&db[0]); // Wait for drawing and vsync DrawSync(0); pd.vsync=VSync(0); // Switch screens SwapDisplay(db[1],1); // Render objects in ordering table GsDrawOt(db[1]->ot); // Fade the game objects FadeAllObjects(); } // Kill off all objects KillSounds(); KillAllObjects(); #ifdef DEBUG_INFO PrintFM("Completed\n"); #endif } // Function : FadeAllObjects() // Coded by : Scott Evans // Created/Modified : 9/7/98 // Description : Fade the game objects // Parameters : None // Returns : None // Notes : None #define FADE_SPEED 15 void FadeAllObjects(void) { if(bg.block->is_fading) { // Fade all the game objects FadeObjectBrightness(bg.block,&default_brightness,FADE_SPEED<ot,MENUS_OT_DEPTH); break; case HIGHSCORES: DisplayHighScoreTable(db[1]->ot,HIGHSCORES_OT_DEPTH); if(pd.pad&PADcross && !(pd.buttons_down&PADcross)) { InitLeaving(); PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); gd.intro_counter=0; } break; case MESSAGES: DisplayMessages(db[1]->ot,MESSAGES_OT_DEPTH); break; } } else { // Pause the game if(!gd.game_over && !gd.level_complete && !gd.bonus_level && !gd.leaving && !gd.lspr_clear && ((pd.pad&PADstart && !(pd.buttons_down&PADstart)) || gd.pad_status)) PauseGame(); if(gd.game_over) GameOver(); // Udate the clock and counters UpdateLevelTimer(); UpdateCounter(score_counter); // Check for an extra life if(score_counter && score_counter->counter/gd.extra_life_score) { CreateExtraLife(); gd.extra_life_score+=EXTRA_LIFE_SCORE; } UpdateCounter(diamond_counter); UpdateCounter(block_counter); UpdateCounter(max_block_counter); if(gd.bonus_level) UpdateCounter(bonus_counter); // Check for bonus level if(!gd.bonus_level) { switch(block_counter->counter) { // Level is complete case BLOCK_COUNTER_FULL: gd.level_complete=1; CopyBrightness(&default_brightness,&brightness[GAME_DEMO_BRIGHTNESS]); StartObjectFading(bg.block); StopLevelTimer(); // The next level will be a bonus level gd.bonus_level=1; break; // Start flashing the counter case BLOCK_COUNTER_FULL+5: block_counter->type.bar.bar->blink=1; break; } } } } // Function : UpdateAndSortGameObjects() // Coded by : Scott Evans // Created/Modified : 9/7/98 // Description : Moves, animates and registers objects in ordering table // Parameters : None // Returns : None // Notes : None void UpdateAndSortGameObjects(void) { if(!gd.paused && !gd.level_complete) { // This means we have finished the level if(diamond_counter && !diamond_counter->counter) { // Get ready for the end of level stuff gd.level_complete=1; CopyBrightness(&default_brightness,&brightness[GAME_DEMO_BRIGHTNESS]); StartObjectFading(bg.block); StopLevelTimer(); } // Move and animate objects UpdateObjects(&objects_list); UpdateObjects(&gun_objects); UpdateObjects(&platform_objects); UpdateObjects(&fan_objects); UpdateObjects(&info_objects); // Apply the virtual winds ApplyWindsToObjects(&wind_objects_list,&objects_list); } else { // The game is paused UpdateObjects(&paused_objects); UpdateObjects(&info_objects); // Only draw "paused mode" objects SortObjects(&paused_objects,db[1]->ot,OBJECTS_OT_DEPTH); // Show the end of level stuff if(gd.level_complete) { if(!gd.leaving) LevelComplete(); } // Check for cheats CheckForCheats(); } // Put all the game objects into the ordering table SortObjects(&objects_list,db[1]->ot,OBJECTS_OT_DEPTH); SortObjects(&gun_objects,db[1]->ot,OBJECTS_OT_DEPTH); SortObjects(&platform_objects,db[1]->ot,OBJECTS_OT_DEPTH); SortObjects(&fan_objects,db[1]->ot,OBJECTS_OT_DEPTH); SortObjects(&info_objects,db[1]->ot,OBJECTS_OT_DEPTH); // Add background to ordering table SortBackground(&bg,db[1]->ot,BACKGROUND_OT_DEPTH); // Add the bounding boxes to the ordering table #ifdef DEBUG SortBoundingBoxes(db[1]->ot,DEBUG_OT_DEPTH); #endif } // Function : InitStartPlay() // Coded by : Scott Evans // Created/Modified : 7/3/98 // Description : Initialise the game ready to play // Parameters : None // Returns : None // Notes : None void InitStartPlay(void) { pd.running=1; gd.level_complete=0; gd.paused=0; gd.bonus_multiplier=1; gd.multiplier_sprite=0; gd.kill_fireworks=0; gd.show_intro=0; gd.lspr_clear=0; gd.block_sp=0; if(gd.just_loaded) { // Game has just been loaded so restore screen position while screen is not visible pd.screen_xoff=lsgd.sx; pd.screen_yoff=lsgd.sy; gd.just_loaded=0; } // Kill all the bloke effects bd.super=0; bd.invisible=0; bd.teleporting=0; bd.shield=0; // Is this demo mode if(gd.demo_mode) { // Set the volume for the game sound effects game_volume.left=SFX_DEMO_VOLUME; game_volume.right=SFX_DEMO_VOLUME; CopyBrightness(&default_brightness,&brightness[GAME_DEMO_BRIGHTNESS]); do { gd.level_no=rand()%(gd.no_levels-MAX_BONUS_LEVELS); }while(gd.level_no==26); gd.timer=MODE_CHANGE_TIMER; StopLevelTimer(); score_counter=diamond_counter=block_counter=max_block_counter=0; // Set up the menus or highscore table switch(gd.mode) { case MENUS: SetCurrentMenu(MT_MAIN); StartMenus(); break; case HIGHSCORES: CreateHighScoreTable(); break; } } else { // Record the last level played gd.last_level=gd.level_no; // Set the volume for the game sound effects game_volume.left=SFX_GAME_VOLUME; game_volume.right=SFX_GAME_VOLUME; CopyBrightness(&default_brightness,&brightness[GAME_NORMAL_BRIGHTNESS]); gd.timer=0; InitLevelTimer(&level_timer); level_timer.no_seconds=0; SetLevelTimer(&level_timer); if(!gd.bonus_level) { CreateDiamondCounter(); CreateBlockCounter(); InitLives(); InitBombs(); } else { CreateBonusLevelCounter(); } CreateScoreCounter(); MoveScoreInfoObjects(START_MOVING_ON_SCREEN,0); // Set the number of time bonuses dropped when almost out of time if(gd.bonus_level) { // Set bonus level time limit AddToTime(BONUS_TIME_LIMIT); CreateBonusLevelSprites(); diamond_counter=0; } else { switch(gd.difficulty) { case EASY: gd.no_time_bonuses=10; AddToTime(level_times[gd.level_no]+MINUTE+15); break; case MEDIUM: gd.no_time_bonuses=5; AddToTime(level_times[gd.level_no]+MINUTE-15); break; case HARD: gd.no_time_bonuses=2; AddToTime(level_times[gd.level_no]); break; } if(gd.level_no==4 || gd.level_no==9 || gd.level_no==14 || gd.level_no==19) level_timer.extra=level_times[gd.level_no]; CreateLevelSprites(gd.level_no); } } // Set the background brightness SetObjectsBrightness(bg.block,&brightness[GAME_MIN_BRIGHTNESS]); StartObjectFading(bg.block); // Set up the level to be played InitLevel(&bg,levels_header,gd.level_no); if(!gd.demo_mode && !gd.bonus_level) AddToCounter(diamond_counter,bg.no_diamonds); // Create the game sprites bat=CreateBatSprite(); SetObjectsBrightness(bat,&brightness[GAME_MIN_BRIGHTNESS]); start_block=CreateStartBlockSprite(); SetObjectsBrightness(start_block,&brightness[GAME_MIN_BRIGHTNESS]); if(gd.bonus_type!=BT_CATCH) { bloke=CreateBlokeSprite(); SetObjectsBrightness(bloke,&brightness[GAME_MIN_BRIGHTNESS]); SetObjectsPosition(bloke,start_block->screen.vx,start_block->screen.vy+5-bloke->h,0); } else { start_block->dying=1; start_block->active=0; start_block->visible=0; } // Set up the bonus level InitBonusLevel(gd.bonus_type); // Set up collision detection stuff SetBoundingBoxes(); // Set the performance levels for the bloke and the bat SetPerformanceLevels(gd.difficulty); #ifdef DEBUG_INFO PrintFM("Completed\n"); #endif } // Function : InitGame() // Coded by : Scott Evans // Created/Modified : 7/3/98 // Description : Initialise data for game // Parameters : None // Returns : None // Notes : None void InitGame(void) { u_word n; // Initialise the font textures n=InitGameFont(0); SetFontInfo(&game_font,&font_sprite_info,&objects_list,16,16,&brightness[GAME_TEXT_BRIGHTNESS],ONE*2,ONE*2); SetFontInfo(&game_info_font,&font_sprite_info,&info_objects,8,8,&brightness[GAME_WHITE_BRIGHTNESS],ONE,ONE); // Initialise the background textures n+=InitGameBackground(n); // Initialise game sprite textures InitGameSprites(n); InitHighScoreTable(); InitMenus(); InitMessageSystem(); InitLSGameData(); } // Function : InitGameFont() // Coded by : Scott Evans // Created/Modified : 7/3/98 // Description : Initialise the font textures // Parameters : n - number of textures already initialised // Returns : None // Notes : None u_word InitGameFont(u_word n) { SetSpriteDataInfo(&font_sprite_info,FONT_TPAGE_X,FONT_TPAGE_Y,FONT_CLUT_X,FONT_CLUT_Y,&texture_info[n]); return(InitSpriteData(font_header,&font_sprite_info,0)); } // Function : InitGameSprites() // Coded by : Scott Evans // Created/Modified : 7/3/98 // Description : Initialise all the game sprite textures // Parameters : n - number of textures already initialised // Returns : None // Notes : None u_word InitGameSprites(u_word n) { SetSpriteDataInfo(&game_sprites_info,GAME_SPRITES_TPAGE_X,GAME_SPRITES_TPAGE_Y,GAME_SPRITES_CLUT_X,GAME_SPRITES_CLUT_Y,&texture_info[n]); return(InitSpriteData(game_sprites_header,&game_sprites_info,0)); } // Function : InitGameBackground() // Coded by : Scott Evans // Created/Modified : 7/3/98 // Description : Initialise the map block textures // Parameters : n - number of textures already initialised // Returns : None // Notes : None u_word InitGameBackground(u_word n) { RECT r={0,0,MAX_MAP_SCREEN_COLUMNS,MAX_MAP_SCREEN_ROWS}; u_word no_textures; SetSpriteDataInfo(&map_blocks_info,MAP_BLOCKS_TPAGE_X,MAP_BLOCKS_TPAGE_Y,MAP_BLOCKS_CLUT_X,MAP_BLOCKS_CLUT_Y,&texture_info[n]); no_textures=InitSpriteData(map_blocks_header,&map_blocks_info,1); InitBackground(&map_blocks_info,&bg,&r); return(no_textures); } // Function : InitGameData() // Coded by : Scott Evans // Created/Modified : 7/3/98 // Description : Set up some game variables // Parameters : g - pointer to game data structure // Returns : None // Notes : None void InitGameData(GAME_DATA *g) { // Clear game data information bzero((u_byte *)g,sizeof(GAME_DATA)); // Set initial values g->no_lives=DEFAULT_NO_LIVES; g->no_bombs=DEFAULT_NO_BOMBS; g->difficulty=MEDIUM; g->mode=MENUS; g->demo_mode=1; g->bonus_multiplier=1; g->start_level=0; g->bonus_type=BT_NONE; g->block_sp=0; } // Function : InitLeaving() // Coded by : Scott Evans // Created/Modified : 19/3/98 // Description : Set up the leaving process // Parameters : None // Returns : None // Notes : None void InitLeaving(void) { // Get ready to fade everything to black CopyBrightness(&default_brightness,&brightness[GAME_MIN_BRIGHTNESS]); StartObjectFading(bg.block); gd.leaving=1; // Clear the menus or highscore table switch(gd.mode) { case MENUS: KillMenus(); PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); break; case HIGHSCORES: KillHighScoreTable(); PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); break; } // Change the mode if(gd.demo_mode) gd.mode=++gd.mode&1; if(bloke->type.s.animation_on && !gd.level_complete && !gd.demo_mode) KillBloke(bloke); bat->can_move=0; // Make sure block counter stops flashing if(block_counter) block_counter->type.bar.bar->blink=0; #ifdef DEBUG_INFO PrintFM("Completed\n"); #endif } // Function : ShakeScreen() // Coded by : Scott Evans // Created/Modified : 21/3/98 // Description : Moves the display area // Parameters : xd,yd - amount to move display // speed - how often to move display // Returns : None // Notes : None void ShakeScreen(u_byte xd,u_byte yd,u_byte speed) { static u_byte counter=1; // Move the display area of both buffers in opposite directions if(counter) { db[0]->dispenv.screen.x-=xd; db[0]->dispenv.screen.y-=yd; db[1]->dispenv.screen.x+=xd; db[1]->dispenv.screen.y+=yd; } else { db[1]->dispenv.screen.x-=xd; db[1]->dispenv.screen.y-=yd; db[0]->dispenv.screen.x+=xd; db[0]->dispenv.screen.y+=yd; } // How quick to move display if(GetTimer()%speed==0) counter++,counter%=2; } // Function : PauseGame() // Coded by : Scott Evans // Created/Modified : 14/4/98 // Description : Toggles pause // Parameters : None // Returns : None // Notes : None void PauseGame(void) { gd.paused=1; // Fade the game down CopyBrightness(&default_brightness,&brightness[GAME_DEMO_BRIGHTNESS]); StartObjectFading(bg.block); // Bring on the paused menu gd.mode=MENUS; gd.shake_screen=0; SetCurrentMenu(MT_PAUSE); StartMenus(); StopLevelTimer(); } // Function : ResumeGame() // Coded by : Scott Evans // Created/Modified : 28/4/98 // Description : Resume game after it has been paused // Parameters : None // Returns : None // Notes : None void ResumeGame(void) { gd.paused=0; CopyBrightness(&default_brightness,&brightness[GAME_NORMAL_BRIGHTNESS]); StartObjectFading(bg.block); // Only start clock if game has been started if(gd.game_started) StartLevelTimer(); pd.buttons_down=AutoRepeat(pd.pad,BUTTON_REPEAT_RATE); pd.pad=PadRead(0); } // Function : InitLevelTimer() // Coded by : Scott Evans // Created/Modified : 20/4/98 // Description : Initialise the level time limit // Parameters : lt - pointer to timer data structure // Returns : None // Notes : None void InitLevelTimer(LEVEL_TIMER *lt) { OBJECT *o,*shadow; u_byte i; word x,y; x=TIMER_X; y=TIMER_Y-OFF_SCREEN_Y; // Create the objects used for the timer for(i=0;i<4;i++) { o=CreateCounterSprite(&info_objects,x,y); if(!i) lt->time_string.start=o; o->allow_fading=0; SetObjectsOtOffset(o,1); o->tmp=6; o->direction=FINISHED; SetObjectsHandler(o,HandleScoreInfoObjects); // Position the shadow objects if(i<2) { shadow=CreateCounterSprite(&info_objects,x+2,y+2); shadow->direction=FINISHED; shadow->tmp=7; SetObjectsHandler(shadow,HandleScoreInfoObjects); o->type.gss.scalex=shadow->type.gss.scalex=ONE<<1; o->type.gss.scaley=shadow->type.gss.scaley=ONE<<1; x+=o->w; } else { shadow=CreateCounterSprite(&info_objects,x+2,y+2); shadow->direction=FINISHED; shadow->tmp=8; SetObjectsHandler(shadow,HandleScoreInfoObjects); o->type.gss.scalex=shadow->type.gss.scalex=ONE; o->type.gss.scaley=shadow->type.gss.scaley=ONE; x+=o->w>>1; } o->parent=shadow; shadow->allow_fading=0; shadow->type.gss.attribute=TRANSPARENCY_ON|BG_MINUS_SP; } lt->time_string.length=4; lt->going=0; lt->extra=0; } // Function : SetLevelTimer() // Coded by : Scott Evans // Created/Modified : 20/4/98 // Description : Display the correct timer value // Parameters : lt - pointer to timer data structure // Returns : None // Notes : None void SetLevelTimer(LEVEL_TIMER *lt) { OBJECT *o; u_word mins,secs,n; u_byte d,d1; n=MapCharacterToImage("0"); mins=lt->no_seconds/60; o=lt->time_string.start; // Work out each digit d=mins/10; d1=mins%10; // Change the graphic o->type.gss.u=font_sprite_info.offsets[n+d].u; o->type.gss.v=font_sprite_info.offsets[n+d].v; o->parent->type.gss.u=font_sprite_info.offsets[n+d].u; o->parent->type.gss.v=font_sprite_info.offsets[n+d].v; o=o->next; o=o->next; o->type.gss.u=font_sprite_info.offsets[n+d1].u; o->type.gss.v=font_sprite_info.offsets[n+d1].v; o->parent->type.gss.u=font_sprite_info.offsets[n+d1].u; o->parent->type.gss.v=font_sprite_info.offsets[n+d1].v; secs=lt->no_seconds%60; o=lt->time_string.start; o=o->next; o=o->next; o=o->next; o=o->next; d=secs/10; d1=secs%10; o->type.gss.u=font_sprite_info.offsets[n+d].u; o->type.gss.v=font_sprite_info.offsets[n+d].v; o->parent->type.gss.u=font_sprite_info.offsets[n+d].u; o->parent->type.gss.v=font_sprite_info.offsets[n+d].v; o=o->next; o=o->next; o->type.gss.u=font_sprite_info.offsets[n+d1].u; o->type.gss.v=font_sprite_info.offsets[n+d1].v; o->parent->type.gss.u=font_sprite_info.offsets[n+d1].u; o->parent->type.gss.v=font_sprite_info.offsets[n+d1].v; } // Function : StartLevelTimer() // Coded by : Scott Evans // Created/Modified : 20/4/98 // Description : Starts the timer // Parameters : None // Returns : None // Notes : None void StartLevelTimer(void) { level_timer.going=1; } // Function : StopLevelTimer() // Coded by : Scott Evans // Created/Modified : 20/4/98 // Description : Stops the timer // Parameters : None // Returns : None // Notes : None void StopLevelTimer(void) { level_timer.going=0; } // Function : AddToTime() // Coded by : Scott Evans // Created/Modified : 20/4/98 // Description : Increase the value of the timer // Parameters : n - number to add to timer // Returns : None // Notes : None void AddToTime(word n) { level_timer.extra+=n; } // Function : UpdateLevelTimer() // Coded by : Scott Evans // Created/Modified : 20/4/98 // Description : Monitor the timer // Parameters : None // Returns : None // Notes : None enum { NO_TIME_LEFT, NOT_MUCH_TIME_LEFT=5 }; void UpdateLevelTimer(void) { u_byte i; // Is there anything to add to timer if(level_timer.extra) { if(level_timer.extra>5) { level_timer.no_seconds+=5; level_timer.extra-=5; } else { level_timer.no_seconds++; level_timer.extra--; } SetLevelTimer(&level_timer); } else { // Each second knock 1 off the timer if(level_timer.going && level_timer.no_seconds && !(gd.cheats_on&CC_INFINITE_TIME)) { if(!(GetTimer()%SECOND)) { //if(level_timer.no_seconds>NOT_MUCH_TIME_LEFT) // PlaySoundEffect(sounds,&game_volume,SFX_CLOCK_TICK); level_timer.no_seconds--; SetLevelTimer(&level_timer); switch(level_timer.no_seconds) { // Run out of time, so game over case NO_TIME_LEFT: if(gd.bonus_level) { // End of bonus level gd.level_complete=1; CopyBrightness(&default_brightness,&brightness[GAME_DEMO_BRIGHTNESS]); StartObjectFading(bg.block); StopLevelTimer(); if(gd.bonus_type==BT_COLLECT) if(bonus_object->extra[1]==1) bonus_object->extra[1]=2; } else { gd.game_over=1; gd.timer=5*SECOND; } break; // The time about to run out warning case NOT_MUCH_TIME_LEFT+1: PlaySoundEffect(sounds,&game_volume,SFX_SIREN); break; // Not much time left so give them a little more time case NOT_MUCH_TIME_LEFT: CreateTimerSprite(&objects_list,NOT_MUCH_TIME_LEFT); if(!gd.bonus_level) { for(i=0;i>4)<<4,0-(rand()%16),EXTRA_TIME_BONUS); // Reduce number of bonuses for next time gd.no_time_bonuses>>=1; if(gd.no_time_bonuses==0) gd.no_time_bonuses=1; } PlaySoundEffect(sounds,&game_volume,SFX_RUNNING_OUT_OF_TIME); break; } } } } } // Function : InitLives() // Coded by : Scott Evans // Created/Modified : 22/4/98 // Description : Create icons for the number of lives // Parameters : None // Returns : None // Notes : None void InitLives(void) { u_byte i; OBJECT *shadow; word x,y; // Create icons and shadows for(i=0;itype.gss.attribute=TRANSPARENCY_ON|BG_MINUS_SP; gd.life_icons[i]->parent=shadow; SetObjectsHandler(gd.life_icons[i],HandleScoreInfoObjects); gd.life_icons[i]->tmp=2; gd.life_icons[i]->direction=FINISHED; SetObjectsHandler(gd.life_icons[i]->parent,HandleScoreInfoObjects); gd.life_icons[i]->parent->tmp=3; gd.life_icons[i]->parent->direction=FINISHED; } } // Function : InitBombs() // Coded by : Scott Evans // Created/Modified : 22/4/98 // Description : Create icons for the number of bombs // Parameters : None // Returns : None // Notes : None void InitBombs(void) { u_byte i; OBJECT *shadow; word x,y; for(i=0;itype.gss.attribute=TRANSPARENCY_ON|BG_MINUS_SP; gd.bomb_icons[i]->parent=shadow; SetObjectsHandler(gd.bomb_icons[i],HandleScoreInfoObjects); gd.bomb_icons[i]->tmp=4; gd.bomb_icons[i]->direction=FINISHED; SetObjectsHandler(gd.bomb_icons[i]->parent,HandleScoreInfoObjects); gd.bomb_icons[i]->parent->tmp=5; gd.bomb_icons[i]->parent->direction=FINISHED; } } // Function : MoveScreen() // Coded by : Scott Evans // Created/Modified : 22/4/98 // Description : Move the screen, shakes it during an explosion // Parameters : db - pointer to double buffer structure // Returns : None // Notes : None void MoveScreen(DBUFFER **db) { // Do we need to shake the screen if(gd.shake_screen) ShakeScreen(1,1,4); else { // Reset the screen position db[0]->dispenv.screen.x=db[1]->dispenv.screen.x=pd.screen_xoff; db[0]->dispenv.screen.y=db[1]->dispenv.screen.y=pd.screen_yoff; } } // Function : LevelComplete() // Coded by : Scott Evans // Created/Modified : 26/4/98 // Description : Do the bit when you complete a level // Parameters : None // Returns : None // Notes : None enum { LC_INIT, LC_NEXT_STATE, LC_INIT_TIME_BONUS, LC_TIME_BONUS, LC_BLOKE_BONUS, LC_INIT_BLOCK_BONUS, LC_BLOCK_BONUS, LC_LEVEL_BONUS, LC_INIT_END, LC_END }; void LevelComplete(void) { static u_byte state=LC_INIT,next_state; static OBJECT_STRING *strings[5]; static COUNTER *counters[5]; static u_word timer,level_bonus; DVECTOR cpos={0,300},pos={0,300}; OBJECT *o; u_byte i,cl; switch(state) { // Initialise the end of level sequence case LC_INIT: gd.shake_screen=0; gd.intro_counter=0; if(gd.cheats_on&CC_BONUS_ON) gd.bonus_level=1; ResetBlockCount(0); // Make sure the score is not still counting score_counter->counter+=score_counter->extra; score_counter->extra=0; // Set up the level complete screen game_font.list=&info_objects; if(gd.bonus_type!=BT_NONE) strings[0]=CreateTextString(&pos,&game_font,"Bonus Level Over",1); else if(gd.level_warp) { gd.level_warp=0; strings[0]=CreateTextString(&pos,&game_font,"Level Warp",1); } else strings[0]=CreateTextString(&pos,&game_font,"Level Complete",1); o=strings[0]->start; // Set each object in the string for(i=0;ilength;i++) { SetObjectsHandler(o,HandleLevelCompleteObject); SetObjectsVelocity(o,0,-9.5,0); SetObjectsAcceleration(o,0,0.2,0); SetObjectsOtOffset(o,1); o->direction=0; o->active=1; o=o->next; } PlaySoundEffect(sounds,&game_volume,SFX_MESSAGE_WOOSH); game_font.list=&objects_list; timer=SECOND*1; next_state=LC_INIT_TIME_BONUS; state=LC_NEXT_STATE; break; // Change to the next state case LC_NEXT_STATE: if(timer) timer--; else state=next_state; break; // Do the time bonus case LC_INIT_TIME_BONUS: if(gd.bonus_type==BT_NONE) { strings[1]=CreateTextString(&pos,&game_info_font,"Time Bonus ",1); cl=3; next_state=LC_TIME_BONUS; } else { if(gd.bonus_type==BT_BLOCK) strings[1]=CreateTextString(&pos,&game_info_font,"Block Bonus ",1); else strings[1]=CreateTextString(&pos,&game_info_font,"Bloke Bonus ",1); cl=4; next_state=LC_BLOKE_BONUS; } o=strings[1]->start; cpos.vx=(o->screen.vx)+(game_info_font.cw*(strings[1]->length+2)); for(i=0;ilength;i++) { SetObjectsHandler(o,HandleLevelCompleteObject); SetObjectsVelocity(o,0,-8.5,0); SetObjectsAcceleration(o,0,0.2,0); SetObjectsOtOffset(o,1); o->direction=1; o->active=1; o=o->next; } counters[0]=CreateCounter(&game_info_font,&cpos,cl,0,DIGIT_COUNTER); o=counters[0]->type.string.start; for(i=0;itype.string.length;i++) { SetObjectsHandler(o,HandleLevelCompleteObject); SetObjectsVelocity(o,0,-8.5,0); SetObjectsAcceleration(o,0,0.2,0); SetObjectsOtOffset(o,1); o->direction=1; o->active=1; o=o->next; } PlaySoundEffect(sounds,&game_volume,SFX_MESSAGE_WOOSH); timer=SECOND*1; state=LC_NEXT_STATE; break; // Calculate the time bonus case LC_TIME_BONUS: if(level_timer.no_seconds) { level_timer.no_seconds--; AddToCounter(counters[0],1); AddToCounter(score_counter,1); // If cross is pressed move on if(pd.pad&PADcross && !(pd.buttons_down&PADcross)) { counters[0]->counter+=(level_timer.no_seconds+1); counters[0]->extra=0; score_counter->extra=0; score_counter->counter+=(level_timer.no_seconds+1); level_timer.no_seconds=0; level_timer.extra=0; } SetLevelTimer(&level_timer); UpdateCounter(counters[0]); PlaySoundEffect(sounds,&game_volume,SFX_COUNTER); } else state=LC_INIT_BLOCK_BONUS; break; // Calculate the bloke bonus case LC_BLOKE_BONUS: if(bonus_counter->counter) { if(!counters[0]->extra) { SubtractFromCounter(bonus_counter,1); AddToCounter(counters[0],50); AddToCounter(score_counter,50); } // If cross is pressed move on if(pd.pad&PADcross && !(pd.buttons_down&PADcross)) { counters[0]->counter+=((bonus_counter->counter*50)+counters[0]->extra); counters[0]->extra=0; score_counter->extra=0; score_counter->counter+=((bonus_counter->counter*50)+counters[0]->extra); bonus_counter->counter=0; bonus_counter->extra=0; } UpdateCounter(counters[0]); PlaySoundEffect(sounds,&game_volume,SFX_COUNTER); } else state=LC_INIT_BLOCK_BONUS; break; // Initialise the block bonus case LC_INIT_BLOCK_BONUS: if(gd.bonus_type==BT_NONE) { strings[2]=CreateTextString(&pos,&game_info_font,"Block Bonus ",1); cl=3; next_state=LC_BLOCK_BONUS; } else { strings[2]=CreateTextString(&pos,&game_info_font,"Level Bonus ",1); cl=4; next_state=LC_LEVEL_BONUS; level_bonus=5000; } o=strings[2]->start; cpos.vx=(o->screen.vx)+(game_info_font.cw*12); for(i=0;ilength;i++) { SetObjectsHandler(o,HandleLevelCompleteObject); SetObjectsVelocity(o,0,-7.5,0); SetObjectsAcceleration(o,0,0.2,0); SetObjectsOtOffset(o,1); o->direction=2; o->active=1; o=o->next; } counters[1]=CreateCounter(&game_info_font,&cpos,cl,0,DIGIT_COUNTER); o=counters[1]->type.string.start; for(i=0;itype.string.length;i++) { SetObjectsHandler(o,HandleLevelCompleteObject); SetObjectsVelocity(o,0,-7.5,0); SetObjectsAcceleration(o,0,0.2,0); SetObjectsOtOffset(o,1); o->direction=2; o->active=1; o=o->next; } PlaySoundEffect(sounds,&game_volume,SFX_MESSAGE_WOOSH); counters[1]->counter=0; SetCounter(counters[1]); timer=SECOND*1; state=LC_NEXT_STATE; break; // Calculate the block bonus case LC_BLOCK_BONUS: if(max_block_counter->counter<0) { AddToCounter(counters[1],1); AddToCounter(score_counter,1); AddToCounter(max_block_counter,1); if(pd.pad&PADcross && !(pd.buttons_down&PADcross)) { score_counter->extra=0; score_counter->counter+=(abs(max_block_counter->counter)+1); counters[1]->extra=0; counters[1]->counter+=(abs(max_block_counter->counter)+1); max_block_counter->extra=0; max_block_counter->counter=0; } UpdateCounter(counters[1]); PlaySoundEffect(sounds,&game_volume,SFX_COUNTER); } else state=LC_INIT_END; break; // Calculate the level bonus case LC_LEVEL_BONUS: if(level_bonus) { level_bonus--; AddToCounter(counters[1],1); AddToCounter(score_counter,1); if(pd.pad&PADcross && !(pd.buttons_down&PADcross)) { score_counter->extra=0; score_counter->counter+=level_bonus+1; counters[1]->extra=0; counters[1]->counter+=level_bonus+1; level_bonus=0; } UpdateCounter(counters[1]); PlaySoundEffect(sounds,&game_volume,SFX_COUNTER); } else state=LC_INIT_END; break; // End bit case LC_INIT_END: game_font.list=&info_objects; strings[3]=CreateTextString(&pos,&game_font,"Press &",1); o=strings[3]->start; for(i=0;ilength;i++) { SetObjectsHandler(o,HandleLevelCompleteObject); SetObjectsVelocity(o,0,-6.5,0); SetObjectsAcceleration(o,0,0.2,0); SetObjectsOtOffset(o,1); o->direction=3; o->active=1; o=o->next; } PlaySoundEffect(sounds,&game_volume,SFX_MESSAGE_WOOSH); game_font.list=&objects_list; state=LC_END; break; // Wait for button press case LC_END: if(pd.pad&PADcross && !(pd.buttons_down&PADcross)) { InitLeaving(); // Select the next level if(gd.bonus_type==BT_NONE) { gd.level_no=(++gd.level_no)%(gd.no_levels-MAX_BONUS_LEVELS); } else { gd.level_no=gd.next_level; gd.bonus_level=0; } state=LC_INIT; gd.score=score_counter->counter; // Get ready to move all the objects off screen for(o=strings[3]->start,i=0;ilength;i++) { o->direction=4; o=o->next; } for(o=strings[2]->start,i=0;ilength;i++) { o->direction=4; o=o->next; } for(o=strings[1]->start,i=0;ilength;i++) { o->direction=4; o=o->next; } for(o=strings[0]->start,i=0;ilength;i++) { o->direction=4; o=o->next; } for(o=counters[1]->type.string.start,i=0;itype.string.length;i++) { o->direction=4; o=o->next; } for(o=counters[0]->type.string.start,i=0;itype.string.length;i++) { o->direction=4; o=o->next; } MoveScoreInfoObjects(START_MOVING_OFF_SCREEN,0); // The next level is a bonus level if(gd.bonus_level) { gd.next_level=gd.level_no; gd.level_no=bonus_levels[rand()%MAX_BONUS_LEVELS]; gd.bonus_type=(gd.level_no-START_BONUS_LEVEL)+1; #ifdef DEBUG_INFO sprintf(fm_string,"bonus level=%d\n",gd.level_no); PrintFM(fm_string); #endif } else gd.bonus_type=BT_NONE; PlaySoundEffect(sounds,&game_volume,SFX_MENU_SELECT); #ifdef DEBUG_INFO PrintFM("Complete\n"); #endif } break; } } // Function : CreateCounter() // Coded by : Scott Evans // Created/Modified : 26/4/98 // Description : Make a counter // Parameters : f - the font to use // pos - screen position // n - number of digits in counter // shadow - do we want a shadow // type - type of counter // Returns : Pointer to new counter // Notes : None COUNTER *CreateCounter(FONT_INFO *f,DVECTOR *pos,word n,u_byte shadow,u_byte type) { OBJECT *o; static COUNTER counters[MAX_COUNTERS]; static u_byte no_counters=0; u_byte i; word x; // Get a free counter no_counters=(++no_counters)%MAX_COUNTERS; // Initialise it counters[no_counters].counter=0; counters[no_counters].extra=0; counters[no_counters].has_shadow=0; counters[no_counters].type_code=type; if(type==DIGIT_COUNTER) { x=pos->vx+((n-1)*f->cw); // Create the digits for the counter counters[no_counters].type.string.length=n; for(i=0;ilist,x,pos->vy); o->allow_fading=0; SetObjectsOtOffset(o,1); if(!i) counters[no_counters].type.string.start=o; // Make a shadow if needed if(shadow) { counters[no_counters].has_shadow=1; o->parent=CreateCounterSprite(f->list,x+2,pos->vy+2); o->parent->allow_fading=0; o->parent->type.gss.attribute=TRANSPARENCY_ON|BG_MINUS_SP; } x-=f->cw; } } #ifdef DEBUG_INFO sprintf(fm_string,"Counter %d created\n",no_counters); PrintFM(fm_string); #endif return(&counters[no_counters]); } // Function : SetCounter() // Coded by : Scott Evans // Created/Modified : 26/4/98 // Description : Define the textures for the counter sprites // Parameters : c - pointer to a counter // Returns : None // Notes : None void SetCounter(COUNTER *c) { OBJECT *o; u_byte m,i; long n,d; switch(c->type_code) { case DIGIT_COUNTER: m=MapCharacterToImage("0"); o=c->type.string.start; n=c->counter; // Set each digit for(i=0;itype.string.length;i++) { d=n%10; n/=10; o->type.gss.u=font_sprite_info.offsets[m+d].u; o->type.gss.v=font_sprite_info.offsets[m+d].v; o=o->next; // Do we need to change the shadow if(c->has_shadow) { o->type.gss.u=font_sprite_info.offsets[m+d].u; o->type.gss.v=font_sprite_info.offsets[m+d].v; o=o->next; } } break; case GFX_COUNTER: o=c->type.bar.bar; o->w=c->counter; break; default: PrintFM("Invalid counter type\n"); break; } } // Function : UpdateCounter() // Coded by : Scott Evans // Created/Modified : 26/4/98 // Description : Change the counter // Parameters : c - pointer to a counter // Returns : None // Notes : None void UpdateCounter(COUNTER *c) { // Has the counter changed if(c) { if(c->extra) { if(c->extra>0) { // Increase the value of the counter if(c->extra>50 && c->type_code==DIGIT_COUNTER && gd.bonus_type==BT_NONE) { c->extra-=50; c->counter+=50; } else { c->extra--; c->counter++; } } else if(c->extra<0) { // Decrease the value of the counter c->extra++; c->counter--; } } SetCounter(c); } } // Function : AddToCounter() // Coded by : Scott Evans // Created/Modified : 26/4/98 // Description : Add a value to a counter // Parameters : c - pointer to a counter // n - the value to add // Returns : None // Notes : None void AddToCounter(COUNTER *c,long n) { if(c) c->extra+=n; } // Function : SubtractFromCounter() // Coded by : Scott Evans // Created/Modified : 26/4/98 // Description : Subtract a value from a counter // Parameters : c - pointer to a counter // n - the value to subtract // Returns : None // Notes : None void SubtractFromCounter(COUNTER *c,long n) { if(c) c->extra-=n; } // Function : CreateDiamondCounter() // Coded by : Scott Evans // Created/Modified : 27/4/98 // Description : Keep a track of the number of diamonds left // Parameters : None // Returns : None // Notes : None void CreateDiamondCounter(void) { DVECTOR cpos={DIAMOND_COUNTER_X,DIAMOND_COUNTER_Y-OFF_SCREEN_Y}; OBJECT *o,*shadow; u_byte i; // Create an icon and a shadow diamond_counter_icon=o=CreateIconSprite(&info_objects,cpos.vx,cpos.vy,DIAMONDS_SYMBOL); o->tmp=9; o->direction=FINISHED; SetObjectsHandler(o,HandleScoreInfoObjects); shadow=CreateIconSprite(&info_objects,cpos.vx+1,cpos.vy+1,DIAMONDS_SYMBOL); o->parent=shadow; shadow->type.gss.attribute=TRANSPARENCY_ON|BG_MINUS_SP; shadow->tmp=10; shadow->direction=FINISHED; shadow->allow_fading=0; SetObjectsHandler(shadow,HandleScoreInfoObjects); cpos.vx+=8; diamond_counter=CreateCounter(&game_info_font,&cpos,3,1,DIGIT_COUNTER); o=diamond_counter->type.string.start; for(i=0;itype.string.length;i++) { o->tmp=9; o->direction=FINISHED; SetObjectsHandler(o,HandleScoreInfoObjects); o=o->next; o->tmp=10; o->direction=FINISHED; SetObjectsHandler(o,HandleScoreInfoObjects); o=o->next; } SetCounter(diamond_counter); PrintFM("Completed\n"); } // Function : CreateScoreCounter() // Coded by : Scott Evans // Created/Modified : 27/4/98 // Description : Create the score sprites // Parameters : None // Returns : None // Notes : None void CreateScoreCounter(void) { DVECTOR cpos={SCORE_POS_X,SCORE_POS_Y-OFF_SCREEN_Y}; OBJECT *o; u_byte i; score_counter=CreateCounter(&game_info_font,&cpos,8,1,DIGIT_COUNTER); score_counter->counter=gd.score; o=score_counter->type.string.start; for(i=0;itype.string.length;i++) { o->tmp=0; o->direction=FINISHED; SetObjectsHandler(o,HandleScoreInfoObjects); o=o->next; o->tmp=1; o->direction=FINISHED; SetObjectsHandler(o,HandleScoreInfoObjects); o=o->next; } SetCounter(score_counter); PrintFM("Completed\n"); } // Function : ResetBlockCount() // Coded by : Scott Evans // Created/Modified : 27/4/98 // Description : Reset the block counnter // Parameters : sfx - play the empty sound effect // Returns : None // Notes : None void ResetBlockCount(long sfx) { if(block_counter) { // Empty the block counter bar if(block_counter->extra==0) { AddToCounter(block_counter,abs(block_counter->counter)); if(abs(block_counter->counter)>0) CreateEmptyBlockCounterEffect(abs(block_counter->counter)); } // Stop it flashing block_counter->type.bar.bar->blink=0; block_counter->type.bar.bar->visible=1; } } // Function : CreateBlockCounter() // Coded by : Scott Evans // Created/Modified : 27/4/98 // Description : Create the block counnter // Parameters : None // Returns : None // Notes : None void CreateBlockCounter(void) { DVECTOR cpos={BLOCK_POS_X,BLOCK_POS_Y-OFF_SCREEN_Y}; OBJECT *o; // Create the counter graphics block_counter=CreateCounter(0,0,0,0,GFX_COUNTER); max_block_counter=CreateCounter(0,0,0,0,GFX_COUNTER); if((o=CreateObject(&info_objects,GsGQUAD_OBJECT))) { block_counter->type.bar.back=o; SetObjectsDefaultProperties(o); SetObjectsPosition(o,cpos.vx,cpos.vy,0); SetObjectsWidthHeight(o,-52,7); SetObjectsOtOffset(o,1); SetObjectsHandler(o,HandleScoreInfoObjects); setRGB4(&o->type.gsgq,0x80,0x80,0x80, 0x70,0x70,0x70, 0x60,0x60,0x60, 0x50,0x50,0x50); o->type.gsgq.attribute=TRANSPARENCY_ON; o->tmp=11; o->direction=FINISHED; o=CreateObject(&info_objects,GsGQUAD_OBJECT); block_counter->type.bar.bar=o; SetObjectsDefaultProperties(o); SetObjectsPosition(o,cpos.vx-1,cpos.vy+1,0); SetObjectsWidthHeight(o,0,5); SetObjectsOtOffset(o,2); SetObjectsHandler(o,HandleScoreInfoObjects); setRGB4(&o->type.gsgq,0xff,0xff,0xff, 0xff,0x80,0x0, 0x0,0x80,0xff, 0xff,0x0,0x80); o->type.gsgq.attribute=TRANSPARENCY_ON|BG_PLUS_SP; o->tmp=12; o->direction=FINISHED; o->blink_rate=8; o=CreateObject(&info_objects,GsGQUAD_OBJECT); max_block_counter->type.bar.bar=o; SetObjectsDefaultProperties(o); SetObjectsPosition(o,cpos.vx-1,cpos.vy+1,0); SetObjectsWidthHeight(o,0,5); SetObjectsOtOffset(o,2); SetObjectsHandler(o,HandleScoreInfoObjects); setRGB4(&o->type.gsgq,0x60,0x60,0x60, 0x60,0x0,0x0, 0x0,0x60,0x0, 0x0,0x0,0x60); o->type.gsgq.attribute=TRANSPARENCY_ON|BG_PLUS_SP; o->tmp=12; o->direction=FINISHED; } } // Function : KillAllObjects() // Coded by : Scott Evans // Created/Modified : 27/4/98 // Description : Clear all the object lists // Parameters : None // Returns : None // Notes : None void KillAllObjects(void) { ClearObjectList(&objects_list); ClearObjectList(&wind_objects_list); ClearObjectList(&info_objects); ClearObjectList(&paused_objects); ClearObjectList(&gun_objects); ClearObjectList(&platform_objects); ClearObjectList(&fan_objects); } // Function : InitObjectLists() // Coded by : Scott Evans // Created/Modified : 8/6/98 // Description : Initialise all the object lists // Parameters : None // Returns : None // Notes : None void InitObjectLists(void) { InitObjectFreeNodes(); InitObjectList(&objects_list); InitObjectList(&wind_objects_list); InitObjectList(&paused_objects); InitObjectList(&info_objects); InitObjectList(&gun_objects); InitObjectList(&platform_objects); InitObjectList(&fan_objects); } // Function : MoveScoreInfoObjects() // Coded by : Scott Evans // Created/Modified : 27/4/98 // Description : Move the score objects // Parameters : state - how to move the objects // mode - which objects to move // Returns : None // Notes : None void MoveScoreInfoObjects(u_byte state,u_byte mode) { OBJECT *o; u_byte i; // Set all the objects states if(mode==0 || mode==1) { o=score_counter->type.string.start; for(i=0;itype.string.length;i++) { o->direction=state; o=o->next; o->direction=state; o=o->next; } } if(mode==0 || mode==2) { // The level timer sprites o=level_timer.time_string.start; for(i=0;idirection=state; o=o->next; o->direction=state; o=o->next; } if(!gd.bonus_type) { // The diamond counter sprites o=diamond_counter->type.string.start; for(i=0;itype.string.length;i++) { o->direction=state; o=o->next; o->direction=state; o=o->next; } diamond_counter_icon->direction=diamond_counter_icon->parent->direction=state; // The icons for(i=0;idirection=state; gd.life_icons[i]->parent->direction=state; } for(i=0;idirection=state; gd.bomb_icons[i]->parent->direction=state; } // The block counter bar block_counter->type.bar.bar->direction=state; block_counter->type.bar.back->direction=state; max_block_counter->type.bar.bar->direction=state; } else { // The bonus counter sprites o=bonus_counter->type.string.start; for(i=0;itype.string.length;i++) { o->direction=state; o=o->next; o->direction=state; o=o->next; } bonus_counter_icon->direction=bonus_counter_icon->parent->direction=state; } } } // Function : GameOver() // Coded by : Scott Evans // Created/Modified : 27/4/98 // Description : The game over procedure // Parameters : None // Returns : None // Notes : None void GameOver(void) { DVECTOR pos={0,-50}; OBJECT *o; static OBJECT_STRING *os; static ENTER_NAME en; static u_byte state=GAME_OVER_INITIALISE; u_byte i; switch(state) { // Set up the game over screen case GAME_OVER_INITIALISE: // Make sure the score is not still counting score_counter->counter+=score_counter->extra; score_counter->extra=0; // Clear out the data bzero((u_byte *)&en,sizeof(ENTER_NAME)); // Start to fade down objects CopyBrightness(&default_brightness,&brightness[GAME_DEMO_BRIGHTNESS]); StartObjectFading(bg.block); StopLevelTimer(); gd.paused=1; gd.shake_screen=0; gd.kill_fireworks=0; gd.intro_counter=0; en.has_highscore=0; game_font.list=&paused_objects; // Have we got a highscore gd.score=score_counter->counter; if(CheckScore(gd.score)) { en.has_highscore=1; state=GAME_OVER_HIGHSCORE; os=CreateTextString(&pos,&game_font,"Congratulations",1); } else { PlaySoundEffect(sounds,&game_volume,SFX_GAME_OVER); state=GAME_OVER_CLEAR_OBJECTS; gd.timer=SECOND<<2; os=CreateTextString(&pos,&game_font,"Game Over",1); } game_font.list=&objects_list; for(o=os->start,i=0;ilength;i++) { o->allow_fading=0; SetObjectsHandler(o,HandlePausedObject); SetObjectsAcceleration(o,0,0.2,0); o->active=1; o->tmp=0; o=o->next; } break; // Set up the enter players name bit case GAME_OVER_HIGHSCORE: InitEnterName(&paused_objects,&en); en.score=gd.score; en.level=gd.level_no; FlashScoreObjects(); MoveScoreInfoObjects(START_MOVING_OFF_SCREEN,2); state=GAME_OVER_START_SELECTION; break; // Start the 1st character boucing case GAME_OVER_START_SELECTION: if(en.selection_chars[en.cursor_pos]->velocity.vy==0) { state=GAME_OVER_ENTER_NAME; en.selection_chars[en.cursor_pos]->velocity.vy=-2*FPN24_8; en.selection_chars[en.cursor_pos]->acceleration.vy=0.2*FPN24_8; en.selection_chars[en.cursor_pos]->tmp=EN_BOUNCE_CHARACTER; en.selection_chars[en.cursor_pos]->direction=1; en.selection_chars[en.cursor_pos]->is_fading=1; } break; // Enter the players name case GAME_OVER_ENTER_NAME: if(pd.pad&PADright && !(pd.buttons_down&PADright)) SelectCharacter(&en,SC_RIGHT); if(pd.pad&PADleft && !(pd.buttons_down&PADleft)) SelectCharacter(&en,SC_LEFT); if(pd.pad&PADcross && !(pd.buttons_down&PADcross)) SelectCharacter(&en,SC_SELECT); if(pd.pad&PADtriangle && !(pd.buttons_down&PADtriangle)) SelectCharacter(&en,SC_DELETE); if(pd.pad&PADL1 && !(pd.buttons_down&PADL1)) SelectCharacter(&en,SC_LEFT_CURSOR); if(pd.pad&PADR1 && !(pd.buttons_down&PADR1)) SelectCharacter(&en,SC_RIGHT_CURSOR); if(en.finished || (pd.pad&PADstart && !(pd.buttons_down&PADstart))) state=GAME_OVER_FINISHED_EDITING; // Create a few fireworks if(!(GetTimer()%35) && state!=GAME_OVER_FINISHED_EDITING) { CreateBonusFirework(); CreateBonusFirework(); CreateBonusFirework(); } break; // Put the players details into highscore table case GAME_OVER_FINISHED_EDITING: SelectCharacter(&en,SC_ENTER_NAME); state=GAME_OVER_CLEAR_OBJECTS; gd.timer=0; gd.kill_fireworks=1; break; // End the game over sequence case GAME_OVER_CLEAR_OBJECTS: if(en.has_highscore) { SelectCharacter(&en,SC_ALL_OFF); MoveScoreInfoObjects(START_MOVING_OFF_SCREEN,1); } else MoveScoreInfoObjects(START_MOVING_OFF_SCREEN,0); state=GAME_OVER_END; break; case GAME_OVER_END: if(gd.timer) gd.timer--; if(!gd.timer || (pd.pad&PADcross && !(pd.buttons_down&PADcross))) { for(o=os->start,i=0;ilength;i++) { o->tmp=1; o=o->next; } gd.game_over=0; gd.demo_mode=1; // Ready for next time state=GAME_OVER_INITIALISE; // Back to main menu InitLeaving(); if(en.has_highscore) gd.mode=HIGHSCORES; else { SetCurrentMenu(MT_MAIN); gd.mode=MENUS; } gd.message_mode=MM_NONE; } break; } } // Function : PositionScreen() // Coded by : Scott Evans // Created/Modified : 29/5/98 // Description : Move the screen // Parameters : p - pointer to program data // Returns : None // Notes : None #define MARKER_WIDTH 30 #define MARKER_HEIGHT 30 void PositionScreen(PROGRAM_DATA *p) { static word oldx,oldy; static u_byte c=PS_INITIALISE; static OBJECT *markers[4]; DVECTOR pos[4]={{0,0},{SCREEN_WIDTH-1,0},{0,SCREEN_HEIGHT-1},{SCREEN_WIDTH-1,SCREEN_HEIGHT-1}}; DVECTOR p0[4]={{0,MARKER_HEIGHT},{-MARKER_WIDTH,0},{0,-MARKER_HEIGHT},{0,-MARKER_HEIGHT}}; DVECTOR p1[4]={{MARKER_WIDTH,0},{0,MARKER_HEIGHT},{MARKER_WIDTH,0},{-MARKER_WIDTH,0}}; byte i; switch(c) { // Set up the position screen stuff case PS_INITIALISE: oldx=p->screen_xoff; oldy=p->screen_yoff; // Create the screen markers for(i=0;i<4;i++) { markers[i]=CreateObject(&objects_list,GsLINE3_OBJECT); if(markers[i]) { SetObjectsDefaultProperties(markers[i]); SetObjectsBrightness(markers[i],&brightness[GAME_MAX_BRIGHTNESS]); SetObjectsOtOffset(markers[i],1); setXY3(&markers[i]->type.gsl3,pos[i].vx+p0[i].vx,pos[i].vy+p0[i].vy,pos[i].vx,pos[i].vy,pos[i].vx+p1[i].vx,pos[i].vy+p1[i].vy); } } c=PS_MOVE_SCREEN; break; // Actually allow the controller to move the screen case PS_MOVE_SCREEN: if(p->pad&PADcross && !(p->buttons_down&PADcross)) { PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); // Ready for next time c=PS_END; } if(p->pad&PADtriangle && !(p->buttons_down&PADtriangle)) { // Cancel, reset to old offsets p->screen_xoff=oldx; p->screen_yoff=oldy; PlaySoundEffect(sounds,&menu_volume,SFX_MENU_CANCEL); c=PS_END; } // Move the screen left, right, up and down if(p->pad&PADleft && p->screen_xoff>0) p->screen_xoff--; if(p->pad&PADright && p->screen_xoff>1) p->screen_xoff++; if(p->pad&PADup && p->screen_yoff>0) p->screen_yoff--; if(p->pad&PADdown && p->screen_yoff>1) p->screen_yoff++; break; case PS_END: gd.message_mode=MM_NONE; gd.mode=MENUS; // Clear the messages KillMessages(); // Back to the menus if(gd.paused) SetCurrentMenu(MT_PAUSE); else SetCurrentMenu(MT_MAIN); StartMenus(); for(i=0;i<4;i++) RemoveObjectFromList(&objects_list,markers[i]); // Ready for next time c=PS_INITIALISE; break; } } // Function : AboutB2() // Coded by : Scott Evans // Created/Modified : 29/5/98 // Description : The about screen // Parameters : pd - pointer to program data // Returns : None // Notes : None void AboutB2(PROGRAM_DATA *pd) { // Show the about B2 messages if(pd->pad&PADcross && !(pd->buttons_down&PADcross)) { gd.message_mode=MM_NONE; gd.mode=MENUS; // Clear the messages KillMessages(); // Back to the menus SetCurrentMenu(MT_MAIN); StartMenus(); PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } } // Function : Instructions() // Coded by : Scott Evans // Created/Modified : 29/5/98 // Description : The instruction screen // Parameters : pd - pointer to program data // Returns : None // Notes : None void Instructions(PROGRAM_DATA *pd) { if(pd->pad&PADcross && !(pd->buttons_down&PADcross)) { gd.message_mode=MM_NONE; gd.mode=MENUS; // Clear the messages KillMessages(); // Back to the menus SetCurrentMenu(MT_MAIN); StartMenus(); PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } } // Function : InitBonusLevel() // Coded by : Scott Evans // Created/Modified : 3/7/98 // Description : Initialise a bonus level // Parameters : type - the type of bonus level // Returns : None // Notes : None void InitBonusLevel(u_byte type) { OBJECT *o; switch(gd.bonus_type) { case BT_CATCH: if((o=CreateObject(&objects_list,NULL_OBJECT))) { SetObjectsHandler(o,HandleBonusDropper); SetObjectsTimer(o,SECOND*5); o->active=1; o->extra[1]=3*SECOND; o->extra[0]=0; } break; case BT_COLLECT: // Create the catcher if((o=CreateObject(&objects_list,NULL_OBJECT))) { SetObjectsHandler(o,HandleBonusCatcher); SetObjectsBoundingBox(o,8<<4,6<<4,4<<4,1<<4); o->active=1; } // Create the arrow if((o=CreateObject(&objects_list,GsSPRITE_OBJECT))) { u_byte n=DOWN_ARROW; SetObjectsDefaultProperties(o); SetObjectsHandler(o,HandleBonusArrow); SetObjectsTimer(o,3*SECOND); SetObjectsWidthHeight(o,font_sprite_info.offsets[n].w,font_sprite_info.offsets[n].h); SetObjectsOtOffset(o,1); // Set the sprite SetGsSPRITE(&o->type.gss,TRANSPARENCY_ON|BG_PLUS_SP,0,0,o->w,o->h, font_sprite_info.tpage,font_sprite_info.offsets[n].u,font_sprite_info.offsets[n].v, font_sprite_info.cx,font_sprite_info.cy+font_sprite_info.offsets[n].clut_y, 0,0,0,0,0,ONE<<1,ONE<<1,0); SetObjectsBrightness(o,&brightness[GAME_MIN_BRIGHTNESS]); SetObjectsPosition(o,9<<4,1<<4,0); SetObjectsVelocity(o,0,1,0); SetObjectsAcceleration(o,0,0.1,0); o->extra[0]=(3<<4)+8; o->extra[1]=0; o->allow_fading=0; o->visible=0; bonus_object=o; } break; } } // Function : CreateBonusLevelCounter() // Coded by : Scott Evans // Created/Modified : 3/7/98 // Description : Keep a track of the number of bonuses achieved // Parameters : None // Returns : None // Notes : None void CreateBonusLevelCounter(void) { DVECTOR cpos={BONUS_COUNTER_X,BONUS_COUNTER_Y-OFF_SCREEN_Y}; OBJECT *o,*shadow; u_word n; u_byte i; // Create an icon and a shadow if(gd.bonus_type==BT_BLOCK) n=BLOCK_SYMBOL; else n=LIVES_SYMBOL; bonus_counter_icon=o=CreateIconSprite(&info_objects,cpos.vx,cpos.vy,n); o->tmp=9; o->direction=FINISHED; SetObjectsHandler(o,HandleScoreInfoObjects); shadow=CreateIconSprite(&info_objects,cpos.vx+1,cpos.vy+1,n); o->parent=shadow; shadow->type.gss.attribute=TRANSPARENCY_ON|BG_MINUS_SP; shadow->tmp=10; shadow->direction=FINISHED; SetObjectsHandler(shadow,HandleScoreInfoObjects); cpos.vx+=8; bonus_counter=CreateCounter(&game_info_font,&cpos,3,1,DIGIT_COUNTER); o=bonus_counter->type.string.start; // Set all the objects that make up the counter for(i=0;itype.string.length;i++) { o->tmp=9; o->direction=FINISHED; SetObjectsHandler(o,HandleScoreInfoObjects); o=o->next; o->tmp=10; o->direction=FINISHED; SetObjectsHandler(o,HandleScoreInfoObjects); o=o->next; } SetCounter(bonus_counter); PrintFM("Completed\n"); } // Function : CreateExtraLife() // Coded by : Scott Evans // Created/Modified : 19/7/98 // Description : Award an extra life // Parameters : None // Returns : None // Notes : None void CreateExtraLife(void) { OBJECT *o; word x; if(gd.no_livesparent=CreateIconSprite(&info_objects,x+1,LIFE_ICON_Y+1,LIVES_SYMBOL); gd.life_icons[gd.no_lives]->parent->type.gss.attribute=TRANSPARENCY_ON|BG_MINUS_SP; SetObjectsBrightness(gd.life_icons[gd.no_lives],&brightness[GAME_MIN_BRIGHTNESS]); gd.life_icons[gd.no_lives]->allow_fading=1; SetObjectsHandler(gd.life_icons[gd.no_lives],HandleNewIconObject); gd.life_icons[gd.no_lives]->extra[0]=2; gd.life_icons[gd.no_lives]->extra[1]=3; gd.no_lives++; if((o=CreateObject(&info_objects,GsSPRITE_OBJECT))) { SetObjectsDefaultProperties(o); SetObjectsWidthHeight(o,game_sprites_info.offsets[LIVES_SYMBOL].w,game_sprites_info.offsets[LIVES_SYMBOL].h); SetObjectsOtOffset(o,2); SetObjectsHandler(o,HandleExtraLifeSprite); SetObjectsTimer(o,SECOND*3); o->allow_fading=1; // Set the sprite SetGsSPRITE(&o->type.gss,TRANSPARENCY_ON|BG_PLUS_SP,0,0,o->w,o->h, game_sprites_info.tpage,game_sprites_info.offsets[LIVES_SYMBOL].u,game_sprites_info.offsets[LIVES_SYMBOL].v, game_sprites_info.cx,game_sprites_info.cy+game_sprites_info.offsets[LIVES_SYMBOL].clut_y, 0,0,0,4,4,ONE,ONE,0); SetObjectsBrightness(o,&brightness[GAME_EXTRA_BRIGHTNESS]); SetObjectsPosition(o,x+4,LIFE_ICON_Y+(o->h>>1),0); } PlaySoundEffect(sounds,&game_volume,SFX_EXTRA_LIFE); } } // Function : CreateExtraBomb() // Coded by : Scott Evans // Created/Modified : 19/7/98 // Description : Award an extra bomb // Parameters : None // Returns : None // Notes : None void CreateExtraBomb(void) { OBJECT *o; word x; if(gd.no_bombsparent=CreateIconSprite(&info_objects,x+1,BOMB_ICON_Y+1,BOMBS_SYMBOL); gd.bomb_icons[gd.no_bombs]->parent->type.gss.attribute=TRANSPARENCY_ON|BG_MINUS_SP; SetObjectsBrightness(gd.bomb_icons[gd.no_bombs],&brightness[GAME_MIN_BRIGHTNESS]); gd.bomb_icons[gd.no_bombs]->allow_fading=1; SetObjectsHandler(gd.bomb_icons[gd.no_bombs],HandleNewIconObject); gd.bomb_icons[gd.no_bombs]->extra[0]=4; gd.bomb_icons[gd.no_bombs]->extra[1]=5; gd.no_bombs++; if((o=CreateObject(&info_objects,GsSPRITE_OBJECT))) { SetObjectsDefaultProperties(o); SetObjectsWidthHeight(o,game_sprites_info.offsets[BOMBS_SYMBOL].w,game_sprites_info.offsets[BOMBS_SYMBOL].h); SetObjectsOtOffset(o,2); SetObjectsHandler(o,HandleExtraLifeSprite); SetObjectsTimer(o,SECOND*3); o->allow_fading=1; // Set the sprite SetGsSPRITE(&o->type.gss,TRANSPARENCY_ON|BG_PLUS_SP,0,0,o->w,o->h, game_sprites_info.tpage,game_sprites_info.offsets[BOMBS_SYMBOL].u,game_sprites_info.offsets[BOMBS_SYMBOL].v, game_sprites_info.cx,game_sprites_info.cy+game_sprites_info.offsets[BOMBS_SYMBOL].clut_y, 0,0,0,3,4,ONE,ONE,0); SetObjectsBrightness(o,&brightness[GAME_EXTRA_BRIGHTNESS]); SetObjectsPosition(o,x+3,BOMB_ICON_Y+(o->h>>1),0); PlaySoundEffect(sounds,&game_volume,SFX_EXTRA_LIFE); } } } // Function : SaveGameScreen() // Coded by : Scott Evans // Created/Modified : 21/7/98 // Description : Handle the save game option // Parameters : pd - pointer to program data // Returns : None // Notes : None void SaveGameScreen(PROGRAM_DATA *pd) { static OBJECT_STRING *os; static u_byte state=SG_START; static u_byte next_state; switch(state) { // Test controller case SG_START: if(pd->pad&PADcross && !(pd->buttons_down&PADcross)) { next_state=SG_INITSAVE; state=SG_CHANGE_STATE; PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } else if(pd->pad&PADtriangle && !(pd->buttons_down&PADtriangle)) { next_state=SG_END; state=SG_CHANGE_STATE; PlaySoundEffect(sounds,&menu_volume,SFX_MENU_CANCEL); } break; // Clear messages and go to next state case SG_CHANGE_STATE: KillMessages(); state=next_state; break; // Return to menu case SG_END: gd.message_mode=MM_NONE; gd.mode=MENUS; if(gd.paused) SetCurrentMenu(MT_PAUSE); else SetCurrentMenu(MT_MAIN); StartMenus(); state=SG_START; break; // Set up the save messages case SG_INITSAVE: os=CreateMessages(SAVEPROGRESS_MESSAGES,30); StopMessage(os+1); StopMessage(os+2); StopMessage(os+3); state=SG_SAVE; break; // Attempt to save the game case SG_SAVE: if(!gd.paused) { // Saving game at frontend, use default no lives and bombs 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; } } if(SaveGame(gd.mcard)) StartMessage(os+1,SECOND); else { SetMessagePosition(os+3,&(os+1)->start->brightness,(os+1)->start->extra[0]); StartMessage(os+3,SECOND); } state=SG_INITCOMPLETE; break; // Show the save complete message case SG_INITCOMPLETE: StartMessage(os+2,SECOND*2); state=SG_COMPLETE; break; // Wait for button press case SG_COMPLETE: if(pd->pad&PADcross && !(pd->buttons_down&PADcross)) { next_state=SG_END; state=SG_CHANGE_STATE; PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } break; } } // Function : LoadGameScreen() // Coded by : Scott Evans // Created/Modified : 21/7/98 // Description : Handle the load game option // Parameters : pd - pointer to program data // Returns : None // Notes : None void LoadGameScreen(PROGRAM_DATA *pd) { static OBJECT_STRING *os; static u_byte state=LG_START; static u_byte next_state; static u_byte play_game; switch(state) { // Test controller case LG_START: play_game=0; if(pd->pad&PADcross && !(pd->buttons_down&PADcross)) { next_state=LG_INITLOAD; state=LG_CHANGE_STATE; PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } else if(pd->pad&PADtriangle && !(pd->buttons_down&PADtriangle)) { next_state=LG_END; state=LG_CHANGE_STATE; PlaySoundEffect(sounds,&menu_volume,SFX_MENU_CANCEL); } break; // Clear messages and go to next state case LG_CHANGE_STATE: KillMessages(); state=next_state; break; // Return to menu or start loaded game case LG_END: if(!play_game) { gd.mode=MENUS; if(gd.paused) SetCurrentMenu(MT_PAUSE); else SetCurrentMenu(MT_MAIN); StartMenus(); } else { if(gd.paused) MoveScoreInfoObjects(START_MOVING_OFF_SCREEN,0); gd.no_lives=lsgd.lives; gd.no_bombs=lsgd.bombs; StartGame(); gd.just_loaded=1; } state=LG_START; gd.message_mode=MM_NONE; break; // Initialise the loading stuff case LG_INITLOAD: os=CreateMessages(LOADPROGRESS_MESSAGES,30); StopMessage(os+1); StopMessage(os+2); StopMessage(os+3); state=LG_LOAD; break; // Load the game case LG_LOAD: if(LoadGame(gd.mcard)) { StartMessage(os+1,SECOND); play_game=1; } else { SetMessagePosition(os+3,&(os+1)->start->brightness,(os+1)->start->extra[0]); StartMessage(os+3,SECOND); } state=LG_INITCOMPLETE; break; // Show the load complete message case LG_INITCOMPLETE: StartMessage(os+2,SECOND*2); state=LG_COMPLETE; break; // Wait for button press case LG_COMPLETE: if(pd->pad&PADcross && !(pd->buttons_down&PADcross)) { next_state=LG_END; state=LG_CHANGE_STATE; PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } break; } } // Function : FormatCardScreen() // Coded by : Scott Evans // Created/Modified : 22/7/98 // Description : Handle the format card option // Parameters : pd - pointer to program data // Returns : None // Notes : None void FormatCardScreen(PROGRAM_DATA *pd) { static OBJECT_STRING *os; static u_byte state=FC_START; static u_byte next_state; switch(state) { // Test controller case FC_START: if(pd->pad&PADcross && !(pd->buttons_down&PADcross)) { next_state=FC_INITFORMAT; state=FC_CHANGE_STATE; PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } else if(pd->pad&PADtriangle && !(pd->buttons_down&PADtriangle)) { next_state=FC_END; state=FC_CHANGE_STATE; PlaySoundEffect(sounds,&menu_volume,SFX_MENU_CANCEL); } break; // Clear messages and go to next state case FC_CHANGE_STATE: KillMessages(); state=next_state; break; // Return to menu case FC_END: gd.message_mode=MM_NONE; gd.mode=MENUS; if(gd.paused) SetCurrentMenu(MT_PAUSE); else SetCurrentMenu(MT_MAIN); StartMenus(); state=FC_START; break; // Get ready to format card case FC_INITFORMAT: os=CreateMessages(FORMATPROGRESS_MESSAGES,30); StopMessage(os+1); StopMessage(os+2); StopMessage(os+3); state=FC_FORMAT; break; // Format the memory card case FC_FORMAT: if(FormatMemoryCard(gd.mcard)) StartMessage(os+1,SECOND); else { SetMessagePosition(os+3,&(os+1)->start->brightness,(os+1)->start->extra[0]); StartMessage(os+3,SECOND); } state=FC_INITCOMPLETE; break; // Show the format complete message case FC_INITCOMPLETE: StartMessage(os+2,SECOND*2); state=FC_COMPLETE; break; // Wait for button press case FC_COMPLETE: if(pd->pad&PADcross && !(pd->buttons_down&PADcross)) { next_state=FC_END; state=FC_CHANGE_STATE; PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } break; } } // Function : StartGame() // Coded by : Scott Evans // Created/Modified : 29/7/98 // Description : Start a game // Parameters : None // Returns : None // Notes : None void StartGame(void) { gd.demo_mode=0; gd.level_no=gd.start_level; gd.score=0; gd.game_over=0; gd.game_started=0; gd.extra_life_score=EXTRA_LIFE_SCORE; InitLeaving(); } // Function : ExitGame() // Coded by : Scott Evans // Created/Modified : 1/8/98 // Description : End the current game // Parameters : pd - pointer to program data // Returns : None // Notes : None void ExitGame(PROGRAM_DATA *pd) { // Show the exit game messages if(pd->pad&PADcross && !(pd->buttons_down&PADcross)) { // Clear the messages KillMessages(); // Back to the main menu gd.demo_mode=1; InitLeaving(); gd.mode=MENUS; gd.message_mode=MM_NONE; gd.intro_counter=0; SetCurrentMenu(MT_MAIN); MoveScoreInfoObjects(START_MOVING_OFF_SCREEN,0); PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } else { // Back to the game if(pd->pad&PADtriangle && !(pd->buttons_down&PADtriangle)) { gd.message_mode=MM_NONE; gd.mode=MENUS; // Clear the messages KillMessages(); // Back to the menus SetCurrentMenu(MT_PAUSE); StartMenus(); PlaySoundEffect(sounds,&menu_volume,SFX_MENU_CANCEL); } } } // Function : FlashScoreObjects() // Coded by : Scott Evans // Created/Modified : 15/8/98 // Description : Make all the score objects blink on and off // Parameters : None // Returns : None // Notes : None void FlashScoreObjects(void) { OBJECT *o; u_byte i; // Set all the objects states o=score_counter->type.string.start; for(i=0;itype.string.length;i++) { o->blink=1; o->blink_rate=16; o=o->next; o->blink=1; o->blink_rate=16; o=o->next; } } // Function : LevelSkipCheat() // Coded by : Scott Evans // Created/Modified : 20/8/98 // Description : Skip to the next level // Parameters : None // Returns : None // Notes : None void LevelSkipCheat(void) { if(gd.cheats_on&CC_LEVEL_SKIP && !gd.paused && !gd.lspr_clear) { // If SELECT is pressed skip to the next level if(pd.pad&PADselect && !(pd.buttons_down&PADselect)) { if(gd.bonus_level && gd.bspr_clear) { gd.bspr_clear=0; gd.level_complete=1; CopyBrightness(&default_brightness,&brightness[GAME_DEMO_BRIGHTNESS]); StartObjectFading(bg.block); StopLevelTimer(); if(gd.bonus_type==BT_COLLECT) if(bonus_object->extra[1]==1) bonus_object->extra[1]=2; } else diamond_counter->counter=0; gd.level_warp=1; } } } // Function : Version() // Coded by : Scott Evans // Created/Modified : 21/8/98 // Description : Shows version information // Parameters : pd - pointer to program data // Returns : None // Notes : None void Version(VERSION_DATA *v) { u_byte fm_string[100]; sprintf(fm_string,"Loaded software - %s\n",v->name); PrintFM(fm_string); sprintf(fm_string,"Software version - %d\n",v->version); PrintFM(fm_string); sprintf(fm_string,"Library type - %s\n",(v->libs==LT_YAROZE ? "YAROZE" : "PSX v4.4")); PrintFM(fm_string); sprintf(fm_string,"Build time - %s %s\n",__DATE__,__TIME__); PrintFM(fm_string); } // Function : LoadGameData() // Coded by : Scott Evans // Created/Modified : 20/3/99 // Description : Load all the game data // Parameters : None // Returns : None // Notes : None u_long LoadGameData(void) { #ifdef PC_LOAD // Load in all the data if(!LoadPCFile("DATA\\BLOCKS",(u_byte *)DM_BLOCKS)) return(0); if(!LoadPCFile("DATA\\SPRITES",(u_byte *)DM_SPRITES)) return(0); if(!LoadPCFile("DATA\\BFONT",(u_byte *)DM_BFONT)) return(0); if(!LoadPCFile("DATA\\LEVELS",(u_byte *)DM_LEVELS)) return(0); if(!LoadPCFile("DATA\\BOUNCER2.VH",(u_byte *)DM_BOUNCER2_VH)) return(0); if(!LoadPCFile("DATA\\BOUNCER2.VB",(u_byte *)DM_BOUNCER2_VB)) return(0); #endif // Set pointers to the data map_blocks_header=(SprHeader *)DM_BLOCKS; game_sprites_header=(SprHeader *)DM_SPRITES; font_header=(SprHeader *)DM_BFONT; levels_header=(LevelHeader *)DM_LEVELS; vab_header=(u_byte *)DM_BOUNCER2_VH; vab_body=(u_byte *)DM_BOUNCER2_VB; return(1); } #if 0 #define TITLE_SCREEN_TIME (5*50) void ShowTitleScreen(void) { RECT r; GsIMAGE title; u_long timer; r.x=0; r.y=0; r.w=320; r.h=511; ClearImage(&r,0,0,0); GsGetTimInfo((u_long *)(title_screen+4),&title); timer=0; r.x=title.px; r.y=title.py+8; r.w=title.pw; r.h=title.ph; SetDispMask(1); DrawSync(0); while(timer