1 line
9.6 KiB
C
Executable File
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|