Pararena2/Sources/Ball.c

1 line
9.6 KiB
C
Executable File

//============================================================
//============================================================
//== ==
//== Ball Handling Routines ==
//== ==
//============================================================
//============================================================
//======================================================== Includes
#include "Globals.h"
#include "UnivUtilities.h"
#include "Ball.h"
#include "Render.h"
#include "PlayUtils.h"
#include "SoundUtils.h"
#include "Dynamics.h"
//======================================================== Functions
//======================================================== BallRectFromPosition
void BallRectFromPosition (void)
{
short rootHeight, actualHeight;
short indexX, absoluteX, fractionalX;
short indexZ, fractionalZ;
theBall.isRect.left = (theBall.xPos / 64) + displayHCenter - 5;
theBall.isRect.right = theBall.isRect.left + 16;
absoluteX = theBall.xPos;
if (absoluteX < 0)
absoluteX = -absoluteX;
indexX = absoluteX / 512;
fractionalX = absoluteX % 512;
indexZ = (theBall.zPos / 512) + 40;
fractionalZ = theBall.zPos % 512;
rootHeight = vertTable[indexX][indexZ];
actualHeight = rootHeight + (fractionalX * (vertTable[indexX + 1][indexZ] - rootHeight)) / 512;
actualHeight += (fractionalZ * (vertTable[indexX][indexZ + 1] - rootHeight)) / 512;
theBall.isRect.bottom = actualHeight + 4;
theBall.isRect.top = theBall.isRect.bottom - 12;
if ((theBall.isRect.bottom > screenHigh) || (theBall.isRect.top < 0) ||
(theBall.isRect.right > screenWide) || (theBall.isRect.left < 0))
{
theBall.isRect = theBall.wasRect;
}
}
//======================================================== ResetBall
void ResetBall (void)
{
theBall.mode = kBallFiring;
theBall.modifier = kInitBallFiringTime + RandomInt(60) - 30;
theBall.flag = kIsNormal;
theBall.xPos = theBall.initXPos;
theBall.zPos = theBall.initZPos;
theBall.xVel = theBall.initXVel + RandomInt(3000) - 1000;
theBall.zVel = theBall.initZVel;
theBall.justHitWall = 0;
theBall.dontDraw = FALSE;
if (RandomCoin()) // was if (leftScoredLast)
{
leftScoredLast = TRUE;
theBall.xVel *= -1;
theBall.xPos += 384;
}
else
{
leftScoredLast = FALSE;
theBall.xPos -= 384;
}
thePlayer.mouseWasLetUp = TRUE;
theOpponent.mouseWasLetUp = TRUE;
BallRectFromPosition();
whosGotBall = kBallIsNotHere;
thePlayer.loopsBallHeld = 0;
theOpponent.loopsBallHeld = 0;
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));
}
UpdateBallTimers(&thePlayer);
UpdateBallTimers(&theOpponent);
UpdateArrows();
}
//======================================================== DoAFoul
void DoAFoul (void)
{
if (theBall.modifier == kPlayerLastHeld)
HandlePlayerFoul();
else
HandleOpponentFoul();
theBall.eraseTheBall = TRUE;
ResetBall();
}
//======================================================== DoBallFiring
void DoBallFiring (void)
{
theBall.modifier--;
if (theBall.modifier == 0)
{
PlaySoundSMS(kBallFiringSound);
theBall.mode = kBallRolling;
theBall.modifier = kNoOneLastHeld;
theBall.loopsBallIdle = kLoopLimitOnIdleBall;
theDoor.doorState = kDoorIsOpen;
theDoor.phase = kDoorPhases;
theDoor.stateChanged = TRUE;
if (leftScoredLast)
theDoor.doorOpen = kLeftDoor;
else
theDoor.doorOpen = kRightDoor;
whosGotBall = kBallRollsFreely;
}
}
//======================================================== MoveRollingBall
void MoveRollingBall (void)
{
#define kOffTheDishLg 473497600L // 340 x 64 ^2
#define kOffTheDishSm 321126400L // 280 x 64 ^2
long ballDistSquared;
short indexX, indexZ;
short signX, signZ;
short forceX, forceZ;
short frictionX, frictionZ;
short tempVel;
indexX = theBall.xPos;
if (indexX < 0)
{
indexX = -indexX;
signX = -1;
}
else
{
signX = 1;
}
indexX /= 512;
indexZ = theBall.zPos;
if (indexZ < 0)
{
indexZ = -indexZ;
signZ = -1;
}
else
{
signZ = 1;
}
indexZ /= 512;
if (theBall.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;
}
}
switch (forceX)
{
case kOutOBounds:
theBall.flag = kIsOutOfBounds;
break;
case kBackBoard:
if (theBall.zPos < 0)
theBall.flag = kIsOutOfBounds;
else
{
HandleBallWallCollision();
theBall.xPos += (theBall.xVel / kVelocitySensitive);
theBall.zPos += (theBall.zVel / kVelocitySensitive);
}
break;
case kGoalPath:
if (theBall.zPos < 0)
theBall.flag = kIsOutOfBounds;
else
theBall.flag = kIsInGoal;
break;
default:
theBall.flag = kIsNormal;
forceX *= signX;
if (theBall.xPos < 0)
{
switch (leftGoalLeague)
{
case kLittleLeague:
forceZ = *(littleForceTable + indexX * 82 + indexZ * 2 +
kZComponent) * signZ;
break;
case kJuniorVarsity:
forceZ = *(juniorForceTable + indexX * 82 + indexZ * 2 +
kZComponent) * signZ;
break;
case kVarsity:
forceZ = *(varsityForceTable + indexX * 82 + indexZ * 2 +
kZComponent) * signZ;
break;
case kMinorLeague:
forceZ = *(minorForceTable + indexX * 82 + indexZ * 2 +
kZComponent) * signZ;
break;
case kProfessional:
forceZ = *(proForceTable + indexX * 82 + indexZ * 2 +
kZComponent) * signZ;
break;
default:
forceZ = 0;
break;
}
}
else
{
switch (rightGoalLeague)
{
case kLittleLeague:
forceZ = *(littleForceTable + indexX * 82 + indexZ * 2 +
kZComponent) * signZ;
break;
case kJuniorVarsity:
forceZ = *(juniorForceTable + indexX * 82 + indexZ * 2 +
kZComponent) * signZ;
break;
case kVarsity:
forceZ = *(varsityForceTable + indexX * 82 + indexZ * 2 +
kZComponent) * signZ;
break;
case kMinorLeague:
forceZ = *(minorForceTable + indexX * 82 + indexZ * 2 +
kZComponent) * signZ;
break;
case kProfessional:
forceZ = *(proForceTable + indexX * 82 + indexZ * 2 +
kZComponent) * signZ;
break;
default:
forceZ = 0;
break;
}
}
theBall.xVel -= forceX;
theBall.zVel -= forceZ;
if (theBall.justHitWall == 0)
{
frictionX = theBall.xVel / kFrictionFraction;
frictionZ = theBall.zVel / kFrictionFraction;
theBall.xVel -= frictionX;
theBall.zVel -= frictionZ;
}
theBall.xPos += (theBall.xVel / kVelocitySensitive);
theBall.zPos += (theBall.zVel / kVelocitySensitive);
break;
}
ballDistSquared = ((long)theBall.xPos * (long)theBall.xPos) +
((long)theBall.zPos * (long)theBall.zPos);
if (arenaSize == kLargeArena)
{
if (ballDistSquared > kOffTheDishLg)
theBall.dontDraw = TRUE;
else
theBall.dontDraw = FALSE;
}
else
{
if (ballDistSquared > kOffTheDishSm)
theBall.dontDraw = TRUE;
else
theBall.dontDraw = FALSE;
}
BallRectFromPosition();
}
//======================================================== DoBallInGoal
void DoBallInGoal (void)
{
theBall.eraseTheBall = TRUE;
if (theBall.xPos < 0)
{
if (leftGoalIsPlayers)
DoPlayerScores();
else
DoOpponentScores();
}
else
{
if (!leftGoalIsPlayers)
DoPlayerScores();
else
DoOpponentScores();
}
ResetBall();
}
//======================================================== DoBallRolling
void DoBallRolling (void)
{
switch (theBall.flag)
{
case kIsNormal:
case kIsRebounding:
MoveRollingBall();
theBall.loopsBallIdle--;
if (theBall.loopsBallIdle == 120)
{
PlaySoundSMS(kIdleSound);
}
if (theBall.loopsBallIdle == 0)
{
theBall.eraseTheBall = TRUE;
ResetBall();
}
break;
case kIsOutOfBounds:
DoAFoul();
break;
case kIsInGoal:
DoBallInGoal();
break;
default:
break;
}
}
//======================================================== HandleBall
void HandleBall (void)
{
switch (theBall.mode)
{
case kBallFiring:
DoBallFiring();
break;
case kBallRolling:
DoBallRolling();
break;
case kBallHeld:
break;
case kBallInStasis:
break;
}
if (theDoor.phase != 0)
{
theDoor.phase--;
if (theDoor.phase == 0)
{
theDoor.doorState = kDoorIsClosed;
theDoor.stateChanged = TRUE;
}
}
}