// Filename : HSCORE.C // Coded by : Scott Evans // Created/Modified : 15/3/98 // Description : B2 highscore routines #include "hscore.h" // External variables extern OBJECT_LIST_HEADER objects_list,paused_objects; extern SPRITE_DATA_INFO font_sprite_info; extern BRIGHTNESS brightness[]; extern PROGRAM_DATA pd; extern SOUND_DATA *sounds; extern VOLUME menu_volume; // Global variables HIGHSCORE highscore_table[HIGHSCORE_TABLE_SIZE]; FONT_INFO highscore_font; OBJECT_LIST_HEADER highscore_objects; u_byte *highscore_table_names[]={"Alex","Warren","Mike","Nick","Paul","Adam","Clare","John","Nathan","Lisa"}; // Function : InitHighScoreTable() // Coded by : Scott Evans // Created/Modified : 15/3/98 // Description : Initialise the high score table // Parameters : None // Returns : None // Notes : None void InitHighScoreTable(void) { u_word i; // Initialise highscore objects list InitObjectList(&highscore_objects); // Set font used for highscore table SetFontInfo(&highscore_font,&font_sprite_info,&highscore_objects,8,8, &brightness[HIGHSCORE_TEXT_BRIGHTNESS],ONE,ONE); for(i=0;i=i;j--) { temp[0].score=h[j-1].score; strcpy(&temp[0].name[0],&h[j-1].name[0]); temp[0].level=h[j-1].level; temp[0].flag=h[j-1].flag; temp[1].score=h[j].score; strcpy(&temp[1].name[0],&h[j].name[0]); temp[1].level=h[j].level; temp[1].flag=h[j].flag; if(temp[1].score>temp[0].score) { h[j-1].score=temp[1].score; strcpy(&h[j-1].name[0],&temp[1].name[0]); h[j-1].level=temp[1].level; h[j-1].flag=temp[1].flag; h[j].score=temp[0].score; strcpy(&h[j].name[0],&temp[0].name[0]); h[j].level=temp[0].level; h[j].flag=temp[0].flag; } } } // Function : CreateHighScoreTableObjects() // Coded by : Scott Evans // Created/Modified : 15/3/98 // Description : Create the objects used in highscore table // Parameters : h - pointer to highscore data // l - pointer to object list to use // area - screen area used by highscore table // Returns : Pointer to array of object strings // Notes : None OBJECT_STRING *CreateHighScoreTableObjects(HIGHSCORE *h,RECT *area) { static OBJECT_STRING highscore_strings[HIGHSCORE_TABLE_SIZE]; VECTOR pos={0,-32,0}; u_word i,w; u_byte string[80]; for(i=0;ix+((area->w-w)>>1); PrintString(string,&highscore_font,&pos,&highscore_strings[i]); } return(&highscore_strings[0]); } // Function : ClearHighScoreTable() // Coded by : Scott Evans // Created/Modified : 15/3/98 // Description : Destroy all objects used in highscore table // Parameters : None // Returns : None // Notes : None void ClearHighScoreTable(OBJECT_LIST_HEADER *l) { OBJECT *next,*o=l->start; PARTICLE_EXPLOSION explosion; while(o) { next=o->next; SetParticleExplosion(&explosion,&objects_list,HandleHighScoreExplosionFragment,1,280,2,2,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,8,8); CreateParticleExplosion(&explosion); RemoveObjectFromList(&highscore_objects,o); o=next; } } // Function : DisplayHighScoreTable() // Coded by : Scott Evans // Created/Modified : 15/3/98 // Description : Display all objects used in highscore table // Parameters : ot - pointer to ordering table // priority - ordering table priority // Returns : None // Notes : None void DisplayHighScoreTable(GsOT *ot,u_word priority) { UpdateObjects(&highscore_objects); SortObjects(&highscore_objects,ot,priority); } // Function : CreateHighScoreTable() // Coded by : Scott Evans // Created/Modified : 15/3/98 // Description : Initialise all objects used in highscore table // Parameters : None // Returns : None // Notes : None void CreateHighScoreTable(void) { RECT r={0,0,SCREEN_WIDTH,SCREEN_HEIGHT}; OBJECT_STRING *s; OBJECT *o; u_word i,j; s=CreateHighScoreTableObjects(&highscore_table[0],&r); for(i=0;inext) { SetObjectsAcceleration(o,0,0.05,0); o->active=1; o->f=HandleHighScoreString; o->allow_fading=1; o->direction=i; o->blink=0; o->extra[0]=0; if(highscore_table[i].flag) o->extra[0]=1; StartObjectFading(o); } #ifdef DEBUG_INFO PrintFM("Completed\n"); #endif } // Function : HandleHighScoreString() // Coded by : Scott Evans // Created/Modified : 15/3/98 // Description : Handler function for highscore objects // Parameters : o - pointer to a object // Returns : None // Notes : None void HandleHighScoreString(OBJECT *o) { // Bounce the objects if(o->screen.vy>(o->direction*22)+25) { o->velocity.vy=-1<screen.vy=(o->direction*22)+25; o->position.vy=o->screen.vy<is_fading && o->extra[0]) FadeObjectBrightness(o,&brightness[HIGHSCORE_MAX_BRIGHTNESS],100<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) RemoveObjectFromList(&objects_list,o); } // Function : CheckScore() // Coded by : Scott Evans // Created/Modified : 16/5/98 // Description : Test whether a score can be put into the highscore table // Parameters : s - the score to test // Returns : True if the score can be put in the highscore table, otherwise false // Notes : None u_byte CheckScore(u_long s) { if(s>highscore_table[HIGHSCORE_TABLE_SIZE-1].score) return(1); #ifdef DEBUG_INFO PrintFM("Failed\n"); #endif return(0); } // Function : InitEnterName() // Coded by : Scott Evans // Created/Modified : 26/5/98 // Description : Initialise the enter name process // Parameters : l - object list to use // en - name data // Returns : None // Notes : None void InitEnterName(OBJECT_LIST_HEADER *l,ENTER_NAME *en) { OBJECT *o; GsSPRITE *spr; u_byte i,n; word cx,x,y; en->cursor_pos=MAX_CHARACTER_SELECTION>>1; en->cpage=en->name_pos=0; en->list=l; cx=x=(GAME_SCREEN_W-(MAX_CHARACTER_SELECTION*12))>>1; y=280; en->dpos.vx=cx+((((MAX_CHARACTER_SELECTION+1)*12)-(HIGHSCORE_NAME_SIZE*8))>>1); en->dpos.vy=230; // Create the chracters to choose from for(i=0;iselection_chars[i]=o; SetObjectsDefaultProperties(o); SetObjectsPosition(o,x,y,0); SetObjectsHandler(o,HandleEnterNameObject); SetObjectsVelocity(o,0,-6,0); SetObjectsAcceleration(o,0,0.2,0); o->tmp=EN_MOVE_ON_CHARACTER; o->is_fading=0; o->direction=0; n=MapCharacterToImage("A")+i; spr=&o->type.gss; SetObjectsWidthHeight(o,font_sprite_info.offsets[n].w,font_sprite_info.offsets[n].h); // Define the sprite SetGsSPRITE(spr,0,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,ONE,0); SetObjectsBrightness(o,&brightness[HIGHSCORE_TEXT_BRIGHTNESS]); x+=(o->w>>1)+4; } } x=cx-2; for(i=0;i<2;i++) { if((o=CreateObject(l,GsTRIANGLE_OBJECT))) { en->arrows[i]=o; SetObjectsDefaultProperties(o); SetObjectsHandler(o,HandleEnterNameObject); SetObjectsVelocity(o,0,-6,0); SetObjectsAcceleration(o,0,0.2,0); SetObjectsPosition(o,x,y,0); if(i) SetObjectsWidthHeight(o,-CURSOR_WIDTH,CURSOR_HEIGHT); else SetObjectsWidthHeight(o,CURSOR_WIDTH,CURSOR_HEIGHT); SetObjectsBrightness(o,&brightness[HIGHSCORE_TEXT_BRIGHTNESS]); o->type.gst.attribute=0; o->tmp=EN_MOVE_ON_CURSOR; o->extra[CURSOR_XPOS]=x; o->is_fading=0; o->direction=0; x+=MAX_CHARACTER_SELECTION*12; } } } // Function : HandleEnterNameObject() // Coded by : Scott Evans // Created/Modified : 26/5/98 // Description : Control the objects used to enter a name // Parameters : o - object to handle // Returns : None // Notes : None void HandleEnterNameObject(OBJECT *o) { // Fade the object up/down if(o->is_fading) { if(o->direction) FadeObjectBrightness(o,&brightness[HIGHSCORE_MAX_BRIGHTNESS],30<tmp) { // Move the objects onto the screen case EN_MOVE_ON_CHARACTER: if(o->velocity.vy>0) if(o->screen.vy>200) { o->velocity.vy=0; o->acceleration.vy=0; o->screen.vy=200; o->position.vy=o->screen.vy<tmp=EN_WAITING; } break; // Start a character bouncing case EN_BOUNCE_CHARACTER: if(o->screen.vy>200) { o->screen.vy=200; o->position.vy=o->screen.vy<velocity.vy=-2*FPN24_8; } break; // Start the left cursor moving case EN_BOUNCE_LEFT_CURSOR: if(o->screen.vx>o->extra[CURSOR_XPOS]) { o->screen.vx=o->extra[CURSOR_XPOS]; o->position.vx=o->screen.vx<velocity.vx=-1*FPN24_8; } break; // Start the right cursor moving case EN_BOUNCE_RIGHT_CURSOR: if(o->screen.vxextra[CURSOR_XPOS]) { o->screen.vx=o->extra[CURSOR_XPOS]; o->position.vx=o->screen.vx<velocity.vx=1*FPN24_8; } break; // Move the cursors on screen case EN_MOVE_ON_CURSOR: if(o->velocity.vy>0) if(o->screen.vy>196) { o->velocity.vy=0; o->acceleration.vy=0; o->screen.vy=196; o->position.vy=o->screen.vy<tmp=EN_WAITING; } break; // Stop bouncing the cursor case EN_STOP_LEFT_CURSOR: if(o->velocity.vx>0) if(o->screen.vx>o->extra[CURSOR_XPOS]) { o->velocity.vx=0; o->acceleration.vx=0; o->screen.vx=o->extra[CURSOR_XPOS]; o->position.vx=o->screen.vx<tmp=EN_WAITING; } break; // Stop bouncing the cursor case EN_STOP_RIGHT_CURSOR: if(o->velocity.vx<0) if(o->screen.vxextra[CURSOR_XPOS]) { o->velocity.vx=0; o->acceleration.vx=0; o->screen.vx=o->extra[CURSOR_XPOS]; o->position.vx=o->screen.vx<tmp=EN_WAITING; } break; // Fade the characters to black case EN_FADE_TO_BLACK: if(o->timer) o->timer--; else { FadeObjectBrightness(o,&brightness[HIGHSCORE_MIN_BRIGHTNESS],5<extra[TIMER]) { // Finshed fading so change the texture to the next character o->type.gss.u=o->extra[NEXT_TEXTURE_U]; o->type.gss.v=o->extra[NEXT_TEXTURE_V]; o->tmp=EN_WAITING; // Fade the new character back up o->direction=0; o->is_fading=1; } else o->extra[TIMER]--; } break; case EN_DELETE_CHARACTER: FadeObjectBrightness(o,&brightness[HIGHSCORE_MIN_BRIGHTNESS],30<type.gss.rotate+=(ONE*(o->velocity.vx>>FP24_8))<<2; if(o->screen.vx>GAME_SCREEN_W || o->screen.vxscreen.vy>GAME_SCREEN_H || o->screen.vyscreen.vy>GAME_SCREEN_H+50) RemoveObjectFromList(&paused_objects,o); break; } } // Function : SelectCharacter() // Coded by : Scott Evans // Created/Modified : 26/5/98 // Description : Action to be taken when selecting characters // Parameters : en - name data // d - action to take // Returns : None // Notes : None void SelectCharacter(ENTER_NAME *en,byte d) { OBJECT *o; GsSPRITE *spr; word x,y; u_byte i,n; switch(d) { // Next character to left case SC_LEFT: if(en->cursor_pos>-1 && ChangedCPage(en)) { if(en->cursor_pos==0 && en->cpage==0) break; // Fade previous character down if(en->cursor_pos<=MAX_CHARACTER_SELECTION-1) { en->selection_chars[en->cursor_pos]->direction=0; en->selection_chars[en->cursor_pos]->is_fading=1; en->selection_chars[en->cursor_pos]->tmp=EN_MOVE_ON_CHARACTER; } else { en->arrows[1]->direction=0; en->arrows[1]->is_fading=1; en->arrows[1]->tmp=EN_STOP_RIGHT_CURSOR; } en->cursor_pos--; // Jump to left cursor if(en->set_pos) { en->set_pos=0; en->cursor_pos=-1; } // Fade next character up if(en->cursor_pos>=0) { en->selection_chars[en->cursor_pos]->direction=1; en->selection_chars[en->cursor_pos]->is_fading=1; // Start it bouncing, if not already moving if(en->selection_chars[en->cursor_pos]->acceleration.vy==0) { 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; } else { // Left cursor en->arrows[0]->direction=1; en->arrows[0]->is_fading=1; en->arrows[0]->tmp=EN_BOUNCE_LEFT_CURSOR; en->arrows[0]->velocity.vx=-1*FPN24_8; en->arrows[0]->acceleration.vx=0.1*FPN24_8; } PlaySoundEffect(sounds,&menu_volume,SFX_MENU_MOVE); } break; // Next character to right case SC_RIGHT: if(en->cursor_poscursor_pos==MAX_CHARACTER_SELECTION-1 && en->cpage==MAX_CPAGES) break; if(en->cursor_pos>=0) { en->selection_chars[en->cursor_pos]->direction=0; en->selection_chars[en->cursor_pos]->is_fading=1; en->selection_chars[en->cursor_pos]->tmp=EN_MOVE_ON_CHARACTER; } else { en->arrows[0]->direction=0; en->arrows[0]->is_fading=1; en->arrows[0]->tmp=EN_STOP_LEFT_CURSOR; } en->cursor_pos++; // Jump to right cursor if(en->set_pos) { en->set_pos=0; en->cursor_pos=MAX_CHARACTER_SELECTION; } if(en->cursor_pos<=MAX_CHARACTER_SELECTION-1) { en->selection_chars[en->cursor_pos]->direction=1; en->selection_chars[en->cursor_pos]->is_fading=1; if(en->selection_chars[en->cursor_pos]->acceleration.vy==0) { 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; } else { en->arrows[1]->direction=1; en->arrows[1]->is_fading=1; en->arrows[1]->tmp=EN_BOUNCE_RIGHT_CURSOR; en->arrows[1]->velocity.vx=1*FPN24_8; en->arrows[1]->acceleration.vx=-0.1*FPN24_8; } PlaySoundEffect(sounds,&menu_volume,SFX_MENU_MOVE); } break; // Select a character for the name case SC_SELECT: if(en->cursor_pos==LEFT_CURSOR) { // Move to the previous characters if(en->cpage>0 && ChangedCPage(en)) { en->cpage--; n=MapCharacterToImage("A")+(en->cpage*MAX_CHARACTER_SELECTION); for(i=0;iselection_chars[i]->timer=i*5; en->selection_chars[i]->tmp=EN_FADE_TO_BLACK; // Set the next texture en->selection_chars[i]->extra[NEXT_TEXTURE_U]=font_sprite_info.offsets[n+i].u; en->selection_chars[i]->extra[NEXT_TEXTURE_V]=font_sprite_info.offsets[n+i].v; en->selection_chars[i]->extra[TIMER]=15; } PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } } else if(en->cursor_pos==RIGHT_CURSOR) { // Move to the next characters if(en->cpagecpage++; n=MapCharacterToImage("A")+(en->cpage*MAX_CHARACTER_SELECTION); for(i=0;iselection_chars[i]->timer=((MAX_CHARACTER_SELECTION-1)-i)*5; en->selection_chars[i]->tmp=EN_FADE_TO_BLACK; // Set the next texture en->selection_chars[i]->extra[NEXT_TEXTURE_U]=font_sprite_info.offsets[n+i].u; en->selection_chars[i]->extra[NEXT_TEXTURE_V]=font_sprite_info.offsets[n+i].v; en->selection_chars[i]->extra[TIMER]=15; } PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } } else { // Selected a character to go in the name byte c=(en->cpage*MAX_CHARACTER_SELECTION)+en->cursor_pos; if(en->name_pos=FIRST_UPPER_CASE_LETTER && c<=FULL_STOP) || c==RIGHT_ARROW) { if((o=CreateObject(en->list,GsSPRITE_OBJECT))) { x=en->selection_chars[en->cursor_pos]->screen.vx; y=en->selection_chars[en->cursor_pos]->screen.vy; x=en->dpos.vx; y=en->dpos.vy; en->oname[en->name_pos]=o; SetObjectsDefaultProperties(o); SetObjectsPosition(o,x,y,0); SetObjectsHandler(o,HandleEnterNameObject); o->tmp=EN_WAITING; o->direction=0; o->is_fading=0; spr=&o->type.gss; SetObjectsWidthHeight(o,en->selection_chars[en->cursor_pos]->w,en->selection_chars[en->cursor_pos]->h); en->dpos.vx+=o->w>>1; n=MapCharacterToImage("A")+(en->cpage*MAX_CHARACTER_SELECTION)+en->cursor_pos; if(c>=FIRST_UPPER_CASE_LETTER && cname[en->name_pos]='A'+c; else if(c>=FIRST_LOWER_CASE_LETTER && cname[en->name_pos]='a'+c-FIRST_LOWER_CASE_LETTER; else if(c>=FIRST_NUMBER && cname[en->name_pos]='0'+c-FIRST_NUMBER; else if(c==FULL_STOP) en->name[en->name_pos]='.'; else if(c==RIGHT_ARROW) { en->name[en->name_pos]=' '; o->visible=0; } en->name[++en->name_pos]=0; // Define the sprite SetGsSPRITE(spr,0,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,o->w>>1,o->h>>1,ONE,ONE,0); SetObjectsBrightness(o,&brightness[HIGHSCORE_TEXT_BRIGHTNESS]); PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); } } } switch(c) { // Delete a character case LEFT_ARROW: SelectCharacter(en,SC_DELETE); break; // Finished editing name case TICK_SYMBOL: en->finished=1; PlaySoundEffect(sounds,&menu_volume,SFX_MENU_SELECT); break; } } break; // Delete a character from the name case SC_DELETE: if(en->name_pos>0) { en->name_pos--; x=(rand()&1)+2; y=-((rand()&3)+3); if(rand()%2) x=-x; en->oname[en->name_pos]->tmp=EN_DELETE_CHARACTER; en->dpos.vx-=en->oname[en->name_pos]->w>>1; SetObjectsVelocity(en->oname[en->name_pos],x,y,0); SetObjectsAcceleration(en->oname[en->name_pos],0,0.2,0); en->oname[en->name_pos]->type.gss.attribute=TRANSPARENCY_ON|BG_PLUS_SP; en->name[en->name_pos]=0; PlaySoundEffect(sounds,&menu_volume,SFX_MENU_CANCEL); } break; case SC_ENTER_NAME: InsertHighScore(&highscore_table[0],en->name,en->score,en->level); break; // Move all the objects off screen case SC_ALL_OFF: for(i=0;iselection_chars[i],0,0.2,0); en->selection_chars[i]->tmp=EN_MOVE_OFF_CHARACTER; } for(i=0;i<2;i++) { SetObjectsAcceleration(en->arrows[i],0,0.2,0); en->arrows[i]->tmp=EN_MOVE_OFF_CHARACTER; } for(i=0;iname_pos;i++) { SetObjectsAcceleration(en->oname[i],0,0.2,0); en->oname[i]->tmp=EN_MOVE_OFF_CHARACTER; } break; // Jump to left cursor case SC_LEFT_CURSOR: if(en->cpage>0 && en->cursor_pos>-1) { en->set_pos=1; SelectCharacter(en,SC_LEFT); } break; // Jump to right cursor case SC_RIGHT_CURSOR: if(en->cpagecursor_posset_pos=1; SelectCharacter(en,SC_RIGHT); } break; } } // Function : ChangedCPage() // Coded by : Scott Evans // Created/Modified : 29/5/98 // Description : Has the page finished changing // Parameters : en - name data // Returns : None // Notes : None u_byte ChangedCPage(ENTER_NAME *en) { u_byte i,finished=1; // Have all the characters been changed if(en->cursor_pos==LEFT_CURSOR || en->cursor_pos==RIGHT_CURSOR) for(i=0;iselection_chars[i]->tmp!=EN_WAITING && en->selection_chars[i]->is_fading) { finished=0; break; } return(finished); } // Function : FinishedFading() // Coded by : Scott Evans // Created/Modified : 29/5/98 // Description : Has the characters finished fading // Parameters : None // Returns : None // Notes : None u_byte FinishedFading(ENTER_NAME *en) { u_byte i,finished=1; for(i=0;iselection_chars[i]->is_fading) { finished=0; break; } return(finished); } // Function : InsertHighScore() // Coded by : Scott Evans // Created/Modified : 29/5/98 // Description : Inserts players details into highscore table // Parameters : h - pointer to highscore table // n - pointer to name // s - score // l - level number // Returns : None // Notes : None void InsertHighScore(HIGHSCORE *h,u_char *n,u_long s,u_word l) { u_byte i; // Copy the players details into the table if(strlen(n)>0) strcpy(h[HIGHSCORE_TABLE_SIZE-1].name,n); else strcpy(h[HIGHSCORE_TABLE_SIZE-1].name,"B2"); h[HIGHSCORE_TABLE_SIZE-1].score=s; h[HIGHSCORE_TABLE_SIZE-1].level=l+1; // Indicate new entry into table for(i=0;i