home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-14 | 34.8 KB | 1,097 lines |
- /**********************************************************************
- *
- * File : ratrophy.c
- *
- * Abstract : The rat and trophy bit handler. This module handles
- * the movement and display of the rats and the trophy that
- * appears once all the rats are destroyed.
- *
- **********************************************************************
- *
- * This file is a product of Criterion Software Ltd.
- *
- * This file is provided as is with no warranties of any kind and is
- * provided without any obligation on Criterion Software Ltd. or
- * Canon Inc. to assist in its use or modification.
- *
- * Criterion Software Ltd. will not, under any
- * circumstances, be liable for any lost revenue or other damages arising
- * from the use of this file.
- *
- * Copyright (c) 1995 Criterion Software Ltd.
- * All Rights Reserved.
- *
- * RenderWare is a trademark of Canon Inc.
- *
- ************************************************************************/
-
- /*--- Include Files ---*/
-
- #include "global.h" /* Application general includes */
-
- #define TARGET_HITFORCE 0.3 /* Objects that are hit move at this velocity */
-
- #define RAT_CREATE_TIME 200 /* No of frames before a new rat is created */
-
- /* Rat State definitions: These are the different ways that a rat can move */
-
- #define RAT_WAIT 1
- #define RAT_TURN_LEFT 2
- #define RAT_TURN_RIGHT 3
- #define RAT_LOOK 4
- #define RAT_FORWARD 5
-
- #define RAT_MOVE_SIZE 0.15 /* Once a rat gets this close to a wall or
- the ground it bounces */
- #define RAT_TRAP_SIZE 0.05 /* If the rat is on the ground and it gets
- this close to a wall or the kerb then
- change its behaviour */
-
- #define TROPHY_MOVE_SIZE 0.5 /* Once the trophy gets this close to a wall
- or the ground it bounces */
-
- /* The start position for the trophy when it enters the street */
-
- #define TROPHY_X 0.0
- #define TROPHY_Y 4.0
- #define TROPHY_Z 2.0
-
-
- #define RAT_START_HEIGHT 4.0 /* The height that the rats fall from */
- #define RAT_SPEED 0.02 /* The speed that rats move forward at */
- #define RAT_HITS 4 /* The number of hits that a rat can take
- before it explodes */
- #define RAT_BOUNCE (-1.0/4.0) /* Change in velocity for a rat when it
- bounces off of a wall or the ground */
- #define RAT_FRICTION (1.0/4.0) /* When a rat bounces of the ground, its
- forward momentum is damped by this amount */
-
- #define RAT_MAX_FRAMES 7 /* the number of different clumps that
- make up the rat animation */
-
- #define GROUND_TRAP 0.01 /* When a rat gets this close to the
- ground it behaves as though it is
- on the ground */
-
- /* All Rats: A single global variable of this type is defined. It holds all
- * of the rat related items that are shared across mulitple instances
- */
- typedef struct
- {
- RwClump *cpaFrames[RAT_MAX_FRAMES]; /* Rat animation clumps */
- RwClump *cpShadow; /* Rat shadow clumps */
- RwMatrix4d *mpTurnLeft; /* Matrix for a rat turning left */
- RwMatrix4d *mpTurnRight; /* Matrix for a rat turning right */
- RwClump *cpCollision; /* minimal rat used for picking */
- int nRats; /* number of rats */
- int nDeadRats; /* number of dead rats */
- int nCreateCount; /* number of frames since last rat
- was created */
- } AllRats;
-
- /* Rat: This is the basic structure for a rat. One of these is created for
- * each rat in the scene */
-
- typedef struct
- {
- Object oObj; /* see object.c for this definition */
- RwClump *cpCollision; /* collision clump for this rat */
- RwClump *cpShadow; /* Rat shadow clump */
- int nState; /* current rat motion type */
- int nCount; /* number of frames to have this motion */
- int nFrame; /* current rat animation frame */
- RwMatrix4d *mpDir; /* rat direction matrix */
- RwV3d vVel; /* Current rat velocity */
- int nHit; /* Number of times that this rat has been hit */
- } Rat;
-
- /* Trophy: The trophy is loaded at startup time but only dropped into the
- * scene once all of the rats have been destroyed. This structure stores
- * the transient trophy data.
- */
-
- typedef struct
- {
- Object oObj;
- RwClump *cpCollision; /* collision clump for the trophy */
- RwClump *cpShadow; /* shadow clump for the trophy */
- RwMatrix4d *mpDir; /* trophy direction */
- RwV3d vVel; /* Current trophy velocity */
- } Trophy;
-
- static AllRats arGRats;
- static Trophy tpGTrophy;
-
- /* Rat Functions */
-
- /************************************************************************
- *
- * Function: NumRats()
- *
- * Description: Returns the number of rats in the street
- *
- * Return Value: The number of rats
- *
- ************************************************************************/
- int NumRats(void)
- {
- return(arGRats.nRats);
- }
-
- /************************************************************************
- *
- * Function: NumDeadRats()
- *
- * Description: Returns the number of rats that have been destroyed
- *
- * Return Value: The number of dead rats
- *
- ************************************************************************/
- int NumDeadRats(void)
- {
- return(arGRats.nDeadRats);
- }
-
- /************************************************************************
- *
- * Function: RatHit()
- *
- * Description: Decrement the hit count for the rat
- *
- * Parameters: opObj - the object structure that represents the rat
- *
- * Return Value: TRUE if the rat has been destroyed, FALSE otherwise
- *
- ************************************************************************/
- int RatHit(Object *opObj)
- {
- RwV3d vPos;
- Rat *rpRat;
-
- /* Extract the Rat data from the Object */
-
- rpRat = (Rat *)opObj->pExtra;
-
- /* Make the target move as a result of the hit by determining the vector
- * from the camera to the object and moving the rat in that direction
- */
-
- /* Determine the unit vector from the camera to the rat */
- RwGetCameraPosition(cpGCamera, &vPos);
- RwSubtractVector(&(opObj->vPos), &vPos, &vPos);
- RwNormalize(&vPos);
-
- /* Make the rat move in the strike direction */
- RwScaleVector(&vPos, CREAL(TARGET_HITFORCE), &vPos);
- RwAddVector(&rpRat->vVel, &vPos, &rpRat->vVel);
-
- /* Can the rat take any more hits ?? */
- if (--(rpRat->nHit) < 0)
- return(TRUE);
- else
- return(FALSE);
- }
-
- /************************************************************************
- *
- * Function: RatGivePurpose()
- *
- * Description: Assign a random rat movement type to the rat
- *
- * Parameters: Rat - the rat to assign the behaviour to
- *
- * Return Value: None
- *
- ************************************************************************/
- static void RatGivePurpose(Rat *rpRat)
- {
- RwInt32 nRand1,nRand2;
-
- /* Generate 2 Random numbers */
-
- nRand1 = RwRandom();
- nRand2 = (nRand1>>8);
- nRand1 &= 0xff;
-
- if (nRand1 < 10)
- {
- rpRat->nState = RAT_TURN_LEFT;
- rpRat->nCount = (nRand2 & 0xf) + 15; /* stay in this state for
- 15 to 30 frames */
- }
- else if (nRand1 < 20)
- {
- rpRat->nState = RAT_TURN_RIGHT;
- rpRat->nCount = (nRand2 & 0xf) + 15; /* stay in this state for
- 15 to 30 frames */
- }
- else if (nRand1 < 40)
- {
- rpRat->nState = RAT_WAIT;
- rpRat->nCount = (nRand2 & 0x1f) + 4; /* stay in this state for
- 4 to 35 frames */
-
- }
- else
- {
- rpRat->nState = RAT_FORWARD;
- rpRat->nCount = (nRand2 & 0xf) + 10; /* stay in this state for
- 10 to 25 frames */
- }
- }
-
- /************************************************************************
- *
- * Function: RatUpdate()
- *
- * Description: Update the position of a single rat. This function
- * is called by the generic object handler on every
- * frame for each rat in the street
- *
- * Parameters: opObj - the object that defines the rat
- *
- * Return Value: None
- *
- ************************************************************************/
- static void RatUpdate(Object *opObj)
- {
- Rat *rpRat;
- RwReal nX,nY,nZ;
-
- /* Extract the rat data from the object */
-
- rpRat = (Rat *)opObj->pExtra;
-
- /* Apply the force of gravity to the rat */
-
- rpRat->vVel.y -= CREAL(GRAVITY);
-
- /* Move the rat to its new position */
-
- RwTranslateMatrix(rpRat->mpDir,
- rpRat->vVel.x, rpRat->vVel.y, rpRat->vVel.z,
- rwPOSTCONCAT);
- nX = RwGetMatrixElement(rpRat->mpDir,3,0);
- nY = RwGetMatrixElement(rpRat->mpDir,3,1);
- nZ = RwGetMatrixElement(rpRat->mpDir,3,2);
-
- /* Test for collisions with the side walls */
-
- if (rpRat->vVel.x < CREAL(0.0))
- {
- /* Moving to the left - check against left wall */
- if (rpRat->oObj.vPos.x < CREAL(LEFT_STREET + RAT_MOVE_SIZE))
- {
- /* collision - bounce */
- rpRat->vVel.x = RMul(rpRat->vVel.x, CREAL(RICOCHET));
- nX = CREAL(LEFT_STREET + RAT_MOVE_SIZE);
- RwSetMatrixElement(rpRat->mpDir, 3, 0, nX);
- }
- }
- else
- {
- /* Moving to the right - check against right wall */
- if (rpRat->oObj.vPos.x > CREAL(RIGHT_STREET - RAT_MOVE_SIZE))
- {
- rpRat->vVel.x = RMul(rpRat->vVel.x, CREAL(RICOCHET));
- nX = CREAL(RIGHT_STREET - RAT_MOVE_SIZE);
- RwSetMatrixElement(rpRat->mpDir, 3, 0, nX);
- }
- }
-
- /* Test for collisions with the end walls */
-
- if (rpRat->vVel.z < CREAL(0))
- {
- /* moving towards far wall */
- if (rpRat->oObj.vPos.z < CREAL(FAR_STREET + RAT_MOVE_SIZE))
- {
- rpRat->vVel.z = RMul(rpRat->vVel.z, CREAL(RICOCHET));
- nZ = CREAL(FAR_STREET + RAT_MOVE_SIZE);
- RwSetMatrixElement(rpRat->mpDir, 3, 2, nZ);
- }
- }
- else
- {
- /* moving towards near wall */
- if (rpRat->oObj.vPos.z > CREAL(NEAR_STREET - RAT_MOVE_SIZE))
- {
- rpRat->vVel.z = RMul(rpRat->vVel.z, CREAL(RICOCHET));
- nZ = CREAL(NEAR_STREET - RAT_MOVE_SIZE);
- RwSetMatrixElement(rpRat->mpDir,3,2,nZ);
- }
- }
-
- /* Test for collisions with the ground */
-
- if ((nX < CREAL(LEFT_KERB)) || (nX > CREAL(RIGHT_KERB)))
- {
- /* On the pavement */
-
- if (nY <= CREAL(KERB_HEIGHT))
- {
- RwTranslateMatrix(rpRat->mpDir,
- CREAL(0.0), RSub(CREAL(KERB_HEIGHT), nY), CREAL(0.0),
- rwPOSTCONCAT);
-
- #ifdef WITH_SOUND
- /* Make the sound */
-
- if (rpRat->vVel.y < CREAL(-0.05))
- {
- AllSoundsPlaySound("boink");
- }
-
- #endif /* WITH_SOUND */
-
- /* Bounce the rat !*/
-
- rpRat->vVel.y = RMul(rpRat->vVel.y, CREAL(RAT_BOUNCE));
-
- /* Take into account friction */
-
- rpRat->vVel.x = RMul(rpRat->vVel.x, CREAL(RAT_FRICTION));
- rpRat->vVel.z = RMul(rpRat->vVel.z, CREAL(RAT_FRICTION));
- nY = CREAL(KERB_HEIGHT);
- }
- }
- else
- {
- /* On the road */
-
- if (nY <= CREAL(STREET_HEIGHT))
- {
- RwTranslateMatrix(rpRat->mpDir,
- CREAL(0.0), RSub(CREAL(STREET_HEIGHT), nY), CREAL(0.0), rwPOSTCONCAT);
-
- #ifdef WITH_SOUND
- /* Make the sound */
-
- if (rpRat->vVel.y < CREAL(-0.05))
- {
- AllSoundsPlaySound("boink");
- }
-
- #endif /* SOUND */
-
- /* Bounce the rat !*/
-
- rpRat->vVel.y = RMul(rpRat->vVel.y, CREAL(RAT_BOUNCE));
-
- /* Take into account friction */
-
- rpRat->vVel.x = RMul(rpRat->vVel.x, CREAL(RAT_FRICTION));
- rpRat->vVel.z = RMul(rpRat->vVel.z, CREAL(RAT_FRICTION));
- nY = CREAL(STREET_HEIGHT);
- }
- }
- /* If on the ground make it do things */
-
- if ( (nY < CREAL(KERB_HEIGHT + GROUND_TRAP)) &&
- (rpRat->vVel.y < CREAL(GRAVITY)))
- {
- if (rpRat->nCount-- < 0)
- {
- /* previous movement completed */
- RatGivePurpose(rpRat);
- }
-
- switch (rpRat->nState)
- {
- case RAT_WAIT:
- break;
-
- case RAT_TURN_LEFT:
- RwTransformMatrix(rpRat->mpDir, arGRats.mpTurnLeft, rwPRECONCAT);
- break;
-
- case RAT_TURN_RIGHT:
- RwTransformMatrix(rpRat->mpDir, arGRats.mpTurnRight, rwPRECONCAT);
- break;
-
- case RAT_FORWARD:
- RwTranslateMatrix(rpRat->mpDir,
- CREAL(0.0), CREAL(0.0), CREAL(RAT_SPEED),
- rwPRECONCAT);
- if (!(rpRat->nCount))
- {
- /* If its the last frame then ortho normalize it */
- RwOrthoNormalizeMatrix(rpRat->mpDir,rpRat->mpDir);
- }
- rpRat->nFrame++;
-
- if (rpRat->nFrame >= RAT_MAX_FRAMES)
- {
- rpRat->nFrame = 0;
- }
- break;
-
- default:
- break;
- }
-
- /* Bound the movement of ratty */
-
- if (nY == CREAL(STREET_HEIGHT))
- {
- if (nX < CREAL(LEFT_KERB + RAT_TRAP_SIZE))
- {
- RwSetMatrixElement(rpRat->mpDir, 3, 0,
- CREAL(LEFT_KERB + RAT_TRAP_SIZE));
- RatGivePurpose(rpRat);
- }
- if (nX > CREAL(RIGHT_KERB - RAT_TRAP_SIZE))
- {
- RwSetMatrixElement(rpRat->mpDir, 3, 0,
- CREAL(RIGHT_KERB - RAT_TRAP_SIZE));
- RatGivePurpose(rpRat);
- }
- }
- else
- {
- if (nX < CREAL(LEFT_STREET + RAT_MOVE_SIZE))
- {
- RwSetMatrixElement(rpRat->mpDir, 3, 0, CREAL(LEFT_STREET + RAT_MOVE_SIZE));
- RatGivePurpose(rpRat);
- }
- if (nX > CREAL(RIGHT_STREET - RAT_MOVE_SIZE))
- {
- RwSetMatrixElement(rpRat->mpDir, 3, 0, CREAL(RIGHT_STREET - RAT_MOVE_SIZE));
- RatGivePurpose(rpRat);
- }
- }
-
- if (nZ < CREAL(FAR_STREET + RAT_MOVE_SIZE))
- {
- RwSetMatrixElement(rpRat->mpDir, 3, 2, CREAL(FAR_STREET + RAT_MOVE_SIZE));
- RatGivePurpose(rpRat);
- }
- else if (nZ > CREAL(NEAR_STREET - RAT_MOVE_SIZE))
- {
- RwSetMatrixElement(rpRat->mpDir, 3, 2, CREAL(NEAR_STREET - RAT_MOVE_SIZE));
- RatGivePurpose(rpRat);
- }
- }
- opObj->cpClump = arGRats.cpaFrames[rpRat->nFrame];
- opObj->vPos.x = RwGetMatrixElement(rpRat->mpDir,3,0);
- opObj->vPos.y = RwGetMatrixElement(rpRat->mpDir,3,1);
- opObj->vPos.z = RwGetMatrixElement(rpRat->mpDir,3,2);
-
- RwTransformClump(rpRat->cpCollision, rpRat->mpDir, rwREPLACE);
- }
-
- /************************************************************************
- *
- * Function: RatRender()
- *
- * Description: Render a single rat. This function
- * is called by the generic object handler on every
- * frame for each rat in the street
- *
- * Parameters: opObj - the object that defines the rat
- *
- * Return Value: None
- *
- ************************************************************************/
- static void RatRender(Object *opObj)
- {
- Rat *rpRat;
- RwReal nX;
-
- /* extract the Rat data from the generic object */
-
- rpRat = (Rat *)opObj->pExtra;
-
- #ifdef WITH_SHADOWS
-
- /* Render the shadow below the rat. The location of the rat on the
- * street needs to be taken into consideration to allow for the
- * different heights of the street and the kerb
- */
-
- /* Extract the location in X from the matrix */
-
- nX = RwGetMatrixElement(rpRat->mpDir, 3, 0);
-
- /* Extract the position and orientation info from the rat */
-
- RwCopyMatrix(rpRat->mpDir, RwScratchMatrix());
-
- /* Adjust the matrix to place the shadow on the street of the kerb */
-
- if ( (nX < CREAL(LEFT_KERB)) || (nX > CREAL(RIGHT_KERB)) )
- {
- RwSetMatrixElement(RwScratchMatrix(), 3, 1, CREAL(KERB_HEIGHT + SHADOW_HEIGHT));
- }
- else
- {
- RwSetMatrixElement(RwScratchMatrix(), 3, 1, CREAL(STREET_HEIGHT + SHADOW_HEIGHT));
- }
-
- /* Transform and render the shadow */
- RwTransformClump(rpRat->cpShadow, RwScratchMatrix(), rwREPLACE);
- RwRenderClump(rpRat->cpShadow);
- #endif
-
- /* Transform and Render the rat */
-
- RwTransformClump(opObj->cpClump, rpRat->mpDir, rwREPLACE);
- RwRenderClump(opObj->cpClump);
- }
-
- /************************************************************************
- *
- * Function: RatDestroy()
- *
- * Description: Destroy a single rat. This function
- * is called by the generic object handler once the
- * object has been deleted.
- *
- * Parameters: opObj - the object that defines the rat
- *
- * Return Value: None
- *
- ************************************************************************/
- static void RatDestroy(Object *opObj)
- {
- Rat *rpRat;
-
- /* extract the rat data from the generic object */
-
- rpRat = (Rat *)opObj->pExtra;
-
- /* Remove the collision object for this rat from the collision scene */
-
- RwRemoveClumpFromScene(rpRat->cpCollision);
- RwDestroyClump(rpRat->cpCollision);
-
- /* Destroy the position matrix for this rat */
-
- RwDestroyMatrix(rpRat->mpDir);
-
- /* There is one less rat in the world */
-
- arGRats.nRats--;
-
- /* Add 1 to the number of dead rats */
-
- arGRats.nDeadRats++;
-
- /* free up the rat data */
- free(rpRat);
- }
-
- /************************************************************************
- *
- * Function: RatSetup()
- *
- * Description: Create a new rat and drop it into the street
- *
- * Parameters: None
- *
- * Return Value: None
- *
- ************************************************************************/
- static void RatSetup(void)
- {
- RwReal nX, nY, nZ;
- Rat *rpRat;
-
- /* Generate a random start position for the rat */
-
- nX = RANDOM_REAL(CREAL(LEFT_STREET + 0.2), CREAL(RIGHT_STREET - 0.2));
- nY = CREAL(RAT_START_HEIGHT);
- nZ = RANDOM_REAL(CREAL(FAR_STREET + 0.2), CREAL(NEAR_STREET - 0.2));
-
- /* Create a new rat */
- rpRat = (Rat *)malloc(sizeof(Rat));
-
- /* initialise the generic bit */
- ObjectSetup(&rpRat->oObj, nX, nY, nZ, NULL);
-
- /* define the functions that the generic object handler needs to
- control the rat */
-
- rpRat->oObj.fpUpdate = RatUpdate;
- rpRat->oObj.fpRender = RatRender;
- rpRat->oObj.fpDestroy = RatDestroy;
- rpRat->oObj.pExtra = (void *)rpRat;
-
- /* We want to assign some behaviour as soon as the rat hits the ground */
- rpRat->nFrame = 0;
-
- /* Start with zero velocity. Gravity will start things moving */
- rpRat->vVel.x = CREAL(0.0);
- rpRat->vVel.y = CREAL(0.0);
- rpRat->vVel.z = CREAL(0.0);
-
- /* Give the rat some behaviour */
- RatGivePurpose(rpRat);
-
- /* Generate and initialise the transformation matrix for this rat */
- rpRat->mpDir = RwCreateMatrix();
- RwTranslateMatrix(rpRat->mpDir, nX, nY, nZ, rwREPLACE);
-
- /* Copy the generic rat collision object, transform it to the position
- and orientation of the rat and add it to the collision scene */
-
- rpRat->cpCollision = RwDuplicateClump(arGRats.cpCollision);
- RwSetClumpData(rpRat->cpCollision, &rpRat->oObj);
- RwTransformClump(rpRat->cpCollision, rpRat->mpDir, rwREPLACE);
- RwAddClumpToScene(spGTargetScene, rpRat->cpCollision);
-
- /* Set the Shadow image */
-
- rpRat->cpShadow = arGRats.cpShadow;
-
- /* Set the amount of hits it can take before being destroyed */
-
- rpRat->nHit = RAT_HITS;
-
- /* Just added a new rat so add one more to the number in the street */
-
- arGRats.nRats++;
-
- /* Add to the generic object scene management stuff */
-
- AllObjectsAddObject(&rpRat->oObj);
-
- /* Give the rat a random direction */
-
- RwRotateMatrix(RwScratchMatrix(),
- CREAL(0.0), CREAL(1.0), CREAL(0.0),
- RANDOM_REAL(CREAL(0.0), CREAL(360.0)),
- rwREPLACE );
-
- RwTransformMatrix(rpRat->mpDir, RwScratchMatrix(), rwPRECONCAT);
- }
- /************************************************************************
- *
- * Function: AllRatsDestroy()
- *
- * Description: Destroy the shared rat data.
- *
- * Parameters: None
- *
- * Return Value: None
- *
- ************************************************************************/
- void AllRatsDestroy(void)
- {
- RwDestroyClump(arGRats.cpShadow);
- RwDestroyClump(arGRats.cpCollision);
- RwDestroyClump(arGRats.cpaFrames[0]);
- RwDestroyClump(arGRats.cpaFrames[1]);
- RwDestroyClump(arGRats.cpaFrames[2]);
- RwDestroyClump(arGRats.cpaFrames[3]);
- RwDestroyClump(arGRats.cpaFrames[4]);
- RwDestroyClump(arGRats.cpaFrames[5]);
- RwDestroyClump(arGRats.cpaFrames[6]);
-
- RwDestroyMatrix(arGRats.mpTurnLeft);
- RwDestroyMatrix(arGRats.mpTurnRight);
- }
-
- /************************************************************************
- *
- * Function: AllRatsSetup()
- *
- * Description: Create the shared rat data.
- *
- * Parameters: None
- *
- * Return Value: TRUE if successful, FALSE otherwise
- *
- ************************************************************************/
- int AllRatsSetup(void)
- {
- /* start with zero rats */
-
- arGRats.nRats = 0;
-
- /* Read all of the clumps needed for the rats*/
- if (!(arGRats.cpCollision = DoRwReadShape("collisio.rwx")) ||
- #ifdef WITH_SHADOWS
- !(arGRats.cpShadow = DoRwReadShape("ratshad.rwx")) ||
- #endif
- /* Get the rat animation frames */
-
- !(arGRats.cpaFrames[0] = DoRwReadShape("rat1.rwx")) ||
- !(arGRats.cpaFrames[2] = DoRwReadShape("rat3.rwx")) ||
- !(arGRats.cpaFrames[4] = DoRwReadShape("rat5.rwx")) ||
- !(arGRats.cpaFrames[6] = DoRwReadShape("rat7.rwx")) ||
- !(arGRats.cpaFrames[1] = DoRwReadShape("rat2.rwx")) ||
- !(arGRats.cpaFrames[3] = DoRwReadShape("rat4.rwx")) ||
- !(arGRats.cpaFrames[5] = DoRwReadShape("rat6.rwx")))
- {
- /* Failed to read something - error */
- return FALSE;
- }
-
- /* Create The matrices used to turn the rats to the left and right */
-
- if (!(arGRats.mpTurnLeft = RwCreateMatrix()) ||
- !(arGRats.mpTurnRight = RwCreateMatrix()))
- {
- /* failed to create the matrices - error */
- return FALSE;
- }
-
- /* And initialise these matrices */
- RwRotateMatrix(arGRats.mpTurnLeft,CREAL(0.0),CREAL(1.0),CREAL(0.0),
- CREAL(3.0),rwREPLACE);
-
- RwRotateMatrix(arGRats.mpTurnRight,CREAL(0.0),CREAL(1.0),CREAL(0.0),
- CREAL(-3.0),rwREPLACE);
-
-
- /* Create the initial amount of rats. Use half of the maximum */
-
- arGRats.nCreateCount=0;
-
- while (arGRats.nRats < RAT_MAXIMUM/2)
- {
- RatSetup();
- }
- return TRUE;
- }
-
- /************************************************************************
- *
- * Function: AllRatsRelease()
- *
- * Description: Control the steady flow of rats into the street
- *
- * Parameters: None. Uses global rat data
- *
- * Return Value: None
- *
- ************************************************************************/
- void AllRatsRelease(void)
- {
- /* Increment the creation timer */
- arGRats.nCreateCount++;
-
- if ( (arGRats.nCreateCount >= RAT_CREATE_TIME) &&
- (arGRats.nRats) )
- {
- /* It's time to create a rat */
- arGRats.nCreateCount = 0;
-
- if (arGRats.nRats < RAT_MAXIMUM)
- {
- /* We haven't reached the limit yet. Create anothe one */
- RatSetup();
- }
- }
- }
-
- /* Trophy Functions */
-
- /************************************************************************
- *
- * Function: TrophyHit()
- *
- * Description: Move the trophy in response to a hit
- *
- * Parameters: None. Uses the global trophy data object
- *
- * Return Value: None
- *
- ************************************************************************/
- void TrophyHit(void)
- {
- RwV3d vPos;
-
- /* Use the vector from the camera to the trophy to determine the strike
- direction */
-
- RwGetCameraPosition(cpGCamera, &vPos);
- RwSubtractVector(&(tpGTrophy.oObj.vPos), &vPos, &vPos);
- RwNormalize(&vPos);
-
- /* Move the trophy in the direction of the strike */
- RwScaleVector(&vPos, CREAL(TARGET_HITFORCE), &vPos);
- RwAddVector(&tpGTrophy.vVel, &vPos, &tpGTrophy.vVel);
- }
-
- /************************************************************************
- *
- * Function: TrophyUpdate()
- *
- * Description: This function is called every frame to
- * update the position of the trophy,
- *
- * Parameters: opObj - the generic object
- *
- * Return Value: None
- *
- ************************************************************************/
- static void TrophyUpdate(Object *opObj)
- {
- RwReal nX,nY,nZ;
-
- /* Apply the force of gravity */
-
- tpGTrophy.vVel.y -= CREAL(GRAVITY);
-
- /* Preserve the momentum of the trophy */
-
- RwTranslateMatrix(tpGTrophy.mpDir,
- tpGTrophy.vVel.x, tpGTrophy.vVel.y, tpGTrophy.vVel.z,
- rwPOSTCONCAT);
- nX = RwGetMatrixElement(tpGTrophy.mpDir,3,0);
- nY = RwGetMatrixElement(tpGTrophy.mpDir,3,1);
- nZ = RwGetMatrixElement(tpGTrophy.mpDir,3,2);
-
- /* Test for collisions with the side walls */
-
- if (tpGTrophy.vVel.x < CREAL(0.0))
- {
- /* Moving to the left - check against left wall */
- if (nX < CREAL(LEFT_STREET + RAT_MOVE_SIZE))
- {
- /* collision - bounce */
- tpGTrophy.vVel.x = RMul(tpGTrophy.vVel.x, CREAL(RICOCHET));
- nX = CREAL(LEFT_STREET + RAT_MOVE_SIZE);
- }
- }
- else
- {
- /* Moving to the right - check against right wall */
- if (nX > CREAL(RIGHT_STREET - RAT_MOVE_SIZE))
- {
- tpGTrophy.vVel.x = RMul(tpGTrophy.vVel.x, CREAL(RICOCHET));
- nX = CREAL(RIGHT_STREET - RAT_MOVE_SIZE);
- }
- }
-
- /* Test for collisions with the end walls */
-
- if (tpGTrophy.vVel.z < CREAL(0))
- {
- /* moving towards far wall */
- if (nZ < CREAL(FAR_STREET + RAT_MOVE_SIZE))
- {
- tpGTrophy.vVel.z = RMul(tpGTrophy.vVel.z, CREAL(RICOCHET));
- nZ = CREAL(FAR_STREET + RAT_MOVE_SIZE);
- }
- }
- else
- {
- /* moving towards near wall */
- if (nZ > CREAL(NEAR_STREET - RAT_MOVE_SIZE))
- {
- tpGTrophy.vVel.z = RMul(tpGTrophy.vVel.z, CREAL(RICOCHET));
- nZ = CREAL(NEAR_STREET - RAT_MOVE_SIZE);
- }
- }
-
- /* Test for collisions with the ground */
-
- if ((nX < CREAL(LEFT_KERB)) || (nX > CREAL(RIGHT_KERB)))
- {
- /* On the pavement */
-
- if (nY <= CREAL(KERB_HEIGHT))
- {
- RwTranslateMatrix(tpGTrophy.mpDir,
- CREAL(0.0), CREAL(KERB_HEIGHT), CREAL(0.0),
- rwPOSTCONCAT);
- #ifdef WITH_SOUND
- /* Make the sound */
-
- if (tpGTrophy.vVel.y < CREAL(-0.05))
- {
- AllSoundsPlaySound("boink");
- }
- #endif /* SOUND */
-
- /* Bounce the trophy. Use the rat friction and bounce parameters */
-
- tpGTrophy.vVel.y = RMul(tpGTrophy.vVel.y, CREAL(RAT_BOUNCE));
-
- /* Take into account friction */
-
- tpGTrophy.vVel.x = RMul(tpGTrophy.vVel.x, CREAL(RAT_FRICTION));
- tpGTrophy.vVel.z = RMul(tpGTrophy.vVel.z, CREAL(RAT_FRICTION));
- nY = CREAL(KERB_HEIGHT);
- }
- }
- else
- {
- /* On the road */
-
- if (nY <= CREAL(STREET_HEIGHT))
- {
- RwTranslateMatrix(tpGTrophy.mpDir,
- CREAL(0.0), CREAL(STREET_HEIGHT) - nY, CREAL(0.0), rwPOSTCONCAT);
-
- #ifdef WITH_SOUND
- /* Make the sound */
-
- if (tpGTrophy.vVel.y < CREAL(-0.05))
- {
- AllSoundsPlaySound("boink");
- }
- #endif /* SOUND */
-
- /* Bounce the trophy !*/
-
- tpGTrophy.vVel.y = RMul(tpGTrophy.vVel.y, CREAL(RAT_BOUNCE));
-
- /* Take into account friction */
-
- tpGTrophy.vVel.x = RMul(tpGTrophy.vVel.x, CREAL(RAT_FRICTION));
- tpGTrophy.vVel.z = RMul(tpGTrophy.vVel.z, CREAL(RAT_FRICTION));
- nY = CREAL(STREET_HEIGHT);
- }
- }
- /* Move the trophy to its new position */
- RwSetMatrixElement(tpGTrophy.mpDir,3,0, nX);
- RwSetMatrixElement(tpGTrophy.mpDir,3,1, nY);
- RwSetMatrixElement(tpGTrophy.mpDir,3,2, nZ);
-
- opObj->vPos.x = nX;
- opObj->vPos.y = nY;
- opObj->vPos.z = nZ;
-
- RwTransformClump(tpGTrophy.cpCollision, tpGTrophy.mpDir, rwREPLACE);
- }
-
- /************************************************************************
- *
- * Function: TrophyRender()
- *
- * Description: This function is called every frame to
- * render the position of the trophy,
- *
- * Parameters: opObj - generic object data
- *
- * Return Value: None
- *
- ************************************************************************/
- void TrophyRender(Object *opObj)
- {
- RwReal nX;
-
- #ifdef WITH_SHADOWS
- /* Render the shadow below the trophy. The location of the trophy on the
- * street needs to be taken into consideration to allow for the
- * different heights of the street and the kerb
- */
-
- /* Extract the location in X from the matrix */
-
- nX = RwGetMatrixElement(tpGTrophy.mpDir, 3, 0);
-
- /* Extract the position and orientation info from the trophy */
-
- RwCopyMatrix(tpGTrophy.mpDir, RwScratchMatrix());
-
- /* Adjust the matrix to place the shadow on the street of the kerb */
-
- if ( (nX < CREAL(LEFT_KERB)) || (nX > CREAL(RIGHT_KERB)) )
- {
- RwSetMatrixElement(RwScratchMatrix(), 3, 1, CREAL(KERB_HEIGHT + SHADOW_HEIGHT));
- }
- else
- {
- RwSetMatrixElement(RwScratchMatrix(), 3, 1, CREAL(STREET_HEIGHT + SHADOW_HEIGHT));
- }
-
- /* Position and Render the shadow */
-
- RwTransformClump(tpGTrophy.cpShadow, RwScratchMatrix(), rwREPLACE);
- RwRenderClump(tpGTrophy.cpShadow);
- #endif
-
- /* Render the trophy */
- RwTransformClump(opObj->cpClump, tpGTrophy.mpDir, rwREPLACE);
- RwRenderClump(opObj->cpClump);
- }
-
- /************************************************************************
- *
- * Function: TrophyEnable()
- *
- * Description: Enable the trophy. Note that all of the trophy
- * data was initialised at load time so all we need
- * top do is drop it into the street .
- *
- * Parameters: None. Uses global trophy data object
- *
- * Return Value: None
- *
- ************************************************************************/
- void TrophyEnable(void)
- {
- AllObjectsAddObject(&tpGTrophy.oObj);
- }
-
- /************************************************************************
- *
- * Function: TrophySetup()
- *
- * Description: Create and initialise the trophy
- *
- * Parameters: None. Uses global trophy data object
- *
- * Return Value: None
- *
- ************************************************************************/
- int TrophySetup(void)
- {
- /* Initialise the generic object bit */
-
- ObjectSetup(&tpGTrophy.oObj, CREAL(TROPHY_X), CREAL(TROPHY_Y), CREAL(TROPHY_Z), NULL);
-
- /* Define the functions that the generic handler will call to update
- and render the trophy */
-
- tpGTrophy.oObj.fpUpdate = TrophyUpdate;
- tpGTrophy.oObj.fpRender = TrophyRender;
-
- /* Don't define a destroy here since the trophy is only destroyed when
- we exit from cyberstreet */
-
- tpGTrophy.oObj.pExtra = (void *)&tpGTrophy;
-
- /* Trophy starts with zero velocity but gravity soon changes that */
- tpGTrophy.vVel.x = CREAL(0.0);
- tpGTrophy.vVel.y = CREAL(0.0);
- tpGTrophy.vVel.z = CREAL(0.0);
-
- /* Create the position matrix for the trophy */
- if (tpGTrophy.mpDir = RwCreateMatrix())
- {
- /* Initialise the trophy's position */
- RwTranslateMatrix(tpGTrophy.mpDir, CREAL(TROPHY_X), CREAL(TROPHY_Y), CREAL(TROPHY_Z), rwREPLACE);
-
- /* Read the trophy script file */
- if (tpGTrophy.oObj.cpClump = DoRwReadShape("trophy.rwx"))
- {
- /* Create the collision data for teh trophy. Use the entire
- trophy for the collision */
- if (tpGTrophy.cpCollision = RwDuplicateClump(tpGTrophy.oObj.cpClump))
- {
- /* Initialise the collision data and add it to the
- collision scene */
- RwSetClumpData(tpGTrophy.cpCollision, &tpGTrophy.oObj);
- RwTransformClump(tpGTrophy.cpCollision, tpGTrophy.mpDir, rwREPLACE);
- RwAddClumpToScene(spGTargetScene, tpGTrophy.cpCollision);
- /* Read the shadow script file */
- if (tpGTrophy.cpShadow = DoRwReadShape("trophys.rwx"))
- {
- return(TRUE);
- }
- RwDestroyClump(tpGTrophy.cpCollision);
- }
- RwDestroyClump(tpGTrophy.oObj.cpClump);
- }
- RwDestroyMatrix(tpGTrophy.mpDir);
- }
- return(FALSE);
- }
-
-