/*************************************************************** main.c - step14 ====== ***************************************************************/ #include #include #include #include "pad.h" #include "addrs.h" #include "step14.h" #include "rg_rand.h" #include "music.h" // We need a viewing system for 3D graphics GsFOGPARAM fogging; GsRVIEW2 ViewPoint; u_long PADstatus=0; u_long GameRunning=TRUE; u_long VerticalSync; long gEnemiesKilled; // sound variable u_short BankId; char worldGroundData[GROUNDMAX_Z][GROUNDMAX_X] ={ {'5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','5','5','5','5','5','g','5','5','5','5','5','5','5','5','g','5','5','5','5','5','g','5','5','5','5','5','5'}, {'5','5','5','1','5','5','5','5','g','5','5','5','5','5','5','5','5','2','1','5','5','5','5','g','5','5','5','5','5','5'}, {'5','5','5','2','1','5','5','5','2','1','5','3','g','1','5','5','5','5','2','1','5','5','5','2','1','5','3','5','5','5'}, {'5','5','5','5','g','5','5','5','5','2','g','4','5','2','1','5','5','5','5','g','5','5','5','5','2','g','4','5','5','5'}, {'5','5','5','5','g','5','5','5','5','5','5','5','5','5','g','5','5','5','5','g','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','3','4','5','5','5','5','5','5','5','5','5','g','5','5','5','3','4','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','4','5','5','5','5','5','5','5','5','5','5','g','5','5','3','4','5','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','5','5','5','5','5','5','5','5','5','5','5','g','5','5','g','5','5','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','1','5','5','5','5','5','5','5','5','5','3','4','5','5','2','1','5','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','2','1','5','5','5','3','g','g','g','g','4','5','5','5','5','2','1','5','5','5','3','g','g','g','5','5','5'}, {'5','5','5','5','2','g','g','g','4','5','5','5','5','5','5','5','5','5','5','2','g','g','g','4','5','5','5','5','5','5'}, {'5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','5','6','6','6','6','6','5','5','5','5','5','5','g','g','g','5','6','6','6','6','6','5','5','5','5','5','5'}, {'5','5','5','g','g','g','g','1','5','5','5','5','5','5','5','g','g','g','g','g','g','g','1','5','5','5','5','5','5','5'}, {'5','5','5','4','5','6','6','2','1','5','5','5','5','5','5','5','5','g','4','5','6','6','2','1','5','5','5','5','5','5'}, {'5','5','5','5','5','5','5','5','g','5','5','5','5','5','5','5','5','g','5','5','5','5','5','g','5','5','5','5','5','5'}, {'5','5','5','1','5','5','5','5','g','5','5','5','5','5','5','5','5','2','1','5','5','5','5','g','5','5','5','5','5','5'}, {'5','5','5','2','1','5','5','5','2','1','5','3','g','1','5','5','5','5','2','1','5','5','5','2','1','5','3','5','5','5'}, {'5','5','5','5','g','5','5','5','5','2','g','4','5','2','1','5','5','5','5','g','5','5','5','5','2','g','4','5','5','5'}, {'5','g','g','5','g','5','5','5','5','5','5','5','5','5','g','5','5','5','5','g','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','3','4','5','5','5','5','5','5','5','5','5','g','5','5','5','3','4','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','4','5','5','5','5','5','5','5','5','5','5','g','5','5','3','4','5','5','5','5','5','5','5','5','5','5','5'}, {'5','g','g','5','5','5','5','5','5','5','5','5','5','5','g','5','5','g','5','5','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','1','5','5','5','5','5','5','5','5','5','3','4','5','5','2','1','5','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5'}, {'5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5','5'} }; char WorldOverlayData[GROUNDMAX_Z][GROUNDMAX_X] ={ {'0','0','1','1','1','0','0','0','1','0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}, {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}, {'0','0','1','2','1','2','2','1','1','1','2','2','2','2','1','1','1','1','1','1','2','2','1','1','1','1','2','1','0','0'}, {'0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1','0','0'}, {'0','0','1','0','2','0','0','0','0','0','0','0','0','1','0','1','0','0','0','2','0','0','0','0','0','0','0','2','0','0'}, {'0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2','0','0'}, {'0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2','0','0'}, {'0','0','2','0','0','0','0','0','0','0','0','0','2','0','0','0','1','0','0','2','2','0','0','0','0','0','0','1','0','0'}, {'0','0','2','0','0','0','0','0','1','0','1','2','1','2','0','0','0','0','0','0','0','0','0','1','0','1','2','1','0','0'}, {'0','0','1','0','0','0','0','0','0','1','0','0','0','0','0','0','0','0','0','0','1','0','0','0','1','0','0','1','0','0'}, {'0','0','2','0','0','0','0','0','0','1','0','0','2','0','0','0','0','0','0','0','1','0','0','0','1','0','0','1','0','0'}, {'0','0','2','0','0','0','0','0','0','0','0','0','0','0','0','0','1','0','0','0','1','0','0','0','0','0','0','1','0','0'}, {'0','0','1','0','0','0','0','1','0','0','0','0','0','0','0','2','0','0','0','0','0','0','1','0','0','0','0','1','0','0'}, {'0','0','1','0','0','0','0','0','0','2','0','0','0','0','0','0','1','0','0','0','0','0','0','0','2','0','0','1','0','0'}, {'0','0','1','0','2','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2','0','0','0','0','0','0','0','2','0','0'}, {'0','0','1','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1','0','0','0','0','0','0','0','2','0','0'}, {'0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1','0','0'}, {'0','0','2','0','0','0','0','0','0','0','0','0','2','0','0','2','2','0','0','0','0','0','0','0','0','0','0','2','0','0'}, {'0','0','2','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1','0','0'}, {'0','0','1','0','2','0','0','0','0','0','0','0','0','1','0','1','0','0','0','2','0','0','0','0','0','0','0','1','0','0'}, {'0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2','0','0'}, {'0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1','0','0'}, {'0','0','2','0','0','0','0','0','0','0','0','0','2','0','0','0','1','0','0','0','0','0','0','0','0','0','0','1','0','0'}, {'0','0','1','0','0','0','0','0','1','0','1','2','1','2','0','0','0','0','0','0','0','0','0','1','0','1','2','1','0','0'}, {'0','0','1','0','0','0','0','0','0','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1','0','0','2','0','0'}, {'0','0','2','0','0','0','0','0','0','1','0','0','2','0','0','0','0','0','0','0','0','0','0','0','1','0','0','2','0','0'}, {'0','0','2','0','0','0','0','0','0','0','0','0','0','0','0','0','1','0','0','0','0','0','0','0','0','0','0','1','0','0'}, {'0','0','1','2','1','2','2','1','1','1','2','2','2','2','1','1','1','1','1','1','2','2','1','1','1','1','2','1','0','0'}, {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}, {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'} }; /************* Function prototypes ***********/ void RenderWorld(); void RotateModelMatrix (PlayerStruct *thePlayer, int nRX, int nRY, int nRZ, int bx1, int bx2, int by1, int by2, int bz1, int bz2 ); void AdvanceModel (PlayerStruct *thePlayer, int bx1, int bx2, int by1, int by2, int bz1, int bz2, int nD); void CheckTerrainCollisions(PlayerStruct *thePlayer, int nD); void CheckPlayerCollisions(PlayerStruct *player1, PlayerStruct *player2); void MoveEnemy(EnemyStruct *theEnemy); void UpdatePlayerCoords(PlayerStruct *thePlayer); int EnemyWithinClipRange(long z, long x); /******************************************************************/ int EnemyWithinClipRange(long z, long x) { return ( ( ( z >= ClipZStart) && ( z <= ClipZEnd ) ) && ( ( x >= ClipXStart) && ( x <= ClipXEnd ) ) ); } // This function deals with double buffering and drawing of 3D objects void RenderWorld() { int loop; RenderPrepare(); DrawWorld(&WorldGround,WORLD_GROUND_PRECISION); DrawWorld(&WorldOverlay,WORLD_OVERLAY_PRECISION); DrawPlayer(&TheCar); for(loop = 0; loop < NUM_ENEMIES; loop++) { if ( EnemyWithinClipRange( enemies[loop].player_data.row, enemies[loop].player_data.col ) ) { DrawPlayer(&enemies[loop].player_data); } else { // printf("Enemy not being drawn"); } } DrawBullet(&TheBullet,WORLD_OVERLAY_PRECISION); // wait for V_BLANK interrupt VerticalSync=VSync(0); slongrand(VerticalSync); // print the vSync interval // FntPrint("VSync Interval: %d.\n",VerticalSync); // force text output to the PSX screen FntFlush(-1); RenderFinish(); } void RotateModelMatrix (PlayerStruct *thePlayer, int nRX, int nRY, int nRZ, int bx1, int bx2, int by1, int by2, int bz1, int bz2 ) { MATRIX matTmp; SVECTOR svRotate; VECTOR startVector; // This is the vector describing the rotation svRotate.vx = nRX; svRotate.vy = nRY; svRotate.vz = nRZ; // RotMatrix sets up the matrix coefficients for rotation RotMatrix(&svRotate, &matTmp); // Concatenate the existing objects matrix with the // rotation matrix //&TheCar.Model.Object_Coord,&TheCar.Direction MulMatrix0(&thePlayer->Model.Object_Coord.coord, &matTmp,&thePlayer->Model.Object_Coord.coord); // condition the matrix AdjustCoordinate2(&thePlayer->Model.Object_Coord); // set up the vector corresponding to the starting orientation startVector.vx = 0; startVector.vy = 0; startVector.vz = ONE; // apply the objects matrix to the start vector to give the current direction //ApplyMatrixLV(&Object_Coord->coord, &startVector, currentDirection); thePlayer->Direction.vx=thePlayer->Model.Object_Coord.coord.m[0][2]; thePlayer->Direction.vy=thePlayer->Model.Object_Coord.coord.m[1][2]; thePlayer->Direction.vz=thePlayer->Model.Object_Coord.coord.m[2][2]; SetBoundingBox(thePlayer->Range,thePlayer->Model.Object_Coord.coord.t[0], thePlayer->Model.Object_Coord.coord.t[1], thePlayer->Model.Object_Coord.coord.t[2], bx1, bx2, by1, by2, bz1, bz2); //-205,205,-158,158,-500,500); CheckTerrainCollisions(thePlayer, nRY); thePlayer->Model.Object_Coord.flg = 0; } void AdvanceModel (PlayerStruct *thePlayer, int bx1, int bx2, int by1, int by2, int bz1, int bz2, int nD) { if (nD==0) return; // avoid divide by 0 error nD = ONE/nD; //&TheCar.Model.Object_Coord,&TheCar.Direction thePlayer->Model.Object_Coord.coord.t[0] += thePlayer->Direction.vx/ nD; thePlayer->Model.Object_Coord.coord.t[1] += thePlayer->Direction.vy/ nD; thePlayer->Model.Object_Coord.coord.t[2] += thePlayer->Direction.vz/ nD; thePlayer->Model.Object_Coord.flg = 0; SetBoundingBox(thePlayer->Range,thePlayer->Model.Object_Coord.coord.t[0], thePlayer->Model.Object_Coord.coord.t[1], thePlayer->Model.Object_Coord.coord.t[2], bx1, bx2, by1, by2, bz1, bz2); //-205,205,-158,158,-500,500); CheckTerrainCollisions(thePlayer, nD); } void ProcessUserInput() { int tmpz,tmpx; PADstatus=PadRead(); if(PADstatus & PADselect)GameRunning=0; if(PADstatus & PADLleft){ //FntPrint( "Left Arrow: Rotate Left\n"); RotateModelMatrix (&TheCar, 0, -16, 0, -205,205,-158,158,-500,500 ); } if(PADstatus & PADLright){ //FntPrint ( "Right Arrow: Rotate Right\n"); RotateModelMatrix (&TheCar, 0, 16, 0, -205,205,-158,158,-500,500 ); } if(PADstatus & PADcross){ //FntPrint ( "PAD cross: Move Forward\n"); AdvanceModel(&TheCar, -205,205,-158,158,-500,500, 64); } if (PADstatus & PADsquare){ //FntPrint ( "PAD square Move Backward\n"); AdvanceModel(&TheCar, -205,205,-158,158,-500,500, -64); } if (PADstatus & PADL1){ //FntPrint ( "PAD padL1:STATIC_VIEW\n"); // InitialiseStaticView(&ViewPoint, 250, 0, 0, -500,-1000, 0, 0, 0 ); //FntPrint ( "PAD padL1:3RD PERSON VIEW\n"); InitialiseTrackerView(&ViewPoint, 250, 0, 0, -500, -1000, 0,0,0,&TheCar.Model.Object_Coord); } if (PADstatus & PADL2) { //FntPrint ( "PAD padL2: 1ST PERSONVIEW\n"); InitialiseTrackerView(&ViewPoint, 250, 0, 0, -200, 0, 0,0,1000,&TheCar.Model.Object_Coord); } if (PADstatus & PADR1){ //FntPrint ( "PAD padR1:Shoot\n"); if (TheBullet.active==0){ TheBullet.Model.Object_Handler.attribute=TheBullet.Model.Object_Handler.attribute&(0<<31); TheBullet.active=1; SetBulletVector(&TheCar.Model.Object_Coord,TheCar.Direction,&TheBullet); AdvanceBullet(&TheBullet); } } /*if (PADstatus & PADR2) { //FntPrint ( "PAD padL2: Overhead\n"); InitialiseTrackerView(&ViewPoint, 250, 0, 0, -10000, 0, 0,0,0,&TheCar.Model.Object_Coord); } */ if(PADstatus & PADstart){ //FntPrint ( "PAD start\n" ); TheCar.Model.Object_Coord.coord=GsIDMATRIX; TheCar.Model.Object_Coord.coord.t[0]=PLAYER_START_X; TheCar.Model.Object_Coord.coord.t[1]=PLAYER_START_Y; TheCar.Model.Object_Coord.coord.t[2]=PLAYER_START_Z; TheCar.Direction.vx=0;TheCar.Direction.vy=0;TheCar.Direction.vz=ONE; //RotateModelMatrix (&TheCar.Object_Coord,&TheCar.Direction, 0, 0, 0 ); TheCar.Model.Object_Coord.flg=0; for (tmpz = 0; tmpz < GROUNDMAX_Z; tmpz++ ){ for (tmpx = 0; tmpx < GROUNDMAX_X; tmpx++ ){ if ((!(WorldGround.ModelMap[tmpz][tmpx]=='0'))&& (WorldOverlay.Model[tmpz][tmpx].Object_Handler.attribute&(1<<31))) { WorldOverlay.Model[tmpz][tmpx].Object_Handler.attribute ^=(1<<31); WorldOverlay.Model[tmpz][tmpx].Object_Coord.flg=0; } } } } } void CheckPlayerCollisions(PlayerStruct *player1, PlayerStruct *player2) { if (CollisionDetect(player1->Range, player2->Range)) { FntPrint("Hit pixie!\n"); //TheCar.Model.Object_Coord,&TheCar.Direction player2->Model.Object_Coord.coord.t[0] -= (player1->Direction.vx/ 64)*2;//64; player2->Model.Object_Coord.coord.t[1] -= (player1->Direction.vy/ 64)*2; player2->Model.Object_Coord.coord.t[2] -= (player1->Direction.vz/ 64)*2;//64; player1->Model.Object_Coord.coord.t[0] -= (player1->Direction.vx/ 64)*2;//64; player1->Model.Object_Coord.coord.t[1] -= (player1->Direction.vy/ 64)*2; player1->Model.Object_Coord.coord.t[2] -= (player1->Direction.vz/ 64)*2;//64; PlaySound(BankId, 0, 0, 72); /* FntPrint("Pixie killed!\n"); gEnemiesKilled ++; InitialisePlayerModel(player2, ENEMY_START_X, ENEMY_START_Y, ENEMY_START_Z, (u_long*)MAN_TMD, -50,50,-150,0,-50,50); */ } } void CheckTerrainCollisions(PlayerStruct *thePlayer, int nD) { int tmpz,tmpx; limitrange(thePlayer->Model.Object_Coord.coord.t[2], 3*GROUNDSIZE, (GROUNDMAX_Z-4)*GROUNDSIZE); limitrange(thePlayer->Model.Object_Coord.coord.t[0], 3*GROUNDSIZE, (GROUNDMAX_X-4)*GROUNDSIZE); for (tmpz = thePlayer->row - 1; tmpz < thePlayer->row + 2; tmpz++ ) { for (tmpx = thePlayer->col - 1; tmpx < thePlayer->col + 2; tmpx++ ) { if(!(WorldOverlay.ModelMap[tmpz][tmpx]=='0')&& (!(WorldOverlay.Model[tmpz][tmpx].Object_Handler.attribute&(1<<31)))&& CollisionDetect(thePlayer->Range, WorldOverlay.Range[tmpz][tmpx])) { //FntPrint("Hit terrain\n"); PlaySound(BankId, 0, 0, 60); thePlayer->Model.Object_Coord.coord.t[0] -= (thePlayer->Direction.vx/ nD)*2;//64; thePlayer->Model.Object_Coord.coord.t[1] -= (thePlayer->Direction.vy/ nD)*2; thePlayer->Model.Object_Coord.coord.t[2] -= (thePlayer->Direction.vz/ nD)*2;//64; } } } } int rand_range(int range) { int value = longrand() & 0xff; return ((value * range)>>8); } void MoveEnemy(EnemyStruct *theEnemy) { short whichWay[] = {-1, 1, 0, 0, 1, -1, 0}; if (theEnemy->amount <= 0) { theEnemy->amount = rand_range(32); theEnemy->randomRotate = rand_range(4); theEnemy->randomMove = rand_range(3); //printf("amount = %d, random = %d\n",amount,random); } // *whichWay[theEnemy->randomRotate] *whichWay[theEnemy->randomMove] RotateModelMatrix (&theEnemy->player_data, 0, 32*whichWay[theEnemy->randomRotate], 0, -50,50,-75,75,-50,50 ); AdvanceModel(&theEnemy->player_data, -50,50,-75,75,-50,50, 64*whichWay[theEnemy->randomMove]); theEnemy->amount--; } void UpdatePlayerCoords(PlayerStruct *thePlayer) { thePlayer->col = (thePlayer->Model.Object_Coord.coord.t[2] + GROUNDSIZEDIV2)/ GROUNDSIZE; thePlayer->row = (thePlayer->Model.Object_Coord.coord.t[0] + GROUNDSIZEDIV2)/ GROUNDSIZE; } int main() { int loop; gEnemiesKilled = 0; printf("testing"); datafile_search(); datafile_read(); LoadTextures(); // set up print-to-screen font, the parameters are where the font is // loaded into the frame buffer FntLoad(960, 256); //specify where to write on the PSX screen FntOpen(-128, -96, 256, 64, 0, 512); // initialise the joypad PadInit(); // initialise graphics Initialise3DGraphics(); // Setup view to view from car bonnet looking along the z axis InitialiseTrackerView(&ViewPoint, 250, 0, 0, -200, 0, 0,0,1000,&TheCar.Model.Object_Coord); InitialiseLights(); // The car's initial xyz is set to 0,-200,0 InitialisePlayerModel(&TheCar, PLAYER_START_X, PLAYER_START_Y, PLAYER_START_Z, (u_long*)CAR01_TMD, -300,300,-600,0,-300,300); for(loop = 0; loop < NUM_ENEMIES; loop++) { InitialisePlayerModel(&enemies[loop].player_data, ENEMY_START_X, ENEMY_START_Y, ENEMY_START_Z, (u_long*)MAN_TMD, -50,50,-150,0,-50,50); enemies[loop].amount = 0; } // initialise the world objects InitialiseWorld(); InitialiseBullet(&TheBullet,0,0,0,(long*)BALL_TMD); // init fogging fogging.dqa = -3500; fogging.dqb = 5120*5120*1.0; fogging.rfc = fogging.gfc = fogging.bfc = 0; GsSetLightMode(1); GsSetFogParam(&fogging); //init sound BankId = InitialiseSound(SOUNDS_VH, SOUNDS_VB); // init music init_music(); play_music(); while(GameRunning){ UpdatePlayerCoords(&TheCar); ProcessUserInput(); ClipWorld(TheCar.Model.Object_Coord.coord.t[0],TheCar.Model.Object_Coord.coord.t[2]); // advance enemy - numbers passed are bounding box details for(loop = 0; loop < NUM_ENEMIES; loop++) { UpdatePlayerCoords(&enemies[loop].player_data); MoveEnemy(&enemies[loop]); CheckPlayerCollisions(&TheCar, &enemies[loop].player_data); } AdvanceBullet(&TheBullet); FntPrint("Pixies killed: %d\n", gEnemiesKilled); RenderWorld(); } // clean up StopSound(); stop_music(); ResetGraph(3); return 0; }