// C Header File // Created 11/27/2002; 1:01:04 PM static inline short ValidMove (short x, short y); void PlayerTurn(short right,short increment); static inline void PlayerMove (short forward_right, short strafe, short shiftmore); static inline void pauseGame(void); static inline void bossKey(void); static inline short HandlePlayerMovement(void); static inline void PlayerMove2(short newxpos, short newypos); #ifndef __PLAYER_H__ #define __PLAYER_H__ #include "gfx.h" #include "weapons.h" #include "sprites_init.h" //============================================================================= // returns 0 if move would bring the character too near to a wall //============================================================================= static inline short ValidMove (short x, short y) { #define WALLDST 19 register char *ptr = fc->map_data; register short width = fc->map_width; char val1 = *(ptr+((y+WALLDST)>>6)*width+((x+WALLDST)>>6)); char val2 = *(ptr+((y-WALLDST)>>6)*width+((x-WALLDST)>>6)); char val3 = *(ptr+((y+WALLDST)>>6)*width+((x-WALLDST)>>6)); char val4 = *(ptr+((y-WALLDST)>>6)*width+((x+WALLDST)>>6)); // if we would come too near to a solid square... if ((val1>0)||(val2>0)||(val3>0)||(val4>0)|| (val1==impassibleWall)||(val2==impassibleWall)|| (val3==impassibleWall)||(val4==impassibleWall)|| (val1==solidSprite)||(val2==solidSprite)|| (val3==solidSprite)||(val4==solidSprite)) return 0; // false return 1; // true #undef WALLDST } //============================================================================= // turn player left or right ... //============================================================================= void PlayerTurn(short right,short increment) { fc->cam_orientation += (right) ? increment : -increment; // now clamp the camera orientation to the valid range of 0 ... 575 fc->cam_orientation = FAT_ClampAngle(fc->cam_orientation); } //============================================================================= // move player forward or backward depending on player's angle ... // // special player move routine (takes doors into account) AND don't allows // the user to come too near to a wall, but try to slide automatically. //============================================================================= static inline void PlayerMove (short forward_right, short strafe, short shiftmore) { short tmp = (strafe) ? +ANGLE_090 : 0; short stepx = FAT_Cos16384 (fc->cam_orientation + tmp) >> (10+shiftmore); short stepy = FAT_Sin16384 (fc->cam_orientation + tmp) >> (10+shiftmore); short newxpos = fc->cam_xpos + ((forward_right) ? stepx : -stepx); short newypos = fc->cam_ypos + ((forward_right) ? stepy : -stepy); short newxmod = newxpos >> 6; short newymod = newypos >> 6; //------------------------------------------------------------------------- // check if we are still within the map //------------------------------------------------------------------------- if (newxmod > fc->map_width - 1 || newymod > fc->map_height - 1 || newxmod < 0 || newymod < 0) { return; } if (!ValidMove (newxpos, newypos)) { // if new position is invalid ... gg->hitwall = TRUE; // ...but old position is OK, we're against a wall to east or west if (ValidMove (fc->cam_xpos, newypos)) { // don't change angle if movement is perpendicular to the wall if (stepy != 0) { // still allow movement along y = parallel to wall fc->cam_ypos = newypos; } } // ...but (new x, old y) is OK, we're against a wall to north or south if (ValidMove (newxpos, fc->cam_ypos)) { // don't change angle if movement is perpendicular to the wall if (stepx != 0) { // still allow movement along x = parallel to wall fc->cam_xpos = newxpos; } } // ...otherwise we're in a corner, so do nothing return; } //------------------------------------------------------------------------- // everything okay -> let's set the new position //------------------------------------------------------------------------- fc->cam_xpos = newxpos; fc->cam_ypos = newypos; } static inline void PlayerMove2(short newxpos, short newypos) { short newxmod = newxpos >> 6; short newymod = newypos >> 6; //------------------------------------------------------------------------- // check if we are still within the map //------------------------------------------------------------------------- if (newxmod > fc->map_width - 1 || newymod > fc->map_height - 1 || newxmod < 0 || newymod < 0) { return; } if (!ValidMove(newxpos, newypos)) { // if new position is invalid ... // ...but old position is OK, we're against a wall to east or west if (ValidMove( fc->cam_xpos, newypos)) { // don't change angle if movement is perpendicular to the wall //if (stepy != 0) { // still allow movement along y = parallel to wall fc->cam_ypos = newypos; } } // ...but (new x, old y) is OK, we're against a wall to north or south if (ValidMove( newxpos, fc->cam_ypos)) { // don't change angle if movement is perpendicular to the wall //if (stepx != 0) { // still allow movement along x = parallel to wall fc->cam_xpos = newxpos; } } // ...otherwise we're in a corner, so do nothing return; } //------------------------------------------------------------------------- // everything okay -> let's set the new position //------------------------------------------------------------------------- fc->cam_xpos = newxpos; fc->cam_ypos = newypos; } static inline void pauseGame(void) { short key; FAT_AllKeysReleased(); GrayOff(); RestoreHandlerForINTs(); OSqclear(kbd_queue()); #ifdef USE_SOUND pSnd_UninstallSound (); pSnd_DisableSound (); #endif ClrScr(); FontSetSys(F_8x10); DrawStr(54+display_offsetx,30+display_offsety,stringIdx(gamestrings,ePaused),A_NORMAL); DrawStr(24+display_offsetx,60+display_offsety,stringIdx(gamestrings,ePressAnyKey),A_NORMAL); FontSetSys(F_4x6); DrawStr(24+display_offsetx,80+display_offsety,stringIdx(gamestrings,ePressOnToTurnOff),A_NORMAL); key = GKeyIn(NULL,0); //Waits for a key, idles, can turn the calc off, etc. if(key == KEY_ON || key == KEY_OFF) off(); InstallDummyHandlerForINTs(); #ifdef USE_SOUND USE_GRAY_WITH_POLYSND; #endif GrayOn(); #ifdef USE_SOUND pSnd_PlayMode (MONO); pSnd_SetTempo (MUSIC_TEMPO); //pSnd_PlaySound_voice1 (channel1); pSnd_PlaySound_voice1 (channel2); pSnd_SetState (VOICE1); #endif gg->plane1 = GetPlane(0); gg->plane2 = GetPlane(1); DisplayGUI(); } static inline void bossKey(void) { register GameGlobals *ggg asm("a4") = gg; //short key = 0; //char quit = 0; FAT_AllKeysReleased(); GrayOff(); #ifdef USE_SOUND pSnd_UninstallSound (); pSnd_DisableSound (); #endif //RestoreHandlerForINTs(); /*FastCopyScreen(glcd,LCD_MEM); FontSetSys(F_6x8); { EVENT ev; TEXT_EDIT te; HANDLE h = HeapAlloc (200); // initial buffer size if(h) { memset (HeapDeref (h), 0, 200); TE_open (&te, DeskTop, MakeWinRect (0, CALCULATOR?111:85, CALCULATOR?239:159, CALCULATOR?121:93), h, 0, 0, 0); CU_start (); // Enable the cursor while ((key=EV_getc (ACTIVITY_BUSY, &ev)) != KEY_ESC) // Get keypress and translate it to { // the event (until ESC pressed) if(key==KEY_F1) {quit++;break;} TE_handleEvent (&te, &ev); // Send the event to the editor } // to be processed HeapFree(h); } } if(quit) {*/ //int1_counter = 0; ggg->quitting = FORCE_QUIT; return; /*} FontSetSys(F_4x6); if(key == KEY_ON || key == KEY_OFF) off(); InstallDummyHandlerForINTs(); GrayOn(); plane1 = GetPlane(0); plane2 = GetPlane(1); DisplayGUI();*/ } static inline short HandlePlayerMovement(void) { register GameGlobals *ggg asm("a4") = gg; PADSTATES key = FAT_GetPadState(); short s; ggg->turning = FALSE; ggg->strafe_flag = FALSE; ggg->oldChgbutton_flag = ggg->chgbutton_flag; ggg->chgbutton_flag = FALSE; ggg->shoot_flag = FALSE; ggg->speedup_flag = FALSE; ggg->oldhitwall = ggg->hitwall; ggg->hitwall = FALSE; if(ggg->automove) { SWAP(ggg->cur_orientation,fc->cam_orientation); PlayerMove(1,0,0); if(ggg->speedup_flag) PlayerMove(1,0,0); SWAP(ggg->cur_orientation,fc->cam_orientation); }//end if automove if(!ggg->autokeys && ggg->levelstyle != level_vehicle) { if(KeyCheck(KEY_PRESSBUTTON)) ggg->chgbutton_flag = TRUE; if(KeyCheck(KEY_FIRE)) ggg->shoot_flag = TRUE; if(KeyCheck(KEY_STRAFE)) ggg->strafe_flag = TRUE; if(KeyCheck(KEY_SWITCHWEAPON)) if(!ggg->switchweapon_flag) ggg->switchweapon_flag = MAX_CHGWEAPON; if(KeyCheck(KEY_SPEEDUP)) ggg->speedup_flag = TRUE; }//end if autokeys if(ggg->levelstyle != level_vehicle) { if (key) { if (key & PADSTATE_ESC) return 0; if(!ggg->automove) { if (key & PADSTATE_UPDOWN) { PlayerMove(key & PADSTATE_UP,0,0); if(ggg->speedup_flag) PlayerMove(key & PADSTATE_UP,0,0); }//end if UPDOWN if (key & PADSTATE_LEFTRIGHT) { // STRAFE if (ggg->strafe_flag) { PlayerMove(key&PADSTATE_RIGHT,1,0); if(ggg->speedup_flag) PlayerMove(key&PADSTATE_RIGHT,1,0); }//end STRAFE }//end if LEFTRIGHT } //end if NOT AUTOMOVE if(!ggg->autoturn) { if (key & PADSTATE_LEFTRIGHT && !ggg->strafe_flag) { PlayerTurn(key&PADSTATE_RIGHT,TURN_SIZE); if(ggg->speedup_flag) PlayerTurn(key&PADSTATE_RIGHT,TURN_SIZE); ggg->turning = TRUE; } } //end if NOT AUTOTURN } //end if KEY }//end if not level_vehicle else //is level_vehicle { if (key & PADSTATE_ESC) return 0; for(s=0;svehicle_speed>>1);s++) PlayerMove(ggg->vehicle_speed>0,0,2); if (key & PADSTATE_UPDOWN) { if((key & PADSTATE_UP)&&ggg->vehicle_speedvehicle_speed++; if((key & PADSTATE_DOWN)&&ggg->vehicle_speed>-MAX_VEHICLE_SPEED) ggg->vehicle_speed--; } if (key & PADSTATE_LEFTRIGHT) { PlayerTurn((ggg->vehicle_speed>0)?key&PADSTATE_RIGHT:!(key&PADSTATE_RIGHT), (ANGLE_015/12)*ggg->vehicle_speed>>1); if(ggg->vehicle_speed) ggg->turning = TRUE; } } if(CIGAM) TAEHC; #ifdef DEBUG if(_keytest(RR_APPS)) { ggg->quitting = NEW_LEVEL; FAT_AllKeysReleased(); GrayOff(); RestoreHandlerForINTs(); #ifdef USE_SOUND pSnd_UninstallSound (); pSnd_DisableSound (); #endif ClrScr(); short key,one=0,two=0; key = ngetchx(); if(isdigit(key)) { one = key-'0'; DrawChar(0,0,key,A_REPLACE); key = ngetchx(); if(isdigit(key)) { two = key-'0'; DrawChar(8,0,key,A_REPLACE); while(!kbhit()); one = one*10 + two; if(one) ggg->current_level = one-1; } else ggg->current_level = two-1; } InstallDummyHandlerForINTs(); #ifdef USE_SOUND pSnd_PlayMode (STEREO); pSnd_SetTempo (160*2); pSnd_PlaySound_voice1 (channel1); pSnd_PlaySound_voice2 (channel2); pSnd_SetState (ALLVOICES); USE_GRAY_WITH_POLYSND; #endif GrayOn(); ggg->plane1 = GetPlane(0); ggg->plane2 = GetPlane(1); } if(_keytest(RR_BCKSPC)) { short levelnum = ggg->current_level; do { levelnum--; } while(levelnum && #include "noprevlevels.txt" ); if(levelnum) {ggg->quitting=OLD_LEVEL;ggg->current_level=levelnum+1;} } #endif if(KeyCheck(KEY_PAUSE)) pauseGame(); if(KeyCheck(KEY_BOSS)) { bossKey(); if(ggg->quitting == FORCE_QUIT) return 0; } if(KeyCheck(KEY_SAVE)) { while(KeyCheck(KEY_SAVE)) continue; TransparentAutoSaveMid(); textEnqueue(stringIdx(gamestrings,eGameSaved)); } if(KeyCheck(KEY_LOAD)) { if(ggg->beginningSaveIsLoaded||ggg->midSaveIsLoaded) { //Double check this one... from experience :-) while(KeyCheck(KEY_LOAD)) continue; DrawGrayStr(display_offsetx,40+display_offsety, stringIdx(gamestrings,ePressLoadToConfirm),A_REPLACE); DrawGrayStr(display_offsetx,47+display_offsety, stringIdx(gamestrings,ePressHomeToRestart),A_REPLACE); FAT_WaitKeyPressed(); if(KeyCheck(KEY_LOAD)&&ggg->midSaveIsLoaded) { ggg->quitting = LOAD_SAVE; } else if(ggg->beginningSaveIsLoaded && _keytest(RR_HOME)) ggg->quitting = PLAYER_DIED; } } if(ggg->levelstyle==level_vehicle) { if(ggg->hitwall && !ggg->oldhitwall) { PlayerLife(-1); ggg->vehicle_speed = 2; } } return 1; } #endif