Pararena2/Sources/Dynamics.c

1 line
15 KiB
C
Executable File
Raw Permalink Blame History

//============================================================
//============================================================
//== ==
//== 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;
}
}
}