home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / SpriteFight 2002 v2.0a1 / SpriteStatusChex.c < prev    next >
Encoding:
Text File  |  1996-04-30  |  29.5 KB  |  987 lines  |  [TEXT/SPM ]

  1. // SpriteStausChex.c by Stefan C. Sinclair Copyright © 1995-1996 All Rights Reserved.
  2.  
  3. #include "StefSpritez.h"
  4. #include "SpriteCicnNumbers.h"
  5. #include "SpriteError.h"
  6. #include "SpriteFile.h"
  7. #include "SpriteSecretCodes.h"
  8.  
  9. #define keyP1Right        keyCommand
  10. #define keyP1Left        keyControl
  11. #define keyP1Jump        keyShift
  12. #define keyP1Punch        keyC
  13. #define keyP1Kick        keyV
  14. #define keyP1JumpAttack    keySpace
  15. #define keyP1Block        keyTab
  16. #define keyP1Duck        keyOption
  17. #define keyP1Uppercut    keyB
  18. #define keyP1Taunt        keyN
  19. #define keyP1Shoot        keyS
  20.  
  21. #define keyP2Right        keyRArrow
  22. #define keyP2Left        keyLArrow
  23. #define keyP2Jump        keyUpArrow
  24. #define keyP2Punch        keyNum1
  25. #define keyP2Kick        keyNum2
  26. #define keyP2JumpAttack    keyNum3
  27. #define keyP2Block        keyNum0
  28. #define keyP2Duck        keyDownArrow
  29. #define keyP2Uppercut    keyNum4
  30. #define keyP2Taunt        keyNum5
  31. #define keyP2Shoot        keyNum6
  32.  
  33. #define bRunLeft        spriteAction[0]
  34. #define bRunRight        spriteAction[1]
  35. #define bPunch            spriteAction[2]
  36. #define bKick            spriteAction[3]
  37. #define bJump            spriteAction[4]
  38. #define bBlock            spriteAction[5]
  39. #define bJumpAttack        spriteAction[6]
  40. #define bJumpPunch        spriteAction[7]
  41. #define bJumpKick        spriteAction[8]
  42. #define bDuck            spriteAction[9]
  43. #define bUppercut        spriteAction[10]
  44. #define bTaunt            spriteAction[11]
  45. #define bShoot            spriteAction[12]
  46. #define kNumActions        13
  47.  
  48. #define FRAME_UPDATE     SpriteFrameUpdate(srcSpriteP, spriteDataPtr,\
  49.                         rightSideAdjustFrames, forceFrameUpdate)
  50.  
  51. extern SpriteGameRec spriteGame;
  52. extern SpriteFileRec    gPlayer1File, gPlayer2File;
  53. extern Handle    gP1SoundH[kNumSpriteSounds], gP2SoundH[kNumSpriteSounds];
  54. extern SndChannelPtr gSoundChanP1, gSoundChanP2, gSoundChanGame;
  55. extern short    gWinnerSprite;
  56. extern short    gFrameAdvanceTime;
  57. extern short gSpriteHeight, gSpriteWidth;
  58. extern Boolean gSecretCode[kNumSecretCodes];
  59.  
  60. Point    player1TopLeft, projectile1TopLeft;
  61. Point    player2TopLeft, projectile2TopLeft;
  62.  
  63. /* PlayerStatusCheck */
  64. /* double = 8 bytes ; char = 1 byte ; => 1 double == 8 chars
  65.     Use srcSpriteP->userData (change from long to double!!!) to store 8 chars, which will
  66.     hold all the necessary information. */
  67. Boolean PlayerStatusCheck(SpritePtr srcSpriteP, Point *spritePoint)
  68. {
  69.     Boolean spriteAction[kNumActions] = {0};
  70.     Boolean airBorne, forceFrameUpdate = FALSE;
  71.     Boolean rightSide, oldSide;
  72.     unsigned char    *spriteDataPtr; // use as an array of 8 u. chars.
  73.     short    rightSideAdjustFrames;
  74.     
  75.     spriteDataPtr = (unsigned char *)&srcSpriteP->userData;
  76.     // is sprite airborne?
  77.     airBorne = ((spritePoint->v >= (srcSpriteP->moveBoundsRect.bottom - kGroundLevel)) ? FALSE : TRUE);
  78.     
  79.     // Which side was sprite on?
  80.     if(rightSide = BitTst(&spriteDataPtr[kSpriteBitData], kCurrentSide))
  81.     // Set previous side
  82.     {
  83.         oldSide = kRightSide;
  84.         BitSet(&spriteDataPtr[kSpriteBitData], kPreviousSide);
  85.     }
  86.     else
  87.     {
  88.         oldSide = kLeftSide;
  89.         BitClr(&spriteDataPtr[kSpriteBitData], kPreviousSide);
  90.     }
  91.     // Now update this data
  92.     if(rightSide = GetSpriteSide(spriteDataPtr))
  93.     {
  94.         BitSet(&spriteDataPtr[kSpriteBitData], kCurrentSide);
  95.         rightSideAdjustFrames = kTotalFramesOneWay;
  96.     }
  97.     else
  98.     {
  99.         BitClr(&spriteDataPtr[kSpriteBitData], kCurrentSide);
  100.         rightSideAdjustFrames = 0;
  101.     }
  102.     
  103.     // force a frame update if necessary    
  104.     if((oldSide != rightSide) && !airBorne)
  105.     {
  106.         SpriteFrameUpdate(srcSpriteP, spriteDataPtr, rightSideAdjustFrames, TRUE);
  107.     }
  108.     // If the other guy is dying, leave now.
  109.     if(spriteDataPtr[kCurrentAction] == aDoNothing)
  110.         return TRUE;
  111.     // First check for special actions being performed
  112.     // Should sprite be dying? If so, start dying
  113.     if(spriteDataPtr[kSpriteLife] <= kSpriteMinLife &&
  114.         spriteDataPtr[kCurrentAction] != aDying)
  115.     {
  116.         short deathMode = aDying; // deathMode is aDying by default for now.
  117.         
  118.         DigSpriteGrave(spriteDataPtr[kSpriteIDNum], deathMode);
  119.         spriteDataPtr[kCurrentAction] = aDying;
  120.         // switch(spriteDataPtr[kCurrentAction]) // switch depending on death mode...
  121.         spriteDataPtr[kCurrentFrame] = kMaxDeathFrames;
  122.         rightSideAdjustFrames = (rightSideAdjustFrames == kTotalFramesOneWay ?
  123.                 kMaxDeathFrames : 0);
  124.         forceFrameUpdate = TRUE;
  125.         FRAME_UPDATE;
  126.         switch(spriteDataPtr[kSpriteIDNum])
  127.         {
  128.             unsigned char    *otherSpriteDataPtr; // make every other sprite 'idle'
  129.             
  130.             case kPlayer1Sprite:
  131.             case kComputer1Sprite:
  132.                 PlaySound(gP1SoundH[sDead], gSoundChanP1);
  133.                 otherSpriteDataPtr = (unsigned char *)&spriteGame.spriteArray[kPlayer2Sprite].userData;
  134.                 otherSpriteDataPtr[kCurrentAction] = aDoNothing;
  135.                 otherSpriteDataPtr = (unsigned char *)&spriteGame.spriteArray[kPlayer1ProjectileSprite].userData;
  136.                 otherSpriteDataPtr[kCurrentAction] = aDoNothing;
  137.                 otherSpriteDataPtr = (unsigned char *)&spriteGame.spriteArray[kPlayer2ProjectileSprite].userData;
  138.                 otherSpriteDataPtr[kCurrentAction] = aDoNothing;
  139.                 break;
  140.             case kPlayer2Sprite:
  141.             case kComputer2Sprite:
  142.                 PlaySound(gP2SoundH[sDead], gSoundChanP2);
  143.                 otherSpriteDataPtr = (unsigned char *)&spriteGame.spriteArray[kPlayer1Sprite].userData;
  144.                 otherSpriteDataPtr[kCurrentAction] = aDoNothing;
  145.                 otherSpriteDataPtr = (unsigned char *)&spriteGame.spriteArray[kPlayer1ProjectileSprite].userData;
  146.                 otherSpriteDataPtr[kCurrentAction] = aDoNothing;
  147.                 otherSpriteDataPtr = (unsigned char *)&spriteGame.spriteArray[kPlayer2ProjectileSprite].userData;
  148.                 otherSpriteDataPtr[kCurrentAction] = aDoNothing;
  149.                 break;
  150.         }
  151.         return TRUE; // not alive anymore, but not finished dying yet
  152.     }
  153.     
  154.     if(spriteDataPtr[kCurrentAction] == aDying || spriteDataPtr[kPreviousAction] == aDying) // Dead or dying.
  155.     {
  156.         spriteDataPtr[kCurrentAction] = aDying; // Make no mistake about it!
  157.         spriteDataPtr[kPreviousAction] = aDying; // This dude will DIE!
  158.         spriteDataPtr[kCurrentFrame] -= 1;
  159.         rightSideAdjustFrames = (rightSideAdjustFrames == kTotalFramesOneWay ?
  160.                 kMaxDeathFrames : 0);
  161.         FRAME_UPDATE;
  162.         if(spriteDataPtr[kCurrentFrame] <= 1) // 1, NOT 0 - trust me; it works
  163.         {
  164.             switch(spriteDataPtr[kSpriteIDNum])
  165.             {
  166.                 case kPlayer1Sprite:
  167.                 case  kComputer1Sprite:
  168.                     gWinnerSprite = kPlayer2Sprite;
  169.                         break;
  170.                 case kPlayer2Sprite:
  171.                 case  kComputer2Sprite:
  172.                     gWinnerSprite = kPlayer1Sprite;
  173.                     break;
  174.                 default:
  175.                     DoError(kUnknownSpriteInGame, FALSE);
  176.                     gWinnerSprite = kPlayer1Sprite;
  177.                     break;
  178.             }
  179.             return FALSE; // He's dead, Jim.
  180.         }
  181.         else
  182.             return TRUE; // Alive, but in the process of dying
  183.     }
  184.     
  185.     // Sprite getting hit?
  186.     if(spriteDataPtr[kCurrentAction] == aGotHit &&
  187.         spriteDataPtr[kPreviousAction] != aGotHit)
  188.     {
  189.         // Need to keep wobbling around in a painful stupor for 1 more frame!
  190.         spriteDataPtr[kPreviousAction] = spriteDataPtr[kCurrentAction];
  191.         forceFrameUpdate = TRUE;
  192.         FRAME_UPDATE;
  193.         return TRUE;
  194.     }
  195.     // This is next time!
  196.     else if(spriteDataPtr[kCurrentAction] == aGotHit &&
  197.         spriteDataPtr[kPreviousAction] == aGotHit)
  198.     {
  199.         // Need to stop wobbling around in a painful stupor!
  200.         FRAME_UPDATE;
  201.         spriteDataPtr[kPreviousAction] = spriteDataPtr[kCurrentAction];
  202.         // Don't return, otherwise sprite will never have chance to block!
  203.     }
  204.     
  205.     // Sprite just hit the other guy?
  206.     if(spriteDataPtr[kCurrentAction] == aPostAttack)
  207.     {
  208.         spriteDataPtr[kPreviousAction] = spriteDataPtr[kCurrentAction];
  209.         spriteDataPtr[kCurrentAction] = aIdle;
  210.         //forceFrameUpdate = TRUE; // comment out to allow the sprite to follow thru
  211.         FRAME_UPDATE;
  212.         return TRUE;
  213.     }
  214.     
  215.     if(!airBorne)
  216.     {
  217.         srcSpriteP->vertMoveDelta = spriteDataPtr[kHangTime] = 0;
  218.         spritePoint->v = srcSpriteP->moveBoundsRect.bottom - kGroundLevel;
  219.         // Just land?
  220.         switch(spriteDataPtr[kPreviousAction]) // used to check kCurrentAction
  221.         {
  222.             case aJump:
  223.             case aJumpAttack:
  224.             case aJumpPunch:
  225.             case aJumpKick:
  226.                 spriteDataPtr[kPreviousAction] = spriteDataPtr[kCurrentAction];
  227.                 spriteDataPtr[kCurrentAction] = aIdle;
  228.                 srcSpriteP->vertMoveDelta = spriteDataPtr[kHangTime] = 0;
  229.                 spritePoint->v = srcSpriteP->moveBoundsRect.bottom - kGroundLevel;
  230.                 forceFrameUpdate = TRUE;
  231.                 FRAME_UPDATE;
  232.                 return TRUE;
  233.             default:
  234.                 break;
  235.         }
  236.     }
  237.     else //(airBorne) 
  238.     // First, do all necessary checking to get the current action.
  239.     // if sprite is airborne, it can only jump-kick, jump-punch or shoot!
  240.     {
  241.         // gravity
  242.         srcSpriteP->vertMoveDelta += spriteDataPtr[kHangTime];
  243.         spriteDataPtr[kHangTime]+=1;
  244.     }
  245.     
  246.     // Get the current action being performed. If it differs from the previous action,
  247.     // update things as necessary.
  248.     GetSpriteAction(spriteDataPtr, &spriteAction[0], airBorne);
  249.     // Save previous action (formerly the current action)
  250.     spriteDataPtr[kPreviousAction] = spriteDataPtr[kCurrentAction];
  251.     
  252.     // Doing nothing?
  253.     if((bRunLeft+bRunRight+bPunch+bKick+bJump+bBlock+bJumpAttack+
  254.         bJumpPunch+bJumpKick+bDuck+bUppercut+bTaunt+bShoot)==0) 
  255.     {
  256.         srcSpriteP->horizMoveDelta = (airBorne ? srcSpriteP->horizMoveDelta : 0);
  257.         spriteDataPtr[kCurrentAction] = (airBorne ? spriteDataPtr[kCurrentAction] : aIdle);
  258.         FRAME_UPDATE;
  259.         return TRUE;
  260.     }
  261.     if(bBlock) // Blocking?
  262.     {
  263.         srcSpriteP->horizMoveDelta=0;
  264.         spriteDataPtr[kCurrentAction] = aBlock;
  265.         FRAME_UPDATE;
  266.         return TRUE;
  267.     }
  268.     if(bUppercut) // Uppercutting? - MUST check for this before ducking
  269.     {
  270.         srcSpriteP->horizMoveDelta = 0; // No horizontal movement for these cases.
  271.         spriteDataPtr[kCurrentAction] = aUppercut;
  272.         FRAME_UPDATE;
  273.         switch(spriteDataPtr[kSpriteIDNum])
  274.         {
  275.             case kPlayer1Sprite:
  276.             case kComputer1Sprite:
  277.                 if(spriteDataPtr[kPreviousAction] != aUppercut)
  278.                     PlaySound(gP1SoundH[sSwing], gSoundChanP1);
  279.                 break;
  280.             case kPlayer2Sprite:
  281.             case kComputer2Sprite:
  282.                 if(spriteDataPtr[kPreviousAction] != aUppercut)
  283.                     PlaySound(gP2SoundH[sSwing], gSoundChanP2);
  284.                 break;
  285.         }
  286.         return TRUE;
  287.     }
  288.     if(bDuck) // Ducking?
  289.     {
  290.         srcSpriteP->horizMoveDelta=0;
  291.         spriteDataPtr[kCurrentAction] = aDuck;
  292.         FRAME_UPDATE;
  293.         return TRUE;
  294.     }
  295.     if(bTaunt) // Taunting?
  296.     {
  297.         srcSpriteP->horizMoveDelta=0;
  298.         spriteDataPtr[kCurrentAction] = aTaunt;
  299.         if(spriteDataPtr[kPreviousAction] != aTaunt)
  300.         {
  301.             spriteDataPtr[kCurrentFrame] = 0;
  302.             switch(spriteDataPtr[kSpriteIDNum])
  303.             {
  304.                 case kPlayer1Sprite:
  305.                 case kComputer1Sprite:
  306.                     PlaySound(gP1SoundH[sTaunt], gSoundChanP1);
  307.                     break;
  308.                 case kPlayer2Sprite:
  309.                 case kComputer2Sprite:
  310.                     PlaySound(gP2SoundH[sTaunt], gSoundChanP2);
  311.                 break;
  312.             }
  313.         }
  314.         else
  315.         {    
  316.             spriteDataPtr[kCurrentFrame] += 1;
  317.             // Taunt long enough and sprite will start to regenerate!
  318.             if(spriteDataPtr[kCurrentFrame] == kSpriteHealingTime &&
  319.                 spriteDataPtr[kSpriteLife] < kSpriteMaxLife &&
  320.                 !gSecretCode[kNoRegenerationCode])
  321.             {
  322.                 Rect    eraseRect;
  323.                 
  324.                 eraseRect.top = kLifeRectTop;
  325.                 eraseRect.bottom = kLifeRectBottom;
  326.                 spriteDataPtr[kSpriteLife] += 1; // regenerate!
  327.                 spriteDataPtr[kCurrentFrame] -= 1; // Allow continuous regeneration
  328.                 switch(spriteDataPtr[kSpriteIDNum])
  329.                 {
  330.                     case kPlayer1Sprite:
  331.                     case kComputer1Sprite:
  332.                         eraseRect.left = kP1LifeRectLeft;
  333.                         eraseRect.right = kP1LifeRectLeft + spriteDataPtr[kSpriteLife] -5;
  334.                         break;
  335.                     case kPlayer2Sprite:
  336.                     case kComputer2Sprite:
  337.                         eraseRect.left = kP2LifeRectLeft;
  338.                         eraseRect.right = kP2LifeRectLeft + spriteDataPtr[kSpriteLife] -5;
  339.                         break;
  340.                     default:
  341.                         DoError(kUnknownSpriteInGame, TRUE);
  342.                         break;
  343.                 }
  344.                 EraseRect(&eraseRect);
  345.             }
  346.         }
  347.         FRAME_UPDATE;
  348.         return TRUE;
  349.     }
  350.     if(bShoot) // shooting?
  351.     {
  352.         unsigned char *projSpriteDataPtr;
  353.         
  354.         // Must determine which projectile is mine
  355.         switch(spriteDataPtr[kSpriteIDNum])
  356.         {    
  357.             case kPlayer1Sprite:
  358.             case kComputer1Sprite:
  359.                 projSpriteDataPtr = (unsigned char *)&spriteGame.spriteArray[kPlayer1ProjectileSprite].userData;
  360.                 bShoot = (projSpriteDataPtr[kCurrentAction] == aProjectileShoot ? FALSE : TRUE);
  361.                 break;
  362.             case kPlayer2Sprite:
  363.             case kComputer2Sprite:
  364.                 projSpriteDataPtr = (unsigned char *)&spriteGame.spriteArray[kPlayer2ProjectileSprite].userData;
  365.                 bShoot = (projSpriteDataPtr[kCurrentAction] == aProjectileShoot ? FALSE : TRUE);
  366.                 break;
  367.         }
  368.         if(bShoot)
  369.         {
  370.             short id = projSpriteDataPtr[kSpriteIDNum], frameOffset, bulletSpeed;
  371.             
  372.             srcSpriteP->horizMoveDelta=0;
  373.             spriteDataPtr[kCurrentAction] = aShoot;
  374.             projSpriteDataPtr[kCurrentAction] = aProjectileShoot;
  375.             FRAME_UPDATE;
  376.             // Launch projectile!!!!
  377.             SWSetSpriteLocation(&spriteGame.spriteArray[id], spritePoint->h, spritePoint->v);
  378.             SWSetSpriteVisible(&spriteGame.spriteArray[id], TRUE);
  379.             frameOffset = (rightSide ? 2 : 0);
  380.             SpriteFrameUpdate(&spriteGame.spriteArray[id], projSpriteDataPtr, frameOffset, TRUE);
  381.             bulletSpeed = kProjectileSpeed;
  382.             if(gSecretCode[kFastProjectileCode])
  383.                 bulletSpeed*=3;
  384.             if(gSecretCode[kSlowProjectileCode])
  385.                 bulletSpeed/=3;
  386.             spriteGame.spriteArray[id].horizMoveDelta = (rightSide ? -bulletSpeed : bulletSpeed);
  387.             switch(spriteDataPtr[kSpriteIDNum])
  388.             {
  389.                 case kPlayer1Sprite:
  390.                 case kComputer1Sprite:
  391.                     PlaySound(gP1SoundH[sProjectile], gSoundChanP1);
  392.                     break;
  393.                 case kPlayer2Sprite:
  394.                 case kComputer2Sprite:
  395.                     PlaySound(gP2SoundH[sProjectile], gSoundChanP2);
  396.                 break;
  397.             }
  398.         }
  399.         return TRUE;
  400.     }
  401.     if(bJump) // Jumping?
  402.     {
  403.         srcSpriteP->vertMoveDelta = (gSecretCode[kHighJumpCode] ?
  404.                 (2*kJumpSpeed) : kJumpSpeed);
  405.         spriteDataPtr[kHangTime] = 1;
  406.         spriteDataPtr[kCurrentAction] = aJump;
  407.         switch(spriteDataPtr[kSpriteIDNum])
  408.         {
  409.             case kPlayer1Sprite:
  410.             case kComputer1Sprite:
  411.                 PlaySound(gP1SoundH[sJump], gSoundChanP1);
  412.                 break;
  413.             case kPlayer2Sprite:
  414.             case kComputer2Sprite:
  415.                 PlaySound(gP2SoundH[sJump], gSoundChanP2);
  416.                 break;
  417.         }
  418.         FRAME_UPDATE;
  419.         return TRUE;
  420.     }
  421.     if(bJumpAttack) // Jump-Attacking? - special case!!!
  422.     {
  423.         srcSpriteP->vertMoveDelta=kJumpAttackVertSpeed;
  424.         srcSpriteP->horizMoveDelta =
  425.             (rightSide ? -kJumpAttackHorizSpeed : +kJumpAttackHorizSpeed);
  426.         if(gSecretCode[kSuperJACode])
  427.             srcSpriteP->horizMoveDelta *= 2;
  428.         spriteDataPtr[kHangTime] = 1;
  429.         spriteDataPtr[kCurrentAction] = aJumpAttack;
  430.         switch(spriteDataPtr[kSpriteIDNum])
  431.         {
  432.             case kPlayer1Sprite:
  433.             case kComputer1Sprite:
  434.                 PlaySound(gP1SoundH[sJumpAttack], gSoundChanP1);
  435.                 break;
  436.             case kPlayer2Sprite:
  437.             case kComputer2Sprite:
  438.                 PlaySound(gP2SoundH[sJumpAttack], gSoundChanP2);
  439.                 break;
  440.         }
  441.         FRAME_UPDATE;
  442.         return TRUE;
  443.     }
  444.     if(bJumpPunch) // Jump-punching?
  445.     {
  446.         spriteDataPtr[kCurrentAction] = aJumpPunch;
  447.         switch(spriteDataPtr[kSpriteIDNum])
  448.         {
  449.             case kPlayer1Sprite:
  450.             case kComputer1Sprite:
  451.                 if(spriteDataPtr[kPreviousAction] != aJumpPunch)
  452.                     PlaySound(gP1SoundH[sSwing], gSoundChanP1);
  453.                 break;
  454.             case kPlayer2Sprite:
  455.             case kComputer2Sprite:
  456.                 if(spriteDataPtr[kPreviousAction] != aJumpPunch)
  457.                     PlaySound(gP2SoundH[sSwing], gSoundChanP2);
  458.                 break;
  459.         }
  460.         FRAME_UPDATE;
  461.         return TRUE;
  462.     }
  463.     if(bJumpKick) // Jump-kicking?
  464.     {
  465.         spriteDataPtr[kCurrentAction] = aJumpKick;
  466.         switch(spriteDataPtr[kSpriteIDNum])
  467.         {
  468.             case kPlayer1Sprite:
  469.             case kComputer1Sprite:
  470.                 if(spriteDataPtr[kPreviousAction] != aJumpKick)
  471.                     PlaySound(gP1SoundH[sSwing], gSoundChanP1);
  472.                 break;
  473.             case kPlayer2Sprite:
  474.             case kComputer2Sprite:
  475.                 if(spriteDataPtr[kPreviousAction] != aJumpKick)
  476.                     PlaySound(gP2SoundH[sSwing], gSoundChanP2);
  477.                 break;
  478.         }
  479.         FRAME_UPDATE;
  480.         return TRUE;
  481.     }
  482.     if(bPunch) // Punching?
  483.     {
  484.         srcSpriteP->horizMoveDelta = 0; // No horizontal movement for these cases.
  485.         spriteDataPtr[kCurrentAction] = aPunch;
  486.         FRAME_UPDATE;
  487.         switch(spriteDataPtr[kSpriteIDNum])
  488.         {
  489.             case kPlayer1Sprite:
  490.             case kComputer1Sprite:
  491.                 if(spriteDataPtr[kPreviousAction] != aPunch)
  492.                     PlaySound(gP1SoundH[sSwing], gSoundChanP1);
  493.                 break;
  494.             case kPlayer2Sprite:
  495.             case kComputer2Sprite:
  496.                 if(spriteDataPtr[kPreviousAction] != aPunch)
  497.                     PlaySound(gP2SoundH[sSwing], gSoundChanP2);
  498.                 break;
  499.         }
  500.         return TRUE;
  501.     }
  502.     if(bKick) // Kicking?
  503.     {
  504.         srcSpriteP->horizMoveDelta = 0; // No horizontal movement for these cases.
  505.         spriteDataPtr[kCurrentAction] = aKick;
  506.         FRAME_UPDATE;
  507.         switch(spriteDataPtr[kSpriteIDNum])
  508.         {
  509.             case kPlayer1Sprite:
  510.             case kComputer1Sprite:
  511.                 if(spriteDataPtr[kPreviousAction] != aKick)
  512.                     PlaySound(gP1SoundH[sSwing], gSoundChanP1);
  513.                 break;
  514.             case kPlayer2Sprite:
  515.             case kComputer2Sprite:
  516.                 if(spriteDataPtr[kPreviousAction] != aKick)
  517.                     PlaySound(gP2SoundH[sSwing], gSoundChanP2);
  518.                 break;
  519.         }
  520.         return TRUE;
  521.     }
  522.     if(bRunRight) // Running right?
  523.     {
  524.         if(srcSpriteP->horizMoveDelta < 0)
  525.         {
  526.             srcSpriteP->horizMoveDelta = 0;
  527.             spriteDataPtr[kCurrentAction] = aIdle;
  528.         }
  529.         else
  530.         {
  531.             srcSpriteP->horizMoveDelta++;
  532.             spriteDataPtr[kCurrentAction] = aRun;
  533.         }
  534.         FRAME_UPDATE;
  535.         return TRUE;
  536.     }
  537.     if(bRunLeft) // Running left?
  538.     {
  539.         if(srcSpriteP->horizMoveDelta > 0)
  540.         {
  541.             srcSpriteP->horizMoveDelta = 0;
  542.             spriteDataPtr[kCurrentAction] = aIdle;
  543.         }
  544.         else
  545.         {
  546.             srcSpriteP->horizMoveDelta--;
  547.             spriteDataPtr[kCurrentAction] = aRun;
  548.         }
  549.         FRAME_UPDATE;
  550.         return TRUE;
  551.     }
  552.  
  553.     return TRUE; // still alive.
  554. }
  555.  
  556. /* ProjectileStatusCheck */
  557. /* double = 8 bytes ; char = 1 byte ; => 1 double == 8 chars
  558.     Use srcSpriteP->userData (change from long to double!!!) to store 8 chars, which will
  559.     hold all the necessary information. */
  560. Boolean ProjectileStatusCheck(SpritePtr srcSpriteP, Point *spritePoint)
  561. {
  562.     Boolean visible, forceFrameUpdate = TRUE;
  563.     Boolean rightSide;
  564.     unsigned char    *spriteDataPtr; // use as an array of 8 u. chars.
  565.     short    rightSideAdjustFrames;
  566.     
  567.     spriteDataPtr = (unsigned char *)&srcSpriteP->userData;
  568.     
  569.     // If the somebody is dying, leave now.
  570.     if(spriteDataPtr[kCurrentAction] == aDoNothing)
  571.         return FALSE; // invisible (at least in theory
  572.     switch(spriteDataPtr[kSpriteIDNum])
  573.     {
  574.         case kPlayer1ProjectileSprite:
  575.             projectile1TopLeft = *spritePoint;
  576.             break;
  577.         case kPlayer2ProjectileSprite:
  578.             projectile2TopLeft = *spritePoint;
  579.             break;
  580.     }
  581.     
  582.     // force a frame update if necessary (but NOT if projectile is visible!)
  583.     visible = (spriteDataPtr[kCurrentAction] == aProjectileShoot ? TRUE : FALSE);
  584.     SWSetSpriteVisible(srcSpriteP, visible);
  585.     if(!visible) // Stop moving
  586.     {
  587.         srcSpriteP->horizMoveDelta=srcSpriteP->vertMoveDelta=0;
  588.     }
  589.     
  590.     spriteDataPtr[kPreviousAction] = spriteDataPtr[kCurrentAction];
  591.     
  592.     return (visible);
  593. }
  594.  
  595. void GetSpriteAction(unsigned char *spriteDataPtr, Boolean *spriteAction, Boolean airBorne)
  596. {
  597.     switch(spriteDataPtr[kSpriteIDNum])
  598.     {
  599.         case kPlayer1Sprite    :
  600.             GetP1HumanAction(spriteAction, airBorne);
  601.             break;
  602.         case kPlayer2Sprite:
  603.             GetP2HumanAction(spriteAction, airBorne);
  604.             break;
  605.         case kComputer1Sprite:
  606.         case kComputer2Sprite:
  607.             GetComputerAction(spriteAction, spriteDataPtr);
  608.             break;
  609.         default: // A memory error has most likely occurred if we get here somehow.
  610.             DoError(kUnknownSpriteInGame, TRUE);
  611.             break;
  612.     }
  613. }
  614.  
  615. void GetP1HumanAction(Boolean *spriteAction, Boolean airBorne)
  616. {
  617.     bRunLeft = (isPressed(keyP1Left) && !airBorne ? TRUE : FALSE);
  618.     bRunRight = (isPressed(keyP1Right) && !airBorne ? TRUE : FALSE);
  619.     bPunch = (isPressed(keyP1Punch) && !airBorne ? TRUE : FALSE);
  620.     bKick = (isPressed(keyP1Kick) && !airBorne ? TRUE : FALSE);
  621.     bBlock = (isPressed(keyP1Block) && !airBorne ? TRUE : FALSE);
  622.     bJumpAttack = (isPressed(keyP1JumpAttack) && !airBorne ? TRUE : FALSE);
  623.     bTaunt = (isPressed(keyP1Taunt) && !airBorne ? TRUE : FALSE);
  624.     bJump = (isPressed(keyP1Jump) && !airBorne ? TRUE : FALSE);
  625.     // You must be in the air to do a jump attack.
  626.     if(bJumpPunch = (isPressed(keyP1Punch) && airBorne ? TRUE : FALSE))
  627.         bPunch = FALSE;
  628.     if(bJumpKick = (isPressed(keyP1Kick) && airBorne ? TRUE : FALSE))
  629.         bKick = FALSE;
  630.     bShoot = (isPressed(keyP1Shoot) && !gSecretCode[kNoProjectileCode] ? TRUE : FALSE);
  631.     bDuck = (isPressed(keyP1Duck) && !airBorne ? TRUE : FALSE);
  632.     // You must be ducking to do an uppercut
  633.     bUppercut = (isPressed(keyP1Uppercut) && bDuck ? TRUE : FALSE);
  634. }
  635.  
  636. void GetP2HumanAction(Boolean *spriteAction, Boolean airBorne)
  637. {
  638.     bRunLeft = (isPressed(keyP2Left) && !airBorne ? TRUE : FALSE);
  639.     bRunRight = (isPressed(keyP2Right) && !airBorne ? TRUE : FALSE);
  640.     bPunch = (isPressed(keyP2Punch) && !airBorne ? TRUE : FALSE);
  641.     bKick = (isPressed(keyP2Kick) && !airBorne ? TRUE : FALSE);
  642.     bBlock = (isPressed(keyP2Block) && !airBorne ? TRUE : FALSE);
  643.     bJumpAttack = (isPressed(keyP2JumpAttack) && !airBorne ? TRUE : FALSE);
  644.     bTaunt = (isPressed(keyP2Taunt) && !airBorne ? TRUE : FALSE);
  645.     bJump = (isPressed(keyP2Jump) && !airBorne ? TRUE : FALSE);
  646.     // You must be in the air to do a jump attack.
  647.     if(bJumpPunch = (isPressed(keyP2Punch) && airBorne ? TRUE : FALSE))
  648.         bPunch = FALSE;
  649.     if(bJumpKick = (isPressed(keyP2Kick) && airBorne ? TRUE : FALSE))
  650.         bKick = FALSE;
  651.     bShoot = (isPressed(keyP2Shoot) && !gSecretCode[kNoProjectileCode] ? TRUE : FALSE);
  652.     bDuck = (isPressed(keyP2Duck) && !airBorne ? TRUE : FALSE);
  653.     // You must be ducking to do an uppercut
  654.     bUppercut = (isPressed(keyP2Uppercut) && bDuck ? TRUE : FALSE);
  655. }
  656.  
  657. void GetComputerAction(Boolean *spriteAction, unsigned char *dataP)
  658. {
  659.     short     beConsistent, inconsistent = 8, newAction;
  660.         
  661.     //• Just using 'beConsistent' as a counter for now...
  662.     for(beConsistent = 0; beConsistent < kNumActions; beConsistent++)
  663.         spriteAction[beConsistent] = FALSE;
  664.     // Now get a random number for consistency checking
  665.     beConsistent = GetRandom(0,9);
  666.     //• If getting hit, will almost always switch to a defensive posture!
  667.     if(dataP[kPreviousAction] == aGotHit || dataP[kCurrentAction] == aGotHit)
  668.     {
  669.         if(beConsistent < inconsistent)
  670.             newAction = aBlock;
  671.         else
  672.             newAction = GetRandom(0,9);
  673.     }
  674.     // be consistent unless jumping around!
  675.     else if((beConsistent < inconsistent) && (dataP[kPreviousAction] != aJump))
  676.     {
  677.         newAction = dataP[kPreviousAction];
  678.     }
  679.     else
  680.     {
  681.         newAction = GetRandom(0,9);
  682.     }
  683.     switch(newAction)
  684.     {
  685.         case aIdle:
  686.             break;
  687.         case aJump:
  688.             bJump = TRUE;
  689.             break;
  690.         case aRun:
  691.             // Which drxn to go?
  692.             switch(dataP[kCurrentSide])
  693.             {
  694.                 case kLeftSide:
  695.                     bRunRight = TRUE; // go right
  696.                     break;
  697.                 case kRightSide:
  698.                     bRunLeft = TRUE; // go left
  699.                     break;
  700.                 default:
  701.                     bJumpAttack = TRUE; // When in doubt, jump attack!
  702.                     break;
  703.             }
  704.             break;
  705.         case aBlock:
  706.             bBlock = TRUE;
  707.             break;
  708.         case aPunch:
  709.             bPunch = TRUE;
  710.             break;
  711.         case aKick:
  712.             bKick = TRUE;
  713.             break;
  714.         case aJumpAttack:
  715.             bJumpAttack = TRUE;
  716.             break;
  717.         default: // Run at your opponent!
  718.             // Which drxn to go?
  719.             switch(dataP[kCurrentSide])
  720.             {
  721.                 case kLeftSide:
  722.                     bRunRight = TRUE; // go right
  723.                     break;
  724.                 case kRightSide:
  725.                     bRunLeft = TRUE; // go left
  726.                     break;
  727.                 default:
  728.                     bJumpAttack = TRUE; // When in doubt, jump attack!
  729.                     break;
  730.             }
  731.             break;
  732.     }
  733. }
  734.  
  735. void SpriteFrameUpdate(SpritePtr srcSpriteP, unsigned char *spriteDataPtr,
  736.         short rightSideAdjustFrames, Boolean forceUpdate)
  737. {
  738.     
  739.     if((spriteDataPtr[kCurrentAction] != spriteDataPtr[kPreviousAction])
  740.         || (forceUpdate==TRUE))
  741.     {
  742.         switch(spriteDataPtr[kCurrentAction])
  743.         {
  744.             case aIdle:
  745.                 // adjust speeds to this action
  746.                 SWSetSpriteMoveTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  747.                 SWSetSpriteFrameTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  748.                 SWSetSpriteFrameRange(srcSpriteP,
  749.                     cicnIdleStart,cicnIdleEnd);
  750.                 break;
  751.             case aJump:
  752.                 // adjust speeds to this action
  753.                 SWSetSpriteMoveTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  754.                 SWSetSpriteFrameTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  755.                 SWSetSpriteFrameRange(srcSpriteP,
  756.                     cicnJumpStart,cicnJumpEnd);
  757.                 break;
  758.             case aJumpAttack:
  759.                 // adjust speeds to this action
  760.                 SWSetSpriteMoveTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  761.                 SWSetSpriteFrameTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  762.                 SWSetSpriteFrameRange(srcSpriteP,
  763.                     cicnJumpAttackStart,cicnJumpAttackEnd);
  764.                 break;
  765.             case aJumpPunch:
  766.                 SWSetSpriteFrameRange(srcSpriteP,
  767.                     cicnJumpPunchStart,cicnJumpPunchEnd);
  768.                 break;
  769.             case aJumpKick:
  770.                 SWSetSpriteFrameRange(srcSpriteP,
  771.                     cicnJumpKickStart,cicnJumpKickEnd);
  772.                 break;
  773.             case aRun:
  774.                 // adjust speeds to this action
  775.                 SWSetSpriteMoveTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  776.                 SWSetSpriteFrameTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  777.                 SWSetSpriteFrameRange(srcSpriteP,
  778.                     cicnRunStart,cicnRunEnd);
  779.                 break;
  780.             case aBlock:
  781.                 SWSetSpriteFrameRange(srcSpriteP,
  782.                     cicnBlockStart,cicnBlockEnd);
  783.                 break;
  784.             case aDuck:
  785.                 SWSetSpriteFrameRange(srcSpriteP,
  786.                     cicnDuckStart,cicnDuckEnd);
  787.                 break;
  788.             case aUppercut:
  789.                 // adjust speeds to this action - 1/3 of normal speed
  790.                 SWSetSpriteMoveTime(srcSpriteP, (3*5*(20-gFrameAdvanceTime-1)));
  791.                 SWSetSpriteFrameTime(srcSpriteP, (3*5*(20-gFrameAdvanceTime-1)));
  792.                 SWSetSpriteFrameRange(srcSpriteP,
  793.                     cicnUppercutStart,cicnUppercutEnd);
  794.                 break;
  795.             case aTaunt:
  796.                 // adjust speeds to this action - 1/5 of normal speed
  797.                 SWSetSpriteMoveTime(srcSpriteP, (5*5*(20-gFrameAdvanceTime-1)));
  798.                 SWSetSpriteFrameTime(srcSpriteP, (5*5*(20-gFrameAdvanceTime-1)));
  799.                 SWSetSpriteFrameRange(srcSpriteP,
  800.                     cicnTauntStart,cicnTauntEnd);
  801.                 break;
  802.             case aShoot:
  803.                 SWSetSpriteFrameRange(srcSpriteP,
  804.                     cicnShootStart,cicnShootEnd);
  805.                 break;
  806.             case aPunch:
  807.                 // adjust speeds to this action
  808.                 SWSetSpriteMoveTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  809.                 SWSetSpriteFrameTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  810.                 SWSetSpriteFrameRange(srcSpriteP,
  811.                     cicnPunchStart,cicnPunchEnd);
  812.                 break;
  813.             case aKick:
  814.                 // adjust speeds to this action
  815.                 SWSetSpriteMoveTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  816.                 SWSetSpriteFrameTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  817.                 SWSetSpriteFrameRange(srcSpriteP,
  818.                     cicnKickStart,cicnKickEnd);
  819.                 break;
  820.             case aGotHit:
  821.                 // adjust speeds to this action
  822.                 SWSetSpriteMoveTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  823.                 //  1/2 of normal speed - FRAMES ONLY
  824.                 SWSetSpriteFrameTime(srcSpriteP, (2*5*(20-gFrameAdvanceTime-1)));
  825.                 SWSetSpriteFrameRange(srcSpriteP,
  826.                     cicnGotHitStart,cicnGotHitEnd);
  827.                 spriteDataPtr[kPreviousAction] = aGotHit;
  828.                 break;
  829.             case aDying:
  830.                 // adjust speeds to this action - 1/3 of normal speed
  831.                 SWSetSpriteMoveTime(srcSpriteP, (3*5*(20-gFrameAdvanceTime-1)));
  832.                 SWSetSpriteFrameTime(srcSpriteP, (3*5*(20-gFrameAdvanceTime-1)));
  833.                 SWSetSpriteFrameRange(srcSpriteP,
  834.                     cicnDyingStart,cicnDyingEnd);
  835.                 break;
  836.             case aRideChair:
  837.                 // adjust speeds to this action
  838.                 SWSetSpriteMoveTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  839.                 SWSetSpriteFrameTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  840.                 SWSetSpriteFrameRange(srcSpriteP,
  841.                     cicnRideChairStart,cicnRideChairEnd);
  842.                 break;
  843.             case aPushChair:
  844.                 // adjust speeds to this action
  845.                 SWSetSpriteMoveTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  846.                 SWSetSpriteFrameTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  847.                 SWSetSpriteFrameRange(srcSpriteP,
  848.                     cicnPushChairStart,cicnPushChairEnd);
  849.                 break;
  850.             case aProjectileIdle: // no adjustment needed
  851.                 break;
  852.             case aProjectileShoot: // no adjustment needed
  853.                 SWSetSpriteFrameRange(srcSpriteP,
  854.                     cicnProjectileStart,cicnProjectileEnd);
  855.                 break;
  856.             case aPostJumpAttack:
  857.                 break;
  858.             default: // in case something really wierd happens!!!
  859.                 spriteDataPtr[kCurrentAction] = aIdle;
  860.                 // adjust speeds to this action
  861.                 SWSetSpriteMoveTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  862.                 SWSetSpriteFrameTime(srcSpriteP, (5*(20-gFrameAdvanceTime-1)));
  863.                 SWSetSpriteFrameRange(srcSpriteP,
  864.                     cicnIdleStart,cicnIdleEnd);
  865.                 break;
  866.         }
  867.     }
  868. }
  869.  
  870. // Which side is sprite on?
  871. Boolean GetSpriteSide(unsigned char *spriteDataPtr)
  872. {
  873.     Point    s1Mid, s2Mid;
  874.     unsigned char side;
  875.     
  876.     s1Mid = GetSpriteMidPoint(player1TopLeft);
  877.     s2Mid = GetSpriteMidPoint(player2TopLeft);
  878.     switch(spriteDataPtr[kSpriteIDNum])
  879.     {
  880.         case kPlayer1Sprite:
  881.         case kComputer1Sprite:
  882.         case kPlayer1ProjectileSprite:
  883.             if(s1Mid.h > s2Mid.h)
  884.                 return (kRightSide);
  885.             else
  886.                 return (kLeftSide);
  887.             break;
  888.         case kPlayer2Sprite:
  889.         case kComputer2Sprite:
  890.         case kPlayer2ProjectileSprite:
  891.             if(s2Mid.h > s1Mid.h)
  892.                 return (kRightSide);
  893.             else
  894.                 return (kLeftSide);
  895.             break;
  896.         default:
  897.             DoError(kUnknownSpriteInGame, TRUE);
  898.             break;
  899.     }
  900. }
  901.     
  902. Point GetSpriteMidPoint(Point spritePoint)
  903. {
  904.     Point    midPt;
  905.     
  906.     midPt.h = spritePoint.h + (gSpriteWidth / 2);
  907.     midPt.v = spritePoint.v + (gSpriteHeight / 2);
  908.     
  909.     return (midPt);
  910. }
  911.  
  912. void DigSpriteGrave(short spriteID, short deathMode)
  913. {
  914.     SpritePtr    deadSpriteP;
  915.     SpriteFilePtr    deadFileP;
  916.     FramePtr newFrameP;
  917.     short    frame, firstDeathFrame, firstMaskDeathFrame, numDeathFrames;
  918.     short    oldResRefNum, curResRefNum;
  919.     OSErr    err;
  920.     Boolean    locked;
  921.     
  922.     switch(spriteID)
  923.     {
  924.         case kPlayer1Sprite:
  925.         case kComputer1Sprite:
  926.             deadSpriteP = &spriteGame.spriteArray[kPlayer1Sprite];
  927.             deadFileP = &gPlayer1File;
  928.             break;
  929.         case kPlayer2Sprite:
  930.         case kComputer2Sprite:
  931.             deadSpriteP = &spriteGame.spriteArray[kPlayer2Sprite];
  932.             deadFileP = &gPlayer2File;
  933.             break;
  934.     }
  935.     // dispose of ALL current frames, since this guy won't be needing them anymore
  936.     // If sprite is locked...
  937.     locked = deadSpriteP->frameArray[0]->isFrameLocked;
  938.     if(locked) // Unlock it.
  939.         SWUnlockSprite(deadSpriteP);
  940.     for (frame = 0; frame < deadSpriteP->numFrames; frame++)
  941.     {
  942.         SWDisposeFrame(deadSpriteP->frameArray[frame]);
  943.     }
  944.     deadSpriteP->numFrames = 0; // sprite should have no frames now.
  945.     // Add death frames...
  946.     switch(deathMode)
  947.     {
  948.         case aDying:
  949.             firstDeathFrame = kFirstDeathResNum;
  950.             firstMaskDeathFrame = firstDeathFrame + kMaskFrameOffset;
  951.             numDeathFrames = 2*kMaxDeathFrames; // 2 = both sides (face left, face right
  952.             break;
  953.         default:
  954.             break;
  955.     }
  956.     // Open required file
  957.     oldResRefNum = CurResFile();
  958.     curResRefNum = HOpenResFile(deadFileP->sfFile.vRefNum,
  959.                 deadFileP->sfFile.parID,deadFileP->sfFile.name, fsRdPerm);
  960.     err = ((ResError()!=noErr) || curResRefNum < 0);
  961.     if (err == noErr) // Here, add the new frames
  962.     {
  963.         UseResFile(curResRefNum);
  964.         for (frame = 0; frame < numDeathFrames; frame++)
  965.         {
  966.             err = SWCreateFrameFromPictResource(&newFrameP, firstDeathFrame + frame,
  967.                     firstMaskDeathFrame + frame, kRegionMask);
  968.             if (err == noErr)
  969.             {
  970.                 err = SWAddFrame(deadSpriteP, newFrameP);
  971.             }
  972.             else
  973.                 break;
  974.         }
  975.     }
  976.     CloseResFile(curResRefNum);
  977.     UseResFile(oldResRefNum);
  978.     if(err != noErr)
  979.         DoError(kCouldNotCreateSprites, TRUE);
  980.     else
  981.     {
  982.         SWSetSpriteFrameRange(deadSpriteP, 0, numDeathFrames - 1);
  983.         if(locked) // Lock it back up.
  984.             SWLockSprite(deadSpriteP);
  985.         SWSetCurrentFrame(deadSpriteP, deadSpriteP->frameArray[0]); // Set to 1st death frame
  986.     }
  987. }