// main.c // BUGGY DEMO //----------- // Ive written must of this while I was half a sleep, probably explains // any wierdness within the code. Saying that, Im always half asleep ??? // INCLUDES //---------- #include #include #include "pad.h" #include "addrs.h" #include "height.h" // also includes 3dgraph.h // DEFINES //--------- #define TITLE (0) #define GAME (1) #define QUIT (9) // STRUCTS / UNION //----------------- // PROTOTYPES //------------ void UpdateWorldTitle(); void RenderWorldTitle(); u_long ProcessUserInputTitle(); void UpdateWorldGame(); void RenderWorldGame(); u_long ProcessUserInputGame(); void UpdateObject(ObjectStruct *theObject); // GLOBALS //--------- ObjectStruct buggy; GsRVIEW2 ViewPoint; //viewing system u_long PADstatus=0; // pad varible status u_long VerticalSync=0; // used for v sync speed test thingy ! ////////////////////////////////////////////////////////////////////// // FUNCTIONS //----------- // ** TITLE SCREEN FUNCTIONS ** //------------------------------ // Draw title screen stuff void RenderWorldTitle() { RenderPrepare(); FntPrint(" Title Screen\n\n "); FntPrint(" X = starts\n "); FntPrint(" select and start = Quits "); FntFlush(-1); RenderFinish(); } // Update title selections to match those on screen. void UpdateWorldTitle() { }; // Simply menu selection style input for // the title screen. u_long ProcessUserInputTitle() { // create PAD variable to hold states of both joypads u_long PAD = PadRead(); // standard check. Quit if pad1 has start + select pressed if ((PAD& PADstart) && (PAD& PADselect)) return(QUIT); if (PAD& PADcross) return (GAME); //if (PAD& PADLup) ; //if (PAD& PADLdown); return(TITLE); } /////////////////////////////////////////////////////////////////////// // ** GAME FUNCTIONS ** // This function deals with double buffering and drawing of 3D objects, // also takes care of onscreen displays such as scores etc. void RenderWorldGame() { RenderPrepare(); DrawMap(); DrawObject(&buggy); VerticalSync = VSync(0); //print your message FntPrint("Game\n"); FntPrint(" \n%d/320\n ",VerticalSync); FntPrint("X =%d\n", ViewPoint.vpx); FntPrint("Y =%d\n", ViewPoint.vpy); // force text output to the PSX screen FntFlush(-1); GsSetRefView2(&ViewPoint); //????????? RenderFinish(); } // Simply updates everything within the game. void UpdateWorldGame() { UpdateObject(&buggy); //Update scores and titles etc }; // Processes all inputs during the game. Simply adjusts player object varibles. // All important player stuff is taken care of else where. u_long ProcessUserInputGame() { // create PAD variable to hold states of both joypads u_long PAD = PadRead(); // standard check. Quit if pad1 has start pressed buggy.PedalDown = FALSE; if (PAD& PADstart) return(TITLE); if (PAD& PADLleft) buggy.yAngle -= buggy.TurnSpeed; if (PAD& PADLright)buggy.yAngle += buggy.TurnSpeed; if (PAD& PADcross) { buggy.Acceleration += buggy.AccelerateSpeed; buggy.PedalDown = TRUE; } if (PAD& PADsquare) { buggy.Acceleration -= buggy.AccelerateSpeed; buggy.PedalDown = TRUE; } // if (PAD& PADtriangle) // if(PAD& PADcircle) if(PAD& PADselect) { buggy.Object_Coord.coord = GsIDMATRIX; buggy.Object_Coord.flg = 0; } return(GAME); } ///////////////////////////////////////////////////////////////////////////////// // ** OBJECT FUNCTIONS ** // This function updates the given object according to its position. It'll set // up the object with the correct height and rotation and also move the object // accordinly, also applys physics to the model. // [Only use this function for moving objects.] // This function is pretty long and hard to follow so there are a lot of comments // within. void UpdateObject(ObjectStruct *theObject) { MATRIX matTemp; SVECTOR Rotation1,Rotation2,Rotation3, forward; VECTOR tempDirection; long HeightToLeft, HeightToRight; long HeightToFront, HeightToBack; // ORIENTATION BIT matTemp = GsIDMATRIX; // set Direction forward.vx = 0; forward.vz = -1000; // needs to be the same size as in Tan calulation (FindOrientation())?????? forward.vy = 0; // clip Y rotation (just to be on the safe side !) if(theObject->yAngle > 4095) theObject->yAngle = theObject->yAngle - 4096; if(theObject->yAngle < 0 ) theObject->yAngle = 4096 + theObject->yAngle; // setup rotation vector Rotation1.vx = 0; Rotation1.vy = theObject->yAngle; Rotation1.vz = 0; // rotate forward vector. So I have a vector that goes directly in front. RotMatrix(&Rotation1,&matTemp); ApplyMatrix(&matTemp,&forward,&theObject->Direction); // Set objects height theObject->Object_Coord.coord.t[1] = FindHeight(theObject->Object_Coord.coord.t[0], theObject->Object_Coord.coord.t[2]) - 500; // Find offset heights for the front and back of object HeightToFront = FindHeight(theObject->Object_Coord.coord.t[0]+(theObject->Direction.vx), theObject->Object_Coord.coord.t[2]+(theObject->Direction.vz))-500; HeightToBack = FindHeight(theObject->Object_Coord.coord.t[0]-(theObject->Direction.vx), theObject->Object_Coord.coord.t[2]-(theObject->Direction.vz))-500; // setup rotation vector again this time at an extra 90 degrees. So // I have a vector that goes out to the side of the object. matTemp = GsIDMATRIX; Rotation1.vx = Rotation1.vz = 0; Rotation1.vy = theObject->yAngle + 1024; // rotate forward vector RotMatrix(&Rotation1,&matTemp); ApplyMatrix(&matTemp,&forward,&tempDirection); // Find offset heights for the left and right of the object HeightToRight = FindHeight(theObject->Object_Coord.coord.t[0]+(tempDirection.vx), theObject->Object_Coord.coord.t[2]+(tempDirection.vz))-500; HeightToLeft = FindHeight(theObject->Object_Coord.coord.t[0]-(tempDirection.vx), theObject->Object_Coord.coord.t[2]-(tempDirection.vz))-500; //Set Objects X Rotation Vector Rotation2.vx = FindRotation(HeightToFront,HeightToBack,2000); Rotation2.vy = Rotation2.vz = 0; FntPrint(" vx = %d ",Rotation2.vx); //Set Objects Z Rotation Vector. Rotation3.vz = FindRotation(HeightToLeft,HeightToRight,2000); Rotation3.vy = Rotation3.vx = 0; FntPrint(" vz = %d ",Rotation3.vz); // Set Objects Y Rotation Vector. Rotation1.vy = theObject->yAngle; Rotation1.vx = Rotation1.vz = 0; FntPrint(" vy = %d ",Rotation1.vy); // Reset Matrix without losing translations. // [this also stops rotation deformations accuring]. theObject->Object_Coord.coord.m[0][0]= theObject->Object_Coord.coord.m[1][1]= theObject->Object_Coord.coord.m[2][2]=ONE; theObject->Object_Coord.coord.m[0][1]= theObject->Object_Coord.coord.m[0][2]= theObject->Object_Coord.coord.m[1][0]= theObject->Object_Coord.coord.m[1][2]= theObject->Object_Coord.coord.m[2][0]= theObject->Object_Coord.coord.m[2][1]=0; //Rotate Object. Explicit ordering of rotations Y,X,Z. (must be better way?) matTemp = GsIDMATRIX; RotMatrix(&Rotation1, &matTemp); MulMatrix0(&theObject->Object_Coord.coord, &matTemp, &theObject->Object_Coord.coord); matTemp = GsIDMATRIX; RotMatrix(&Rotation2, &matTemp); MulMatrix0(&theObject->Object_Coord.coord, &matTemp, &theObject->Object_Coord.coord); matTemp = GsIDMATRIX; RotMatrix(&Rotation3, &matTemp); MulMatrix0(&theObject->Object_Coord.coord, &matTemp, &theObject->Object_Coord.coord); // PHYSICS STUFF // Apply Speed Constraints if(theObject->Acceleration > theObject->MaxSpeed) theObject->Acceleration = theObject->MaxSpeed; else if(theObject->Acceleration < -theObject->MaxSpeed>>1) theObject->Acceleration = -theObject->MaxSpeed>>1; //Apply Friction if(theObject->PedalDown==FALSE) { if(theObject->Acceleration > 0) if(theObject->Acceleration > getFriction()) theObject->Acceleration -= getFriction(); else theObject->Acceleration =0; else if(theObject->Acceleration < 0) if(theObject->Acceleration < -getFriction()) theObject->Acceleration += getFriction(); else theObject->Acceleration =0; } // Apply Gravity - (Gravity is applied to acceleration because it contributes // to friction when on a slope, which is what I want to model). // The slope is the difference between the front height and back. theObject->Acceleration += ((HeightToBack - HeightToFront)>>9); FntPrint("difference = %d",(int)(HeightToBack - HeightToFront)>>9); FntPrint("\nAcc = %d \n",(int)theObject->Acceleration); // temp velocity calc if(theObject->Acceleration != 0) { theObject->Velocity.vx = -((theObject->Direction.vx>>4) * theObject->Acceleration); theObject->Velocity.vy = -((theObject->Direction.vy>>4) * theObject->Acceleration); theObject->Velocity.vz = -((theObject->Direction.vz>>4) * theObject->Acceleration); } else { theObject->Velocity.vx = theObject->Velocity.vy = theObject->Velocity.vz = 0; } // Apply previous calculations to object !!!! ApplyVelocity(theObject); // make sure object is redrawn. theObject->Object_Coord.flg = 0; } //////////////////////////////////////////////////////////////////////// // **** M A I N **** //------------------ int main() { u_long GameRunning = TRUE; // FLAG Has game been exited u_long GameState = TITLE;// FLAG Which part of game are we in. (e.g title) // 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(-150, -110, 300, 220, 0, 512); // initialise the joypad PadInit(); // initialise graphics Initialise3DGraphics(); LoadTextures(); InitialiseLights(); InitialiseModel(&buggy,0,-500,0,(u_long *)BUGGY1_TMD); InitialiseFollowView(&ViewPoint,250, 0, 0, -2000, -4000, 0, 0, 0,&buggy.Object_Coord); // setupMaps SetDemoMap(); // setup demo map SetCurrentMap(&map1); // make pointers point to demo map SetupMap(); // Main game loop while(GameRunning == TRUE) { // Main title screen loop while(GameState == TITLE) { GameState = ProcessUserInputTitle(); UpdateWorldTitle(); RenderWorldTitle(); } // Actual game loop while(GameState == GAME) { GameState = ProcessUserInputGame(); UpdateWorldGame(); UpdateFollowView(&ViewPoint); RenderWorldGame(); } // set Quit state. if(GameState == QUIT) { GameRunning = FALSE; } } // clean up DestroyMap(&map1); ResetGraph(3); return 0; }