home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / SpriteWorld 2.2 / SpriteWorld Examples / Split-Screen Scrolling / Sprite Stuff.c < prev    next >
Encoding:
Text File  |  1999-01-12  |  20.9 KB  |  669 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. // Sprite Stuff.c
  3. ///--------------------------------------------------------------------------------------
  4.  
  5. #include <SWIncludes.h>
  6. #include <SWGameUtils.h>
  7. #include "SWApplication.h"
  8.  
  9. #include "Split-Screen Demo.h"
  10. #include "Sprite Stuff.h"
  11.  
  12.  
  13.     // Pointers to the original sprites which we clone
  14.     // when we want to add a sprite to the animation.
  15.     // We never add these sprites themselves to the animation.
  16.     
  17. SpritePtr    gMasterTank1SpriteP,
  18.             gMasterTank2SpriteP,
  19.             gMasterBulletSpriteP,
  20.             gMasterGunPowerUpSpriteP;
  21.             
  22.  
  23. extern WindowPtr            gWindowP;
  24. extern SpriteWorldPtr        gMasterSpriteWorldP, gCloneSpriteWorldP;
  25. extern SpriteLayerPtr        gTankSpriteLayerP, gBulletSpriteLayerP, gPowerUpSpriteLayerP;
  26. extern TileMapStructPtr        gTileMapStructP;
  27. extern TileMapPtr            gTileMap;
  28. extern Rect                    gMasterRect, gCloneRect;
  29. extern Rect                    gMoveBoundsRect;
  30. extern DrawProcPtr            gSpriteMaskDrawProc;
  31. extern RgnHandle            gTempRgn;                    // Used by TankHitDrawProc
  32.  
  33. extern KeyStruct             gTank1Keys, gTank2Keys;
  34.  
  35.  
  36. ///--------------------------------------------------------------------------------------
  37. // LoadSprites
  38. ///--------------------------------------------------------------------------------------
  39.  
  40. void    LoadSprites( void )
  41. {
  42.     OSErr            err;
  43.     
  44.         // Load gMasterTank1SpriteP
  45.     err = SWCreateSpriteFromSinglePictXY(gMasterSpriteWorldP, &gMasterTank1SpriteP,
  46.             NULL, 128, 128, 50, 50, 0, 0, 18, kFatMask);
  47.     SetUpSprite(gMasterTank1SpriteP, err);
  48.     
  49.         // Load gMasterTank2SpriteP
  50.     err = SWCreateSpriteFromSinglePictXY(gMasterSpriteWorldP, &gMasterTank2SpriteP,
  51.             NULL, 129, 129, 50, 50, 0, 0, 18, kFatMask);
  52.     SetUpSprite(gMasterTank2SpriteP, err);
  53.     
  54.         // Load gMasterBulletSpriteP
  55.     err = SWCreateSpriteFromCicnResource(gMasterSpriteWorldP, &gMasterBulletSpriteP, 
  56.             NULL, 128, 1, kFatMask);
  57.     SetUpSprite(gMasterBulletSpriteP, err);
  58.     SWSetFrameHotSpot(gMasterBulletSpriteP->curFrameP, kHalfBulletSize, kHalfBulletSize);
  59.     
  60.         // Load gMasterGunPowerUpSpriteP
  61.     err = SWCreateSpriteFromCicnResource(gMasterSpriteWorldP, &gMasterGunPowerUpSpriteP, 
  62.             NULL, 130, 1, kFatMask);
  63.     SetUpSprite(gMasterGunPowerUpSpriteP, err);
  64. }
  65.  
  66.  
  67. ///--------------------------------------------------------------------------------------
  68. // DisposeSprites - we must dispose of each sprite we loaded, since they are not
  69. // added to the SpriteWorld, and therefore will not be disposed with the SpriteWorld.
  70. ///--------------------------------------------------------------------------------------
  71.  
  72. void    DisposeSprites( void )
  73. {
  74.     SWDisposeSprite(&gMasterTank1SpriteP);
  75.     SWDisposeSprite(&gMasterTank2SpriteP);
  76.     SWDisposeSprite(&gMasterBulletSpriteP);
  77. }
  78.  
  79.  
  80. ///--------------------------------------------------------------------------------------
  81. // SetUpSprite - makes the LoadSprites code a little cleaner.
  82. ///--------------------------------------------------------------------------------------
  83.  
  84. void    SetUpSprite(SpritePtr mySpriteP, OSErr err)
  85. {
  86.     FatalError(err);
  87.     
  88.     if (gMasterSpriteWorldP->pixelDepth == 8)
  89.         SWCompileSprite(mySpriteP);
  90.     
  91.     SWSetSpriteMoveBounds(mySpriteP, &gMasterSpriteWorldP->scrollRectMoveBounds);
  92.     SWSetSpriteDrawProc(mySpriteP, gSpriteMaskDrawProc);
  93.     SWLockSprite(mySpriteP);
  94. }
  95.  
  96.  
  97. ///--------------------------------------------------------------------------------------
  98. // NewTankSprite - clone the master sprite and add the clone to the animation.
  99. // Also allocate memory for the custom sprite structure.
  100. ///--------------------------------------------------------------------------------------
  101.  
  102. SpritePtr    NewTankSprite( short tankType )
  103. {
  104.     TankStructPtr    tankStructP;
  105.     SpritePtr        tankSpriteP;
  106.     OSErr            err;
  107.     
  108.         // Allocate memory for the TankStruct
  109.     tankStructP = (TankStructPtr)NewPtr(sizeof(TankStruct));
  110.     FatalError( MemError() );
  111.     
  112.     if (tankType == kPlayer1)
  113.         err = SWCloneSprite(gMasterTank1SpriteP, &tankSpriteP, tankStructP);
  114.     else
  115.         err = SWCloneSprite(gMasterTank2SpriteP, &tankSpriteP, tankStructP);
  116.     FatalError(err);
  117.     
  118.     SWAddSprite(gTankSpriteLayerP, tankSpriteP);
  119.     SWSetSpriteMoveProc(tankSpriteP, TankSpriteMoveProc);
  120.     
  121.     if (tankType == kPlayer1)
  122.         SWSetCurrentFrameIndex(tankSpriteP, kTankRightFrameIndex);
  123.     else
  124.         SWSetCurrentFrameIndex(tankSpriteP, kTankLeftFrameIndex);
  125.     
  126.     tankStructP->tankType = tankType;
  127.     tankStructP->numBulletsOnScreen = 0;
  128.     tankStructP->nextShotDelay = 0;
  129.     tankStructP->gunType = kNormalGun;
  130.     tankStructP->damage = 0;
  131.     tankStructP->canShoot = true;
  132.     tankStructP->wasHit = false;
  133.     SW_SET_RECT(tankStructP->insetRect, 10, 10, 10, 10);
  134.     
  135.     return tankSpriteP;
  136. }
  137.  
  138.  
  139. ///--------------------------------------------------------------------------------------
  140. // NewBulletSprite - clone the master sprite and add the clone to the animation.
  141. // Also allocate memory for the custom sprite structure.
  142. ///--------------------------------------------------------------------------------------
  143.  
  144. SpritePtr    NewBulletSprite( void )
  145. {
  146.     BulletStructPtr    bulletStructP;
  147.     SpritePtr        bulletSpriteP;
  148.     OSErr            err;
  149.     
  150.         // Allocate memory for the BulletStruct
  151.     bulletStructP = (BulletStructPtr)NewPtr(sizeof(BulletStruct));
  152.     FatalError( MemError() );
  153.  
  154.     err = SWCloneSprite(gMasterBulletSpriteP, &bulletSpriteP, bulletStructP);
  155.     FatalError(err);
  156.     
  157.     SWAddSprite(gBulletSpriteLayerP, bulletSpriteP);
  158.     SWSetSpriteMoveProc(bulletSpriteP, BulletSpriteMoveProc);
  159.     SWSetSpriteCollideProc(bulletSpriteP, BulletSpriteCollideProc);
  160.     
  161.     bulletStructP->numMovesLeft = 30;
  162.  
  163.     return bulletSpriteP;
  164. }
  165.  
  166.  
  167. ///--------------------------------------------------------------------------------------
  168. // NewPowerUpSprite - clone the master sprite and add the clone to the animation.
  169. ///--------------------------------------------------------------------------------------
  170.  
  171. SpritePtr    NewPowerUpSprite( GunType gunType )
  172. {
  173.     SpritePtr        powerUpSpriteP;
  174.     OSErr            err;
  175.  
  176.     err = SWCloneSprite(gMasterGunPowerUpSpriteP, &powerUpSpriteP, NULL);
  177.     FatalError(err);
  178.     
  179.     SWAddSprite(gPowerUpSpriteLayerP, powerUpSpriteP);
  180.     SWSetSpriteCollideProc(powerUpSpriteP, PowerUpCollideProc);
  181.     
  182.     powerUpSpriteP->userData = gunType;
  183.  
  184.     return powerUpSpriteP;
  185. }
  186.  
  187.  
  188. ///--------------------------------------------------------------------------------------
  189. // TankSpriteMoveProc
  190. ///--------------------------------------------------------------------------------------
  191.  
  192. SW_FUNC void TankSpriteMoveProc(SpritePtr tankSpriteP)
  193. {
  194.     TankStructPtr        tankStructP = (TankStructPtr)tankSpriteP;
  195.     TankDirectionType    currentDirection;
  196.     KeyStruct            *tankKeysP;
  197.     
  198.         // Determine whether to use keys for player 1 or player 2
  199.     if (tankStructP->tankType == kPlayer1)
  200.         tankKeysP = &gTank1Keys;
  201.     else
  202.         tankKeysP = &gTank2Keys;
  203.     
  204.     
  205.         // If the tank was just hit and flashed white, change back to normal drawProc
  206.     if (tankStructP->wasHit)
  207.     {
  208.         tankStructP->wasHit = false;
  209.         tankSpriteP->needsToBeDrawn = true;
  210.         SWSetSpriteDrawProc(tankSpriteP, gSpriteMaskDrawProc);
  211.     }
  212.     
  213.     
  214.         // Figure out which direction we're going
  215.     if (tankKeysP->up)
  216.     {
  217.         if (tankKeysP->right)
  218.             currentDirection = kTankUpRightFrameIndex;
  219.         else if (tankKeysP->left)
  220.             currentDirection = kTankUpLeftFrameIndex;
  221.         else
  222.             currentDirection = kTankUpFrameIndex;
  223.     }
  224.     else if (tankKeysP->down)
  225.     {
  226.         if (tankKeysP->right)
  227.             currentDirection = kTankDownRightFrameIndex;
  228.         else if (tankKeysP->left)
  229.             currentDirection = kTankDownLeftFrameIndex;
  230.         else
  231.             currentDirection = kTankDownFrameIndex;
  232.     }
  233.     else
  234.     {
  235.         if (tankKeysP->right)
  236.             currentDirection = kTankRightFrameIndex;
  237.         else if (tankKeysP->left)
  238.             currentDirection = kTankLeftFrameIndex;
  239.         else 
  240.             currentDirection = kNoDirection;
  241.     }
  242.     
  243.     
  244.         // Set the current frame index, and store current direction
  245.     if (currentDirection != kNoDirection)
  246.     {
  247.         SWSetCurrentFrameIndex(tankSpriteP, currentDirection);
  248.     }
  249.     
  250.     
  251.         // Move the tank
  252.     switch (currentDirection)
  253.     {
  254.         case kTankUpFrameIndex:
  255.             tankSpriteP->horizMoveDelta = 0;
  256.             tankSpriteP->vertMoveDelta = -kTankSpeed;
  257.             break;
  258.         case kTankUpRightFrameIndex:
  259.             tankSpriteP->horizMoveDelta = kTankSpeed/1.5;
  260.             tankSpriteP->vertMoveDelta = -kTankSpeed/1.5;
  261.             break;
  262.         case kTankRightFrameIndex:
  263.             tankSpriteP->horizMoveDelta = kTankSpeed;
  264.             tankSpriteP->vertMoveDelta = 0;
  265.             break;
  266.         case kTankDownRightFrameIndex:
  267.             tankSpriteP->horizMoveDelta = kTankSpeed/1.5;
  268.             tankSpriteP->vertMoveDelta = kTankSpeed/1.5;
  269.             break;
  270.         case kTankDownFrameIndex:
  271.             tankSpriteP->horizMoveDelta = 0;
  272.             tankSpriteP->vertMoveDelta = kTankSpeed;
  273.             break;
  274.         case kTankDownLeftFrameIndex:
  275.             tankSpriteP->horizMoveDelta = -kTankSpeed/1.5;
  276.             tankSpriteP->vertMoveDelta = kTankSpeed/1.5;
  277.             break;
  278.         case kTankLeftFrameIndex:
  279.             tankSpriteP->horizMoveDelta = -kTankSpeed;
  280.             tankSpriteP->vertMoveDelta = 0;
  281.             break;
  282.         case kTankUpLeftFrameIndex:
  283.             tankSpriteP->horizMoveDelta = -kTankSpeed/1.5;
  284.             tankSpriteP->vertMoveDelta = -kTankSpeed/1.5;
  285.             break;
  286.         default:
  287.             tankSpriteP->horizMoveDelta = 0;
  288.             tankSpriteP->vertMoveDelta = 0;
  289.             break;
  290.     }
  291.     
  292.     
  293.             // Slow the tank down if it is in contact with mud
  294.     if ( SWCheckSpriteWithTiles(gMasterSpriteWorldP, tankSpriteP, kSWEntireSprite,
  295.             &tankStructP->insetRect, 0, 0, kMudTile, kMudTile, false) )
  296.     {
  297.         tankSpriteP->horizMoveDelta /= 2;
  298.         tankSpriteP->vertMoveDelta /= 2;
  299.     }
  300.     
  301.     
  302.     tankSpriteP->destFrameRect.top += tankSpriteP->vertMoveDelta;
  303.     tankSpriteP->destFrameRect.bottom += tankSpriteP->vertMoveDelta;
  304.  
  305.  
  306.         // Check for collisions with walls vertically
  307.     if (tankSpriteP->vertMoveDelta > 0)            // Moving down
  308.     {
  309.         if ( SWCheckSpriteWithTiles(gMasterSpriteWorldP, tankSpriteP, kSWBottomSide, 
  310.             &tankStructP->insetRect, 0, 0, kFirstWallTile, kLastWallTile, true) )
  311.         {
  312.             tankSpriteP->vertMoveDelta = 0;
  313.         }
  314.     }
  315.     else if (tankSpriteP->vertMoveDelta < 0)        // Moving up
  316.     {
  317.         if ( SWCheckSpriteWithTiles(gMasterSpriteWorldP, tankSpriteP, kSWTopSide,  
  318.             &tankStructP->insetRect, 0, 0, kFirstWallTile, kLastWallTile, true) )
  319.         {
  320.             tankSpriteP->vertMoveDelta = 0;
  321.         }
  322.     }
  323.     
  324.  
  325.     tankSpriteP->destFrameRect.right += tankSpriteP->horizMoveDelta;
  326.     tankSpriteP->destFrameRect.left += tankSpriteP->horizMoveDelta;
  327.     
  328.             // Check for collisions with walls horizontally
  329.     if (tankSpriteP->horizMoveDelta > 0)            // Moving right
  330.     {
  331.         if ( SWCheckSpriteWithTiles(gMasterSpriteWorldP, tankSpriteP, kSWRightSide,  
  332.             &tankStructP->insetRect, 0, 0, kFirstWallTile, kLastWallTile, true) )
  333.         {
  334.             tankSpriteP->horizMoveDelta = 0;
  335.         }
  336.     }
  337.     else if (tankSpriteP->horizMoveDelta < 0)        // Moving left
  338.     {
  339.         if ( SWCheckSpriteWithTiles(gMasterSpriteWorldP, tankSpriteP, kSWLeftSide,
  340.             &tankStructP->insetRect, 0, 0, kFirstWallTile, kLastWallTile, true) )
  341.         {
  342.             tankSpriteP->horizMoveDelta = 0;
  343.         }
  344.     }
  345.     
  346.             // Damage the tank if it hits lava
  347.     if ( SWCheckSpriteWithTiles(gMasterSpriteWorldP, tankSpriteP, kSWEntireSprite,
  348.             &tankStructP->insetRect, 0, 0, kFirstLavaTile, kFirstLavaTile, false) )
  349.     {
  350.         DamageTank(tankSpriteP, 4);
  351.     }
  352.     
  353.     
  354.     tankSpriteP->needsToBeDrawn = true;
  355.     
  356.     
  357.     if (tankKeysP->shoot)
  358.     {
  359.         if (tankStructP->canShoot)
  360.         {
  361.             tankStructP->canShoot = false;
  362.         
  363.             if ( (tankStructP->numBulletsOnScreen < kMaxNumBullets) || tankStructP->gunType == kMachineGun)
  364.                 ShootBullet(tankSpriteP);
  365.         }
  366.         else if (tankStructP->gunType == kMachineGun)
  367.         {
  368.             tankStructP->nextShotDelay++;
  369.             if (tankStructP->nextShotDelay >= kNextShotDelay)
  370.             {
  371.                 tankStructP->nextShotDelay = 0;
  372.                 tankStructP->canShoot = true;
  373.             }
  374.         }
  375.     }
  376.     else if (tankStructP->gunType == kMachineGun && tankStructP->canShoot == false)
  377.     {
  378.         tankStructP->nextShotDelay++;
  379.         if (tankStructP->nextShotDelay >= kNextShotDelay)
  380.         {
  381.             tankStructP->nextShotDelay = 0;
  382.             tankStructP->canShoot = true;
  383.         }
  384.     }
  385.     else
  386.     {
  387.         tankStructP->canShoot = true;
  388.     }    
  389. }
  390.  
  391.  
  392. ///--------------------------------------------------------------------------------------
  393. //  BulletSpriteMoveProc
  394. ///--------------------------------------------------------------------------------------
  395.  
  396. SW_FUNC void BulletSpriteMoveProc(SpritePtr bulletSpriteP)
  397. {
  398.     BulletStructPtr    bulletStructP = (BulletStructPtr)bulletSpriteP;
  399.     short    tileRow, tileCol, tileID;
  400.     
  401.         // Don't move the sprite if it was just now created
  402.         // and hasn't even been drawn yet.
  403.     if (bulletSpriteP->needsToBeDrawn)
  404.         return;
  405.     
  406.     
  407.     tileID = SWReturnTileUnderPixel(gMasterSpriteWorldP, 0,
  408.         bulletSpriteP->destFrameRect.left + kHalfBulletSize,
  409.         bulletSpriteP->destFrameRect.top + kHalfBulletSize);
  410.     
  411.     if ( tileID >= kFirstWallTile && tileID <= kLastWallTile )
  412.     {
  413.             // Remove the bullet - it hit a wall
  414.         bulletStructP->parentStructP->numBulletsOnScreen--;
  415.         SWRemoveSpriteFromAnimation(gMasterSpriteWorldP, bulletSpriteP, true);
  416.     
  417.             // Convert pixel coordinates to tileMap coordinates
  418.         tileRow = (bulletSpriteP->destFrameRect.top + kHalfBulletSize) / kTileHeight;
  419.         tileCol = (bulletSpriteP->destFrameRect.left + kHalfBulletSize) / kTileWidth;
  420.         
  421.             // Damage the wall
  422.         tileID += kWallDamageOffset;
  423.         if (tileID > kLastWallTile)
  424.             tileID = kMainFloorTile;
  425.         
  426.             // Change the tile in *both* SpriteWorlds.
  427.         SWDrawTile(gMasterSpriteWorldP, 0, tileRow, tileCol, tileID);
  428.         SWDrawTile(gCloneSpriteWorldP, 0, tileRow, tileCol, tileID);
  429.     }
  430.     else if (bulletStructP->numMovesLeft-- <= 0)
  431.     {
  432.             // Remove the bullet - it has moved past its range
  433.         bulletStructP->parentStructP->numBulletsOnScreen--;
  434.         SWRemoveSpriteFromAnimation(gMasterSpriteWorldP, bulletSpriteP, true);
  435.     }
  436.     
  437.     SWOffsetSprite(bulletSpriteP, bulletSpriteP->horizMoveDelta, bulletSpriteP->vertMoveDelta);
  438. }
  439.  
  440.  
  441. ///--------------------------------------------------------------------------------------
  442. //  DeadTankFrameProc
  443. ///--------------------------------------------------------------------------------------
  444.  
  445. SW_FUNC void DeadTankFrameProc(SpritePtr tankSpriteP, FramePtr curFrameP, long *frameIndex)
  446. {
  447.     #pragma         unused(curFrameP)    // Let CodeWarrior know this variable is unused
  448.     TankStructPtr    tankStructP = (TankStructPtr)tankSpriteP;
  449.     
  450.     if (*frameIndex < kLastTankBlowUpFrame)
  451.         *frameIndex++;
  452.     else
  453.     {
  454.             // Make the tank as good as new
  455.         SWSetCurrentFrameIndex(tankSpriteP, kTankRightFrameIndex);
  456.         tankStructP->gunType = kNormalGun;
  457.         tankStructP->damage = 0;
  458.         tankStructP->wasHit = false;
  459.         SWSetSpriteDrawProc(tankSpriteP, gSpriteMaskDrawProc);
  460.         SWSetSpriteFrameProc(tankSpriteP, NULL);
  461.         SWSetSpriteFrameTime(tankSpriteP, -1);
  462.         SWSetSpriteMoveProc(tankSpriteP, TankSpriteMoveProc);
  463.         
  464.         if (tankStructP->tankType == kPlayer1)
  465.             SWMoveSprite(tankSpriteP, gMoveBoundsRect.left + 120, gMoveBoundsRect.top + 100);
  466.         else 
  467.             SWMoveSprite(tankSpriteP, gMoveBoundsRect.right-140, gMoveBoundsRect.bottom-140);
  468.     }
  469. }
  470.  
  471.  
  472. ///--------------------------------------------------------------------------------------
  473. // ShootBullet
  474. ///--------------------------------------------------------------------------------------
  475.  
  476. void    ShootBullet(SpritePtr tankSpriteP)
  477. {
  478.     TankStructPtr    tankStructP = (TankStructPtr)tankSpriteP;
  479.     SpritePtr        newBulletSpriteP;
  480.         
  481.     newBulletSpriteP = NewBulletSprite();
  482.     ((BulletStructPtr)newBulletSpriteP)->parentStructP = tankStructP;
  483.     tankStructP->numBulletsOnScreen++;
  484.     
  485.     SWSetSpriteLocation(newBulletSpriteP, 
  486.             tankSpriteP->destFrameRect.left + kHalfTankWidth,
  487.             tankSpriteP->destFrameRect.top + kHalfTankHeight);
  488.     
  489.     switch (tankSpriteP->curFrameIndex)
  490.     {
  491.         case kTankUpFrameIndex:
  492.             SWSetSpriteMoveDelta(newBulletSpriteP, 0, -kBulletSpeed);
  493.             SWOffsetSprite(newBulletSpriteP, 0, -kHalfTankHeight-5);
  494.             break;
  495.         case kTankUpRightFrameIndex:
  496.             SWSetSpriteMoveDelta(newBulletSpriteP, kBulletSpeed, -kBulletSpeed);
  497.             SWOffsetSprite(newBulletSpriteP, kHalfTankWidth+5, -kHalfTankHeight-5);
  498.             break;
  499.         case kTankRightFrameIndex:
  500.             SWSetSpriteMoveDelta(newBulletSpriteP, kBulletSpeed, 0);
  501.             SWOffsetSprite(newBulletSpriteP, kHalfTankWidth+5, 0);
  502.             break;
  503.         case kTankDownRightFrameIndex:
  504.             SWSetSpriteMoveDelta(newBulletSpriteP, kBulletSpeed, kBulletSpeed);
  505.             SWOffsetSprite(newBulletSpriteP, kHalfTankWidth+5, kHalfTankHeight+5);
  506.             break;
  507.         case kTankDownFrameIndex:
  508.             SWSetSpriteMoveDelta(newBulletSpriteP, 0, kBulletSpeed);
  509.             SWOffsetSprite(newBulletSpriteP, 0, kHalfTankHeight+5);
  510.             break;
  511.         case kTankDownLeftFrameIndex:
  512.             SWSetSpriteMoveDelta(newBulletSpriteP, -kBulletSpeed, kBulletSpeed);
  513.             SWOffsetSprite(newBulletSpriteP, -kHalfTankWidth-5, kHalfTankHeight+5);
  514.             break;
  515.         case kTankLeftFrameIndex:
  516.             SWSetSpriteMoveDelta(newBulletSpriteP, -kBulletSpeed, 0);
  517.             SWOffsetSprite(newBulletSpriteP, -kHalfTankWidth-5, 0);
  518.             break;
  519.         case kTankUpLeftFrameIndex:
  520.             SWSetSpriteMoveDelta(newBulletSpriteP, -kBulletSpeed, -kBulletSpeed);
  521.             SWOffsetSprite(newBulletSpriteP, -kHalfTankWidth-5, -kHalfTankHeight-5);
  522.             break;
  523.         default:
  524.             break;
  525.     }
  526. }
  527.  
  528.  
  529. ///--------------------------------------------------------------------------------------
  530. //   BulletSpriteCollideProc
  531. ///--------------------------------------------------------------------------------------
  532.  
  533. SW_FUNC void BulletSpriteCollideProc(
  534.     SpritePtr    bulletSpriteP,
  535.     SpritePtr    tankSpriteP,
  536.     Rect*        sectRect)
  537. {
  538.     #pragma            unused(sectRect)    // Let CodeWarrior know this variable is unused
  539.     Boolean            hasCollided;
  540.     TankStructPtr    tankStructP = (TankStructPtr)tankSpriteP;
  541.     
  542.         // Exit if the tank is in the process of being blown up
  543.     if (tankStructP->damage > kMaximumDamage)
  544.         return;
  545.     
  546.         // See if the actual sprite images collided
  547.     if (gMasterSpriteWorldP->pixelDepth == 8)
  548.         hasCollided = SWPixelCollision(bulletSpriteP, tankSpriteP);    // Faster, but 8-bit only
  549.     else
  550.         hasCollided = SWRegionCollision(bulletSpriteP, tankSpriteP); // Works in any depth
  551.  
  552.     if (hasCollided)
  553.     {
  554.             // Remove the bullet
  555.         ((BulletStructPtr)bulletSpriteP)->parentStructP->numBulletsOnScreen--;
  556.         SWRemoveSpriteFromAnimation(gMasterSpriteWorldP, bulletSpriteP, true);
  557.         
  558.         DamageTank(tankSpriteP, 10);
  559.     }
  560. }
  561.  
  562.  
  563. ///--------------------------------------------------------------------------------------
  564. //   PowerUpCollideProc
  565. ///--------------------------------------------------------------------------------------
  566.  
  567. SW_FUNC void PowerUpCollideProc(
  568.     SpritePtr    powerUpSpriteP,
  569.     SpritePtr    tankSpriteP,
  570.     Rect*        sectRect)
  571. {
  572.     #pragma            unused(sectRect)    // Let CodeWarrior know this variable is unused
  573.     Boolean            hasCollided;
  574.     TankStructPtr    tankStructP = (TankStructPtr)tankSpriteP;
  575.     
  576.  
  577.         // See if the actual sprite images collided
  578.     if (gMasterSpriteWorldP->pixelDepth == 8)
  579.         hasCollided = SWPixelCollision(powerUpSpriteP, tankSpriteP); // Faster, but 8-bit only
  580.     else
  581.         hasCollided = SWRegionCollision(powerUpSpriteP, tankSpriteP); // Works in any depth
  582.  
  583.     if (hasCollided)
  584.     {
  585.             // Pick it up only if we don't already have it
  586.         if (tankStructP->gunType != powerUpSpriteP->userData)
  587.         {
  588.             tankStructP->gunType = powerUpSpriteP->userData;
  589.             
  590.                 // Remove the power-up Sprite
  591.             SWRemoveSpriteFromAnimation(gMasterSpriteWorldP, powerUpSpriteP, true);
  592.         }
  593.     }
  594. }
  595.  
  596.  
  597. ///--------------------------------------------------------------------------------------
  598. //   DamageTank
  599. ///--------------------------------------------------------------------------------------
  600.  
  601. void    DamageTank( SpritePtr tankSpriteP, short damageAmount )
  602. {
  603.     TankStructPtr    tankStructP = (TankStructPtr)tankSpriteP;
  604.     
  605.         // Increase the tank's damage
  606.     tankStructP->damage += damageAmount;
  607.     if (tankStructP->damage > kMaximumDamage)
  608.     {
  609.             // Kill the tank
  610.         SWSetSpriteMoveProc(tankSpriteP, NULL);    // A dead tank can't move.
  611.         SWSetSpriteFrameProc(tankSpriteP, DeadTankFrameProc); // Blow it up!
  612.         SWSetSpriteFrameTime(tankSpriteP, 1000/10);    // Show animation at 10fps
  613. //        SWSetCurrentFrameIndex(tankSpriteP, kFirstTankBlowUpFrame-1);
  614.     }
  615.     else
  616.     {
  617.             // Make the tank flash yellow
  618.         tankStructP->wasHit = true;
  619.         tankSpriteP->needsToBeDrawn = true;
  620.         SWSetSpriteDrawProc(tankSpriteP, TankHitDrawProc);
  621.     }
  622. }
  623.  
  624.  
  625.  
  626. ///--------------------------------------------------------------------------------------
  627. //    TankHitDrawProc - Note: this DrawProc requires the sprite to have a maskRgn. If you
  628. //    look at NewSprite(), you'll see that the tank sprite was loaded with kFatMask, 
  629. //    instead of kPixelMask, so this drawProc could be used.
  630. //
  631. //    Note also that since PaintRgn gives us no option to clip our drawing to the dstRect,
  632. //    we turn the dstRect into a region and "clip" the frame's region to the dstRect
  633. //    region with SectRgn. An alternative would be to call ClipRect to set the current
  634. //    clipping region to dstRect before making the call to PaintRgn. (Remembering to 
  635. //    restore the old clipping region when done). This clipping must be done because
  636. //    sometimes (especially in scrolling games) only part of a sprite needs to be drawn,
  637. //    and drawing outside the dstRect could cause problems.
  638. ///--------------------------------------------------------------------------------------
  639.  
  640. SW_FUNC void TankHitDrawProc(
  641.     FramePtr srcFrameP,
  642.     FramePtr dstFrameP,
  643.     Rect* srcRect,
  644.     Rect* dstRect)
  645. {
  646.     #pragma unused(dstFrameP)    // Let CodeWarrior know this variable is unused
  647.     
  648.     if (srcFrameP->maskRgn != NULL)
  649.     {
  650.         Rect rgnRect = (**srcFrameP->maskRgn).rgnBBox;
  651.  
  652.             // move the mask region to the sprite location
  653.         OffsetRgn(srcFrameP->maskRgn,
  654.             (dstRect->left - (srcRect->left - srcFrameP->frameRect.left) - rgnRect.left) 
  655.             + srcFrameP->offsetPoint.h,
  656.             (dstRect->top - (srcRect->top - srcFrameP->frameRect.top) - rgnRect.top)
  657.             + srcFrameP->offsetPoint.v);
  658.         
  659.             // Here we "clip" the srcFrameP->maskRgn with the dstRect.
  660.         RectRgn(gTempRgn, dstRect);
  661.         SectRgn(gTempRgn, srcFrameP->maskRgn, gTempRgn);
  662.         
  663.         ForeColor(yellowColor);
  664.         PaintRgn(gTempRgn);
  665.         ForeColor(blackColor);
  666.     }
  667. }
  668.  
  669.