1 line
15 KiB
C
Executable File
1 line
15 KiB
C
Executable File
//============================================================
|
||
//============================================================
|
||
//== ==
|
||
//== Game Dynamics Routines ==
|
||
//== ==
|
||
//============================================================
|
||
//============================================================
|
||
|
||
|
||
//======================================================== Includes
|
||
|
||
#include "Globals.h"
|
||
#include "UnivUtilities.h"
|
||
#include "Dynamics.h"
|
||
#include "SoundUtils.h"
|
||
#include "Render.h"
|
||
#include "Ball.h"
|
||
|
||
|
||
//======================================================== Functions
|
||
//======================================================== DoPersonBallMerged
|
||
|
||
void DoPersonBallMerged (playerType *who)
|
||
|
||
{
|
||
register long xMomentum, zMomentum;
|
||
short strategum;
|
||
|
||
PlaySoundSMS(kBallPickUpSound);
|
||
// calc. components of momentum
|
||
xMomentum = (who->xVel * kPersonMass) + (theBall.xVel * kBallMass);
|
||
zMomentum = (who->zVel * kPersonMass) + (theBall.zVel * kBallMass);
|
||
// momentum / mass = velocity
|
||
who->xVel = xMomentum / kPersonBallMass;
|
||
who->zVel = zMomentum / kPersonBallMass;
|
||
|
||
if ((who->persona == kHumanPlayer) || (who->persona == kNetHuman))
|
||
{
|
||
who->mouseWasLetUp = FALSE;
|
||
}
|
||
else
|
||
{
|
||
if (who->persona == kMisterEaze)
|
||
{
|
||
who->strategy = (short)RandomCoin();
|
||
}
|
||
else if (who->persona == kMissTeak)
|
||
{
|
||
strategum = RandomInt(100);
|
||
if (strategum < who->teaksThresh)
|
||
who->strategy = kRunDiagonal;
|
||
else
|
||
who->strategy = kRunCircle;
|
||
}
|
||
}
|
||
|
||
theBall.eraseTheBall = TRUE;
|
||
drawThisFrame = TRUE;
|
||
who->posture = kCarrying;
|
||
theBall.mode = kBallHeld;
|
||
if (who->selector == kPlayerSelector)
|
||
{
|
||
whosGotBall = kPlayerHasBall;
|
||
theBall.modifier = kPlayerHolding;
|
||
theOpponent.loopsBallHeld = 0; // zero out the other's timer
|
||
if (thePlayer.loopsBallHeld == 0) // ???
|
||
thePlayer.loopsBallHeld = kLoopLimitOnHeldBall;
|
||
}
|
||
else
|
||
{
|
||
whosGotBall = kOpponentHasBall;
|
||
theBall.modifier = kOpponentHolding;
|
||
thePlayer.loopsBallHeld = 0;
|
||
if (theOpponent.loopsBallHeld == 0)
|
||
theOpponent.loopsBallHeld = kLoopLimitOnHeldBall;
|
||
}
|
||
|
||
UpdateBallTimers(&thePlayer);
|
||
UpdateBallTimers(&theOpponent);
|
||
UpdateArrows();
|
||
}
|
||
|
||
|
||
//======================================================== DoPersonBallParted
|
||
|
||
void DoPersonBallParted (playerType *who)
|
||
|
||
{
|
||
#define kBallDiskDistance 1216
|
||
#define kOffsetMultiplier 2
|
||
short deltaPX, deltaPZ;
|
||
|
||
PlaySoundSMS(kBallDropSound);
|
||
|
||
deltaPX = boardForceTable[who->direction][kXComponent] * kPersonImpulse;
|
||
deltaPZ = boardForceTable[who->direction][kZComponent] * kPersonImpulse;
|
||
|
||
theBall.xVel = who->xVel + (deltaPX / kBallMass); // momentum => velocity
|
||
theBall.zVel = who->zVel + (deltaPZ / kBallMass); // x & z components
|
||
theBall.xPos = who->xPos + (deltaPX * kOffsetMultiplier); // get ball clear<61>
|
||
theBall.zPos = who->zPos + (deltaPZ * kOffsetMultiplier); // of disk.
|
||
|
||
BallRectFromPosition();
|
||
|
||
who->xVel -= deltaPX / kPersonMass;
|
||
who->zVel -= deltaPZ / kPersonMass;
|
||
|
||
who->posture = kCrouching;
|
||
theBall.mode = kBallRolling;
|
||
whosGotBall = kBallRollsFreely;
|
||
|
||
if (who->selector == kPlayerSelector)
|
||
{
|
||
theBall.modifier = kPlayerLastHeld;
|
||
}
|
||
else
|
||
{
|
||
theBall.modifier = kOpponentLastHeld;
|
||
}
|
||
|
||
if (thePlayer.persona == kMissTeak)
|
||
{
|
||
oldDistSquared = ((long)(thePlayer.xPos) * (long)(thePlayer.xPos)) +
|
||
((long)(thePlayer.zPos) * (long)(thePlayer.zPos));
|
||
}
|
||
else if (theOpponent.persona == kMissTeak)
|
||
{
|
||
oldDistSquared = ((long)(theOpponent.xPos) * (long)(theOpponent.xPos)) +
|
||
((long)(theOpponent.zPos) * (long)(theOpponent.zPos));
|
||
}
|
||
|
||
if ((who->persona == kHumanPlayer) || (who->persona == kNetHuman))
|
||
who->mouseWasLetUp = FALSE;
|
||
|
||
UpdateArrows();
|
||
}
|
||
|
||
|
||
//======================================================== DoPersonBallCollided
|
||
|
||
void DoPersonBallCollided (playerType *who)
|
||
|
||
{
|
||
#define kPBLimitScale 512L // 1024 occ. probs, 2048 more probs
|
||
short original2XVel, original2ZVel;
|
||
long distX, distZ;
|
||
long new1XVel, new1ZVel, new2XVel, new2ZVel;
|
||
long distSquared, scalar1, scalar2;
|
||
|
||
who->xPos -= (who->xVel / kVelocitySensitive);
|
||
who->zPos -= (who->zVel / kVelocitySensitive);
|
||
|
||
theBall.xVel -= theBall.xVel / kPBEnergyAbsorbed;
|
||
theBall.zVel -= theBall.zVel / kPBEnergyAbsorbed;
|
||
who->xVel -= who->xVel / kPBEnergyAbsorbed;
|
||
who->zVel -= who->zVel / kPBEnergyAbsorbed;
|
||
|
||
theBall.xVel /= kPersonSmallMass;
|
||
theBall.zVel /= kPersonSmallMass;
|
||
who->xVel /= kBallMass;
|
||
who->zVel /= kBallMass;
|
||
|
||
original2XVel = who->xVel;
|
||
original2ZVel = who->zVel;;
|
||
|
||
theBall.xVel -= original2XVel;
|
||
theBall.zVel -= original2ZVel;
|
||
who->xVel = 0;
|
||
who->zVel = 0;
|
||
|
||
distX = (long)who->xPos - (long)theBall.xPos;
|
||
distZ = (long)who->zPos - (long)theBall.zPos;
|
||
|
||
distSquared = ((distX * distX) + (distZ * distZ)) / kPBLimitScale;
|
||
scalar1 = (((long)-theBall.xVel * distZ) + ((long)theBall.zVel * distX)) / kPBLimitScale;
|
||
scalar2 = (((long)theBall.xVel * distX) + ((long)theBall.zVel * distZ)) / kPBLimitScale;
|
||
|
||
if (distSquared != 0)
|
||
{
|
||
new1XVel = -scalar1 * distZ / distSquared;
|
||
new1ZVel = scalar1 * distX / distSquared;
|
||
new2XVel = scalar2 * distX / distSquared;
|
||
new2ZVel = scalar2 * distZ / distSquared;
|
||
}
|
||
|
||
if (theBall.justHitWall == 0)
|
||
{
|
||
theBall.xVel = (short)new1XVel + original2XVel;
|
||
theBall.zVel = (short)new1ZVel + original2ZVel;
|
||
}
|
||
|
||
who->xVel = (short)new2XVel + original2XVel;
|
||
who->zVel = (short)new2ZVel + original2ZVel;
|
||
|
||
theBall.xVel *= kPersonSmallMass;
|
||
theBall.zVel *= kPersonSmallMass;
|
||
who->xVel *= kBallMass;
|
||
who->zVel *= kBallMass;
|
||
}
|
||
|
||
|
||
//======================================================== DoPersonPersonCollided
|
||
|
||
void DoPersonPersonCollided (void)
|
||
|
||
{
|
||
#define kLimitScale 1024L
|
||
short original2XVel, original2ZVel;
|
||
long distX, distZ;
|
||
long new1XVel, new1ZVel, new2XVel, new2ZVel;
|
||
long distSquared, scalar1, scalar2;
|
||
|
||
PlaySoundSMS(kClashSound);
|
||
thePlayer.justHitOpponent = kLoopsImpactless;
|
||
theOpponent.justHitOpponent = kLoopsImpactless;
|
||
|
||
thePlayer.justHitWall = 0;
|
||
theOpponent.justHitWall = 0;
|
||
|
||
thePlayer.xVel -= thePlayer.xVel / kEnergyAbsorbed;
|
||
thePlayer.zVel -= thePlayer.zVel / kEnergyAbsorbed;
|
||
theOpponent.xVel -= theOpponent.xVel / kEnergyAbsorbed;
|
||
theOpponent.zVel -= theOpponent.zVel / kEnergyAbsorbed;
|
||
|
||
original2XVel = theOpponent.xVel;
|
||
original2ZVel = theOpponent.zVel;;
|
||
|
||
thePlayer.xVel -= original2XVel;
|
||
thePlayer.zVel -= original2ZVel;
|
||
theOpponent.xVel = 0;
|
||
theOpponent.zVel = 0;
|
||
|
||
distX = (long)theOpponent.xPos - (long)thePlayer.xPos;
|
||
distZ = (long)theOpponent.zPos - (long)thePlayer.zPos;
|
||
|
||
distSquared = ((distX * distX) + (distZ * distZ)) / kLimitScale;
|
||
scalar1 = (((long)-thePlayer.xVel * distZ) + ((long)thePlayer.zVel * distX)) / kLimitScale;
|
||
scalar2 = (((long)thePlayer.xVel * distX) + ((long)thePlayer.zVel * distZ)) / kLimitScale;
|
||
|
||
if (distSquared != 0)
|
||
{
|
||
new1XVel = -scalar1 * distZ / distSquared;
|
||
new1ZVel = scalar1 * distX / distSquared;
|
||
new2XVel = scalar2 * distX / distSquared;
|
||
new2ZVel = scalar2 * distZ / distSquared;
|
||
}
|
||
|
||
thePlayer.xVel = (short)new1XVel + original2XVel;
|
||
thePlayer.zVel = (short)new1ZVel + original2ZVel;
|
||
theOpponent.xVel = (short)new2XVel + original2XVel;
|
||
theOpponent.zVel = (short)new2ZVel + original2ZVel;
|
||
}
|
||
|
||
|
||
//======================================================== CheckPersonBallCollision
|
||
|
||
void CheckPersonBallCollision (playerType *who)
|
||
|
||
{
|
||
#define kSqrImpactDistancePB 1478656L // r. of ball = 416, r. disk = 800
|
||
long sqrXDistance, sqrDistance; // Add these & square the result.
|
||
|
||
if ((who->mode != kInArena) || (theBall.mode != kBallRolling) ||
|
||
(who->justHitBall != 0))
|
||
{
|
||
return;
|
||
}
|
||
|
||
sqrXDistance = ((long)theBall.xPos - who->xPos) *
|
||
((long)theBall.xPos - who->xPos);
|
||
|
||
if (sqrXDistance < kSqrImpactDistancePB) // check x 1st (one mult. only)
|
||
{
|
||
sqrDistance = sqrXDistance + ((long)theBall.zPos - who->zPos) *
|
||
((long)theBall.zPos - who->zPos);
|
||
|
||
if (sqrDistance < kSqrImpactDistancePB)
|
||
{
|
||
if ((who->posture == kCrouching) && (who->mouseWasLetUp))
|
||
{
|
||
DoPersonBallMerged(who);
|
||
}
|
||
else
|
||
{
|
||
PlaySoundSMS(kClashSound);
|
||
|
||
DoPersonBallCollided(who);
|
||
who->justHitBall = kLoopsImpactless;
|
||
CheckUpOnBall();
|
||
|
||
if (who->selector == kPlayerSelector)
|
||
{
|
||
theBall.modifier = kPlayerLastHeld;
|
||
}
|
||
else
|
||
{
|
||
theBall.modifier = kOpponentLastHeld;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//======================================================== CheckPersonPersonCollision
|
||
|
||
void CheckPersonPersonCollision (void)
|
||
|
||
{
|
||
#define kSqrImpactDistancePO 2560000L // 2 * r. disk = 800
|
||
long sqrXDistance, sqrDistance; // Add these & square the result.
|
||
|
||
if ((thePlayer.mode != kInArena) || (theOpponent.mode != kInArena) ||
|
||
(thePlayer.justHitOpponent != 0))
|
||
{
|
||
return;
|
||
}
|
||
|
||
sqrXDistance = ((long)theOpponent.xPos - thePlayer.xPos) *
|
||
((long)theOpponent.xPos - thePlayer.xPos);
|
||
|
||
if (sqrXDistance < kSqrImpactDistancePO) // check x first (one multiply only)
|
||
{
|
||
sqrDistance = sqrXDistance + ((long)theOpponent.zPos - thePlayer.zPos) *
|
||
((long)theOpponent.zPos - thePlayer.zPos);
|
||
|
||
if (sqrDistance < kSqrImpactDistancePO)
|
||
{
|
||
DoPersonPersonCollided();
|
||
|
||
do
|
||
{
|
||
thePlayer.xPos += (thePlayer.xVel / kVelocitySensitive);
|
||
thePlayer.zPos += (thePlayer.zVel / kVelocitySensitive);
|
||
theOpponent.xPos += (theOpponent.xVel / kVelocitySensitive);
|
||
theOpponent.zPos += (theOpponent.zVel / kVelocitySensitive);
|
||
|
||
sqrXDistance = ((long)theOpponent.xPos - thePlayer.xPos) *
|
||
((long)theOpponent.xPos - thePlayer.xPos);
|
||
sqrDistance = sqrXDistance + ((long)theOpponent.zPos - thePlayer.zPos) *
|
||
((long)theOpponent.zPos - thePlayer.zPos);
|
||
|
||
} while (sqrDistance < kSqrImpactDistancePO);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//======================================================== GetPlaceOnArena
|
||
|
||
short GetPlaceOnArena (short xPos, short zPos)
|
||
|
||
{
|
||
register short indexX, indexZ;
|
||
short signX, signZ;
|
||
short forceX, forceZ;
|
||
|
||
indexX = xPos;
|
||
if (indexX < 0)
|
||
{
|
||
indexX = -indexX;
|
||
signX = -1;
|
||
}
|
||
else
|
||
{
|
||
signX = 1;
|
||
}
|
||
indexX /= 512;
|
||
|
||
indexZ = zPos;
|
||
if (indexZ < 0)
|
||
{
|
||
indexZ = -indexZ;
|
||
signZ = -1;
|
||
}
|
||
else
|
||
{
|
||
signZ = 1;
|
||
}
|
||
indexZ /= 512;
|
||
|
||
if (xPos < 0)
|
||
{
|
||
switch (leftGoalLeague)
|
||
{
|
||
case kLittleLeague:
|
||
forceX = *(littleForceTable + indexX * 82 + indexZ * 2 + kXComponent);
|
||
break;
|
||
case kJuniorVarsity:
|
||
forceX = *(juniorForceTable + indexX * 82 + indexZ * 2 + kXComponent);
|
||
break;
|
||
case kVarsity:
|
||
forceX = *(varsityForceTable + indexX * 82 + indexZ * 2 + kXComponent);
|
||
break;
|
||
case kMinorLeague:
|
||
forceX = *(minorForceTable + indexX * 82 + indexZ * 2 + kXComponent);
|
||
break;
|
||
case kProfessional:
|
||
forceX = *(proForceTable + indexX * 82 + indexZ * 2 + kXComponent);
|
||
break;
|
||
default:
|
||
forceX = 0;
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
switch (rightGoalLeague)
|
||
{
|
||
case kLittleLeague:
|
||
forceX = *(littleForceTable + indexX * 82 + indexZ * 2 + kXComponent);
|
||
break;
|
||
case kJuniorVarsity:
|
||
forceX = *(juniorForceTable + indexX * 82 + indexZ * 2 + kXComponent);
|
||
break;
|
||
case kVarsity:
|
||
forceX = *(varsityForceTable + indexX * 82 + indexZ * 2 + kXComponent);
|
||
break;
|
||
case kMinorLeague:
|
||
forceX = *(minorForceTable + indexX * 82 + indexZ * 2 + kXComponent);
|
||
break;
|
||
case kProfessional:
|
||
forceX = *(proForceTable + indexX * 82 + indexZ * 2 + kXComponent);
|
||
break;
|
||
default:
|
||
forceX = 0;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return (forceX);
|
||
}
|
||
|
||
|
||
//======================================================== HandlePersonWallCollision
|
||
|
||
void HandlePersonWallCollision (playerType *who)
|
||
|
||
{
|
||
short tempVel, wheresIt;
|
||
|
||
if (who->justHitWall != 0)
|
||
{
|
||
who->flag = kIsNormal;
|
||
return;
|
||
}
|
||
|
||
if (who->xPos < 0)
|
||
{
|
||
if (who->xVel > who->zVel)
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
if (-who->xVel > who->zVel)
|
||
return;
|
||
}
|
||
|
||
PlaySoundSMS(kRicochetSound);
|
||
who->flag = kIsRebounding;
|
||
who->justHitWall = kLoopsImpactless;
|
||
|
||
who->xPos -= (who->xVel / kVelocitySensitive);
|
||
who->zPos -= (who->zVel / kVelocitySensitive);
|
||
|
||
if (who->xPos < 0)
|
||
{
|
||
tempVel = who->xVel;
|
||
who->xVel = who->zVel;
|
||
who->zVel = tempVel;
|
||
}
|
||
else
|
||
{
|
||
tempVel = who->xVel;
|
||
who->xVel = -who->zVel;
|
||
who->zVel = -tempVel;
|
||
}
|
||
|
||
wheresIt = GetPlaceOnArena(who->xPos, who->zPos);
|
||
if ((wheresIt == kBackBoard) || (wheresIt == kGoalPath))
|
||
{
|
||
if (who->zVel > 0)
|
||
who->zVel *= -1;
|
||
|
||
if (who->xPos < 0)
|
||
{
|
||
if (who->xVel < 0)
|
||
who->xVel *= -1;
|
||
}
|
||
else
|
||
{
|
||
if (who->xVel > 0)
|
||
who->xVel *= -1;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//======================================================== CheckUpOnBall
|
||
|
||
void CheckUpOnBall (void)
|
||
|
||
{
|
||
short wheresIt;
|
||
|
||
wheresIt = GetPlaceOnArena(theBall.xPos, theBall.zPos);
|
||
if (wheresIt == kBackBoard)
|
||
{
|
||
if (theBall.zVel > 0)
|
||
theBall.zVel *= -1;
|
||
|
||
if (theBall.xPos < 0)
|
||
{
|
||
if (theBall.xVel < 0)
|
||
theBall.xVel *= -1;
|
||
}
|
||
else
|
||
{
|
||
if (theBall.xVel > 0)
|
||
theBall.xVel *= -1;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//======================================================== HandleBallWallCollision
|
||
|
||
void HandleBallWallCollision (void)
|
||
|
||
{
|
||
short tempVel;
|
||
|
||
if (theBall.justHitWall != 0)
|
||
{
|
||
theBall.flag = kIsNormal;
|
||
return;
|
||
}
|
||
|
||
if (theBall.xPos < 0)
|
||
{
|
||
if (theBall.xVel > theBall.zVel)
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
if (-theBall.xVel > theBall.zVel)
|
||
return;
|
||
}
|
||
|
||
PlaySoundSMS(kRicochetSound);
|
||
theBall.flag = kIsRebounding;
|
||
|
||
theBall.justHitWall = kLoopsImpactless;
|
||
thePlayer.justHitBall = 0;
|
||
theOpponent.justHitBall = 0;
|
||
|
||
theBall.xPos -= (theBall.xVel / kVelocitySensitive);
|
||
theBall.zPos -= (theBall.zVel / kVelocitySensitive);
|
||
|
||
if (theBall.xPos < 0)
|
||
{
|
||
tempVel = theBall.xVel;
|
||
theBall.xVel = theBall.zVel;
|
||
theBall.zVel = tempVel;
|
||
}
|
||
else
|
||
{
|
||
tempVel = theBall.xVel;
|
||
theBall.xVel = -theBall.zVel;
|
||
theBall.zVel = -tempVel;
|
||
}
|
||
|
||
CheckUpOnBall();
|
||
}
|
||
|
||
|
||
//======================================================== HandleCollisions
|
||
|
||
void HandleCollisions (void)
|
||
|
||
{
|
||
if (netGameInSession)
|
||
{
|
||
if (imTheMaster)
|
||
{
|
||
CheckPersonBallCollision(&thePlayer);
|
||
CheckPersonBallCollision(&theOpponent);
|
||
}
|
||
else
|
||
{
|
||
CheckPersonBallCollision(&theOpponent);
|
||
CheckPersonBallCollision(&thePlayer);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
CheckPersonBallCollision(&thePlayer);
|
||
CheckPersonBallCollision(&theOpponent);
|
||
}
|
||
|
||
CheckPersonPersonCollision();
|
||
|
||
if (thePlayer.justHitWall > 0)
|
||
{
|
||
thePlayer.justHitWall--;
|
||
if (thePlayer.justHitWall == kFrameToDampen)
|
||
{
|
||
thePlayer.xVel -= thePlayer.xVel / kPersonDampening;
|
||
thePlayer.zVel -= thePlayer.zVel / kPersonDampening;
|
||
}
|
||
}
|
||
if (thePlayer.justHitBall > 0)
|
||
thePlayer.justHitBall--;
|
||
if (thePlayer.justHitOpponent > 0)
|
||
thePlayer.justHitOpponent--;
|
||
|
||
if (theOpponent.justHitWall > 0)
|
||
{
|
||
theOpponent.justHitWall--;
|
||
if (theOpponent.justHitWall == kFrameToDampen)
|
||
{
|
||
theOpponent.xVel -= theOpponent.xVel / kPersonDampening;
|
||
theOpponent.zVel -= theOpponent.zVel / kPersonDampening;
|
||
}
|
||
}
|
||
if (theOpponent.justHitBall > 0)
|
||
theOpponent.justHitBall--;
|
||
if (theOpponent.justHitOpponent > 0)
|
||
theOpponent.justHitOpponent--;
|
||
|
||
if (theBall.justHitWall > 0)
|
||
{
|
||
theBall.justHitWall--;
|
||
if (theBall.justHitWall == kFrameToDampen)
|
||
{
|
||
theBall.xVel /= kBallDampening;
|
||
theBall.zVel /= kBallDampening;
|
||
}
|
||
}
|
||
}
|
||
|