home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / SpriteWorld 2.2 / SpriteWorld Examples / SimpleBreakOut / SimpleBreakOut.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-19  |  16.2 KB  |  596 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. // SimpleBreakOut.c
  3. //
  4. // Portions are Copyright © 1993 Tony Myles, All rights reserved worldwide.
  5. //
  6. // Description: This is a very basic breakout type game that demonstrates
  7. // SpriteWorld's efficient handling of inactive sprites.
  8. ///--------------------------------------------------------------------------------------
  9.  
  10.  
  11. #include <SWIncludes.h>            // Automatically include all SpriteWorld.h files
  12. #include <SWGameUtils.h>
  13.  
  14. #include "SWApplication.h"
  15. #include "SimpleBreakOut.h"
  16.  
  17.  
  18.  
  19. #define kMaxFPS                    0                // Set to 0 for maximum speed
  20. #define kSyncToVBL                true            // Sync animation to VBL?
  21.  
  22.  
  23. enum
  24. {
  25.     kBallHorizDelta = 5,
  26.     kBallVertDelta = 5,
  27.     kNumberOfBrickColumns = 10,
  28.     kNumberOfBrickRows = 5,
  29.     kTotalNumberOfBricks = (kNumberOfBrickColumns * kNumberOfBrickRows),
  30.     kBrickCIconID = 129,
  31.     kBreakBallCIconID = 130,
  32.     kPaddleCIconID = 131
  33. };
  34.  
  35.  
  36.  
  37. Point        oldPoint, newPoint;            // Mouse variables used for moving paddle
  38. short        gBrickNum;
  39.  
  40.  
  41. ///--------------------------------------------------------------------------------------
  42. // main
  43. ///--------------------------------------------------------------------------------------
  44.  
  45. void main(void)
  46. {
  47.     WindowPtr    myWindowP = NULL;
  48.     Rect        windRect;
  49.     
  50.     
  51.     Initialize(kNumberOfMoreMastersCalls);
  52.     
  53.     if (!SWHasSystem7())
  54.         CantRunOnThisMachine();
  55.  
  56.  
  57.         // Create and set up the window
  58.     myWindowP = GetNewCWindow(kWindowResID, NULL, (WindowPtr)-1L);
  59.  
  60.     if (myWindowP != NULL)
  61.     {
  62.             // Center window in screen
  63.         windRect = myWindowP->portRect;
  64.         CenterRect(&windRect, &qd.screenBits.bounds);
  65.         MoveWindow(myWindowP, windRect.left, windRect.top, false);
  66.         
  67.         ShowWindow(myWindowP);
  68.         SetPort(myWindowP);
  69.     }
  70.     else
  71.         CantFindResource();
  72.     
  73.  
  74.     PerformSimpleAnimation((CWindowPtr)myWindowP);
  75. }
  76.  
  77.  
  78. ///--------------------------------------------------------------------------------------
  79. // PerformSimpleAnimation
  80. ///--------------------------------------------------------------------------------------
  81.  
  82. void PerformSimpleAnimation(CWindowPtr srcWindowP)
  83. {
  84.     OSErr                    err;
  85.     PixPatHandle        pixPatH;
  86.     
  87.     SpriteWorldPtr        spriteWorldP;
  88.     SpriteLayerPtr        brickLayerP;
  89.     SpriteLayerPtr        ballLayerP;
  90.     SpriteLayerPtr        paddleLayerP;
  91.     SpritePtr            brickSpriteArray[kTotalNumberOfBricks];
  92.     SpritePtr            ballSpriteP;
  93.     SpritePtr            paddleSpriteP;
  94.     
  95.     short        horizOffset, vertOffset, brickHoriz, brickVert, col, row, n;
  96.     Rect        moveBoundsRect;
  97.  
  98.  
  99.     SetPort((GrafPtr)srcWindowP);
  100.     SetCursor(*GetCursor(watchCursor));
  101.  
  102.  
  103.     //
  104.     // STEP #1: initialize the sprite world package
  105.     //
  106.  
  107.     err = SWEnterSpriteWorld();
  108.     FatalError(err);
  109.  
  110.  
  111.     //
  112.     // STEP #2: create the various pieces that we need
  113.     //
  114.  
  115.         // create the sprite world
  116.     err = SWCreateSpriteWorldFromWindow(&spriteWorldP, srcWindowP, NULL, NULL, 0);
  117.     FatalError(err);
  118.  
  119.         // create the brick layer
  120.     err = SWCreateSpriteLayer(&brickLayerP);
  121.     FatalError(err);
  122.  
  123.         // create the ball layer
  124.     err = SWCreateSpriteLayer(&ballLayerP);
  125.     FatalError(err);
  126.  
  127.         // create the paddle layer
  128.     err = SWCreateSpriteLayer(&paddleLayerP);
  129.     FatalError(err);
  130.  
  131.         // Create the first brick sprite
  132.     err = SWCreateSpriteFromCicnResource(spriteWorldP, &(brickSpriteArray[0]), NULL, 
  133.                 kBrickCIconID, 1, kNoMask);
  134.  
  135.         // Clone the other brick sprites off the first one
  136.     for (gBrickNum = 1; gBrickNum < kTotalNumberOfBricks; gBrickNum++)
  137.     {
  138.         err = SWCloneSprite(brickSpriteArray[0], &brickSpriteArray[gBrickNum], NULL);
  139.         FatalError(err);
  140.     }
  141.  
  142.         // create ball sprite
  143.     err = SWCreateSpriteFromCicnResource(spriteWorldP, &ballSpriteP, NULL, 
  144.                 kBreakBallCIconID, 1, kFatMask);
  145.     FatalError(err);
  146.  
  147.         // create paddle sprite
  148.     err = SWCreateSpriteFromCicnResource(spriteWorldP, &paddleSpriteP, NULL, 
  149.                 kPaddleCIconID, 1, kFatMask);
  150.     FatalError(err);
  151.  
  152.  
  153.  
  154.     //
  155.     // STEP #3: put the pieces together (must be done BEFORE the sprite world is locked!)
  156.     //
  157.  
  158.     for (gBrickNum = 0; gBrickNum < kTotalNumberOfBricks; gBrickNum++)
  159.     {
  160.             // add the brick sprite to the brick layer
  161.         SWAddSprite(brickLayerP, brickSpriteArray[gBrickNum]);
  162.     }
  163.  
  164.         // add the ball sprite to the ball layer
  165.     SWAddSprite(ballLayerP, ballSpriteP);
  166.  
  167.         // add the paddle sprite to the paddle layer
  168.     SWAddSprite(paddleLayerP, paddleSpriteP);
  169.  
  170.         // add the layers to the world
  171.     SWAddSpriteLayer(spriteWorldP, brickLayerP);
  172.     SWAddSpriteLayer(spriteWorldP, ballLayerP);
  173.     SWAddSpriteLayer(spriteWorldP, paddleLayerP);
  174.     
  175.  
  176.  
  177.     //
  178.     // STEP #4: set things up for the animation
  179.     // (can be done before or after locking the SpriteWorld)
  180.     //
  181.  
  182.         // calculate the movement boundary rectangle
  183.     moveBoundsRect = srcWindowP->portRect;
  184.  
  185.     horizOffset = (brickSpriteArray[0]->curFrameP->frameRect.right - brickSpriteArray[0]->curFrameP->frameRect.left) + 2;
  186.     vertOffset = (brickSpriteArray[0]->curFrameP->frameRect.bottom - brickSpriteArray[0]->curFrameP->frameRect.top) + 2;
  187.     brickHoriz = 2;
  188.     brickVert = (vertOffset * 2);
  189.     gBrickNum = 0;
  190.  
  191.         // set up the bricks
  192.     for (col = 0; col < kNumberOfBrickColumns; col++)
  193.     {
  194.         brickVert = (vertOffset * 2);
  195.  
  196.         for (row = 0; row < kNumberOfBrickRows; row++)
  197.         {
  198.                 // set the sprite’s initial location
  199.             SWSetSpriteLocation(brickSpriteArray[gBrickNum], brickHoriz, brickVert);
  200.             SWSetSpriteMoveTime(brickSpriteArray[gBrickNum], -1);
  201.  
  202.             gBrickNum++;
  203.             brickVert += vertOffset;
  204.         }
  205.     
  206.         brickHoriz += horizOffset;
  207.     }
  208.  
  209.         // set the ball’s movement characteristics
  210.     SWSetSpriteLocation(ballSpriteP, - 100, 50);
  211.     SWSetSpriteMoveBounds(ballSpriteP, &moveBoundsRect);
  212.     SWSetSpriteMoveDelta(ballSpriteP, kBallHorizDelta, kBallVertDelta);
  213.     SWSetSpriteMoveProc(ballSpriteP, BallMoveProc);
  214.     SWSetSpriteCollideProc(ballSpriteP, BallCollideProc);
  215.  
  216.         // set the paddle’s movement characteristics
  217.     SWSetSpriteMoveBounds(paddleSpriteP, &moveBoundsRect);
  218.     SetUpPaddle(paddleSpriteP);
  219.     SWSetSpriteMoveProc(paddleSpriteP, PaddleMoveProc);
  220.     SWSetSpriteCollideProc(paddleSpriteP, PaddleCollideProc);
  221.     
  222.     
  223.     //
  224.     // Set the DrawProcs to BlitPixie
  225.     //
  226.  
  227.         // Set the sprite drawProcs
  228.     if (spriteWorldP->pixelDepth == 8)        // 256 colors
  229.     {
  230.         SWSetSpriteDrawProc(ballSpriteP, BlitPixie8BitMaskDrawProc);
  231.         SWSetSpriteDrawProc(paddleSpriteP, BlitPixie8BitRectDrawProc);
  232.     }
  233.     else if ( !(SW_PPC && spriteWorldP->pixelDepth < 8) )    // Not 256 colors
  234.     {
  235.         SWSetSpriteDrawProc(ballSpriteP, BlitPixieAllBitMaskDrawProc);
  236.         SWSetSpriteDrawProc(paddleSpriteP, BlitPixieAllBitRectDrawProc);
  237.     }
  238.     
  239.         // Set the screen drawProcs
  240.     if (spriteWorldP->pixelDepth == 8)        // 256 colors
  241.     {
  242.         SWSetSpriteWorldScreenDrawProc(spriteWorldP, BlitPixie8BitRectDrawProc);
  243.         SWSetSpriteWorldOffscreenDrawProc(spriteWorldP, BlitPixie8BitRectDrawProc);
  244.     }
  245.     else if ( !(SW_PPC && spriteWorldP->pixelDepth < 8) )    // Not 256 colors
  246.     {
  247.         SWSetSpriteWorldScreenDrawProc(spriteWorldP, BlitPixieAllBitRectDrawProc);
  248.         SWSetSpriteWorldOffscreenDrawProc(spriteWorldP, BlitPixieAllBitRectDrawProc);
  249.     }
  250.  
  251.  
  252.  
  253.     //
  254.     // STEP #5: lock the sprite world        !!! VERY IMPORTANT !!!
  255.     //
  256.  
  257.     SWLockSpriteWorld(spriteWorldP);
  258.     
  259.  
  260.     HideCursor();
  261.     
  262.     
  263.     //
  264.     // SETP #6: Draw a nice background. Must be done *after* locking the SpriteWorld!
  265.     //
  266.  
  267.     SWSetPortToBackground(spriteWorldP);
  268.     
  269.     if (spriteWorldP->pixelDepth == 1)
  270.         pixPatH = GetPixPat(129);        // B&W dithered background
  271.     else
  272.         pixPatH = GetPixPat(128);        // Color
  273.     
  274.     if (pixPatH != NULL)
  275.     {
  276.         FillCRect(&moveBoundsRect, pixPatH);
  277.         DisposePixPat(pixPatH);
  278.     }
  279.  
  280.  
  281.     SWSetPortToWindow(spriteWorldP);
  282.  
  283.  
  284.     //
  285.     // STEP #7: update the SpriteWorld and run the animation
  286.     //
  287.  
  288.  
  289.     SetCursor(&qd.arrow);
  290.     SWUpdateSpriteWorld(spriteWorldP, true);
  291.     SWSetSpriteWorldMaxFPS( spriteWorldP, kMaxFPS );
  292.     SWSyncSpriteWorldToVBL(spriteWorldP, kSyncToVBL);
  293.     SWSetCleanUpSpriteWorld(spriteWorldP);
  294.     
  295.     FatalError( SWStickyError() ); // Make sure no errors got past us during setup
  296.     
  297.     while (!Button())
  298.     {
  299.         SWProcessSpriteWorld(spriteWorldP);
  300.  
  301.             // did we lose the last ball?
  302.         if (ballSpriteP->userData == 4)
  303.         {
  304.             SysBeep(1);
  305.             break;
  306.         }
  307.         else if (gBrickNum == 0)
  308.         {
  309.             for (n=0; n<3; n++)
  310.                 SysBeep(1);
  311.             break;
  312.         }
  313.  
  314.             // see if the ball has hit the paddle
  315.         SWCollideSpriteLayer(spriteWorldP, paddleLayerP, ballLayerP);
  316.  
  317.             // see if the ball has hit the bricks
  318.         SWCollideSpriteLayer(spriteWorldP, ballLayerP, brickLayerP);
  319.         
  320.             // Make sure no errors occurred during a MoveProc, etc.
  321.         FatalError( SWStickyError() );
  322.  
  323.         SWAnimateSpriteWorld(spriteWorldP);
  324.     }
  325.  
  326.  
  327.     //
  328.     // STEP #8: Clean up
  329.     //
  330.  
  331.     SWUnlockSpriteWorld(spriteWorldP);
  332.     SWDisposeSpriteWorld(&spriteWorldP);
  333.     SWExitSpriteWorld();
  334.     
  335.     FlushEvents(everyEvent, 0);
  336.     ShowCursor();
  337. }
  338.  
  339.  
  340. ///--------------------------------------------------------------------------------------
  341. // BallCollideProc
  342. ///--------------------------------------------------------------------------------------
  343.  
  344. SW_FUNC void BallCollideProc(SpritePtr ballSpriteP, SpritePtr brickSpriteP, Rect* sectRect)
  345. {
  346.     short        offset;
  347.     short        vertMoveDelta = ballSpriteP->vertMoveDelta;
  348.     short        horizMoveDelta = ballSpriteP->horizMoveDelta;
  349.  
  350.  
  351.     if (vertMoveDelta < 0)
  352.         vertMoveDelta = -vertMoveDelta;
  353.     
  354.     if (horizMoveDelta < 0)
  355.         horizMoveDelta = -horizMoveDelta;
  356.     
  357.     if (brickSpriteP->isVisible)
  358.     {
  359.         SWSetSpriteVisible(brickSpriteP, false);
  360.         gBrickNum--;
  361.  
  362.  
  363.         
  364.         if (vertMoveDelta < sectRect->bottom - sectRect->top)
  365.         {
  366.                 // Hit left or right side of brick
  367.             
  368.                 // Reverse direction
  369.             ballSpriteP->horizMoveDelta = -ballSpriteP->horizMoveDelta;
  370.             
  371.                 // "Bounce" ball off bricks
  372.             offset = (sectRect->right - sectRect->left) * 2;
  373.             if (ballSpriteP->horizMoveDelta < 0)
  374.                 offset = -offset;
  375.             
  376.             SWOffsetSprite(ballSpriteP, offset, 0);
  377.         }
  378.         else if (horizMoveDelta < sectRect->right - sectRect->left)
  379.         {
  380.                 // Hit top or bottom of brick
  381.             
  382.                 // Reverse direction
  383.             ballSpriteP->vertMoveDelta = -ballSpriteP->vertMoveDelta;
  384.             
  385.                 // "Bounce" ball off bricks
  386.             offset = (sectRect->bottom - sectRect->top) * 2;
  387.             if (ballSpriteP->vertMoveDelta < 0)
  388.                 offset = -offset;
  389.             
  390.             SWOffsetSprite(ballSpriteP, 0, offset);
  391.         }
  392.         else
  393.         {
  394.                 // Hit corner of brick
  395.                 
  396.             if ((sectRect->right - sectRect->left) > (sectRect->bottom - sectRect->top) )
  397.             {
  398.                     // Hit left or right side of brick
  399.                 
  400.                     // Reverse direction
  401.                 ballSpriteP->horizMoveDelta = -ballSpriteP->horizMoveDelta;
  402.                 
  403.                     // "Bounce" ball off bricks
  404.                 offset = (sectRect->right - sectRect->left) * 2;
  405.                 if (ballSpriteP->horizMoveDelta < 0)
  406.                     offset = -offset;
  407.                 
  408.                 SWOffsetSprite(ballSpriteP, offset, 0);
  409.             }
  410.             else
  411.             {
  412.                     // Hit top or bottom of brick
  413.                 
  414.                     // Reverse direction
  415.                 ballSpriteP->vertMoveDelta = -ballSpriteP->vertMoveDelta;
  416.                 
  417.                     // "Bounce" ball off bricks
  418.                 offset = (sectRect->bottom - sectRect->top) * 2;
  419.                 if (ballSpriteP->vertMoveDelta < 0)
  420.                     offset = -offset;
  421.                 
  422.                 SWOffsetSprite(ballSpriteP, 0, offset);
  423.             }
  424.         }
  425.     }
  426. }
  427.  
  428.  
  429. ///--------------------------------------------------------------------------------------
  430. // PaddleCollideProc
  431. ///--------------------------------------------------------------------------------------
  432.  
  433. SW_FUNC void PaddleCollideProc(SpritePtr paddleSpriteP, SpritePtr ballSpriteP, Rect* sectRect)
  434. {
  435.     short    paddleMid = (paddleSpriteP->destFrameRect.right - 
  436.                             paddleSpriteP->destFrameRect.left)/2;
  437.     short    ballMid = (ballSpriteP->destFrameRect.right - 
  438.                             ballSpriteP->destFrameRect.left)/2;
  439.             
  440.     if ( (ballSpriteP->destFrameRect.bottom - ballSpriteP->vertMoveDelta) 
  441.             > paddleSpriteP->destFrameRect.bottom )
  442.         return;                            // Return if ball did not hit above bottom of paddle
  443.     
  444.     
  445.         // Set ball direction according to position hit on paddle
  446.     if (ballSpriteP->destFrameRect.left + ballMid >
  447.          paddleSpriteP->destFrameRect.left + paddleMid)
  448.     {
  449.         ballSpriteP->horizMoveDelta = ( (ballSpriteP->destFrameRect.left + ballMid) - 
  450.                 (paddleSpriteP->destFrameRect.left + paddleMid) )/4;
  451.                 
  452.         if (ballSpriteP->horizMoveDelta > 0)
  453.             ballSpriteP->vertMoveDelta = kBallVertDelta - ballSpriteP->horizMoveDelta/2;
  454.         else
  455.             ballSpriteP->vertMoveDelta = kBallVertDelta + ballSpriteP->horizMoveDelta/2;
  456.         
  457.         if (ballSpriteP->horizMoveDelta == 0)
  458.             ballSpriteP->horizMoveDelta++;
  459.     }
  460.     else
  461.     {
  462.         ballSpriteP->horizMoveDelta = ( (ballSpriteP->destFrameRect.left + ballMid) - 
  463.                 (paddleSpriteP->destFrameRect.left + paddleMid) )/4;
  464.                 
  465.         if (ballSpriteP->horizMoveDelta > 0)
  466.             ballSpriteP->vertMoveDelta = kBallVertDelta - ballSpriteP->horizMoveDelta/2;
  467.         else
  468.             ballSpriteP->vertMoveDelta = kBallVertDelta + ballSpriteP->horizMoveDelta/2;
  469.         
  470.         if (ballSpriteP->horizMoveDelta == 0)
  471.             ballSpriteP->horizMoveDelta--;
  472.     }
  473.  
  474.     
  475.         // If ball was moving down, turn it around
  476.     if (ballSpriteP->vertMoveDelta > 0)
  477.         ballSpriteP->vertMoveDelta = -ballSpriteP->vertMoveDelta;
  478.     
  479.     if ( (ballSpriteP->destFrameRect.bottom - ballSpriteP->vertMoveDelta) 
  480.             > paddleSpriteP->destFrameRect.top )
  481.     {
  482.         SWOffsetSprite(ballSpriteP, 0, sectRect->top - sectRect->bottom);
  483.     }
  484.     
  485. }
  486.  
  487.  
  488. ///--------------------------------------------------------------------------------------
  489. // SetUpPaddle
  490. ///--------------------------------------------------------------------------------------
  491.  
  492. SW_FUNC void SetUpPaddle(SpritePtr paddleSpriteP)
  493. {
  494.     short    middle = (paddleSpriteP->moveBoundsRect.right - 
  495.                         paddleSpriteP->moveBoundsRect.left) / 2;
  496.     short    paddleWidth = (paddleSpriteP->destFrameRect.right - 
  497.                             paddleSpriteP->destFrameRect.left);
  498.     Point    globalPoint;
  499.     
  500.     
  501.     GetMouse(&newPoint);
  502.     globalPoint = newPoint;
  503.     LocalToGlobal(&globalPoint);
  504.     
  505.     if (globalPoint.h < middle)
  506.     {
  507.         SWSetSpriteLocation(paddleSpriteP, paddleSpriteP->moveBoundsRect.left +
  508.                                     globalPoint.h, paddleSpriteP->moveBoundsRect.bottom - 30);
  509.     }
  510.     else if (qd.screenBits.bounds.right - globalPoint.h < middle)
  511.     {
  512.         SWSetSpriteLocation(paddleSpriteP, paddleSpriteP->moveBoundsRect.right+1 -
  513.                                     (qd.screenBits.bounds.right - globalPoint.h) - paddleWidth, 
  514.                                     paddleSpriteP->moveBoundsRect.bottom - 30);
  515.     }
  516.     else
  517.     {
  518.         SWSetSpriteLocation(paddleSpriteP, paddleSpriteP->moveBoundsRect.left +
  519.                         middle - paddleWidth/2, paddleSpriteP->moveBoundsRect.bottom - 30);
  520.     }
  521. }
  522.  
  523.  
  524. ///--------------------------------------------------------------------------------------
  525. // PaddleMoveProc
  526. ///--------------------------------------------------------------------------------------
  527.  
  528. SW_FUNC void PaddleMoveProc(SpritePtr paddleSpriteP)
  529. {
  530.     oldPoint = newPoint;
  531.     GetMouse(&newPoint);
  532.  
  533.     SWOffsetSprite(paddleSpriteP, newPoint.h - oldPoint.h, 0);
  534.     
  535.     if (paddleSpriteP->destFrameRect.left < paddleSpriteP->moveBoundsRect.left)
  536.     {
  537.         SWOffsetSprite(paddleSpriteP, (paddleSpriteP->moveBoundsRect.left - 
  538.                             paddleSpriteP->destFrameRect.left) , 0);
  539.     }
  540.     else if (paddleSpriteP->destFrameRect.right > paddleSpriteP->moveBoundsRect.right)
  541.     {
  542.         SWOffsetSprite(paddleSpriteP, (paddleSpriteP->moveBoundsRect.right - 
  543.                             paddleSpriteP->destFrameRect.right) , 0);
  544.     }
  545. }
  546.  
  547.  
  548. ///--------------------------------------------------------------------------------------
  549. // BallMoveProc
  550. ///--------------------------------------------------------------------------------------
  551.  
  552. SW_FUNC void BallMoveProc(SpritePtr srcSpriteP)
  553. {
  554.     register short         inset;
  555.     
  556.     
  557.         // Move the sprite
  558.     SWOffsetSprite(srcSpriteP, srcSpriteP->horizMoveDelta, srcSpriteP->vertMoveDelta);
  559.     
  560.  
  561.         // Check for collision with walls
  562.     if ((srcSpriteP->destFrameRect.left < srcSpriteP->moveBoundsRect.left) &&
  563.             (srcSpriteP->horizMoveDelta < 0))        // Past left bounds and moving left
  564.     {
  565.         srcSpriteP->horizMoveDelta *= -1;            // Reverse direction
  566.         inset = srcSpriteP->moveBoundsRect.left - srcSpriteP->destFrameRect.left;
  567.         SWOffsetSprite( srcSpriteP, inset * 2, 0 );    // "Bounce" sprite off bounds
  568.  
  569.     }
  570.     else if ((srcSpriteP->destFrameRect.right > srcSpriteP->moveBoundsRect.right)&&
  571.                 (srcSpriteP->horizMoveDelta > 0))    // Past right bounds and moving right
  572.     {
  573.         srcSpriteP->horizMoveDelta *= -1;            // Reverse direction
  574.         inset = srcSpriteP->moveBoundsRect.right - srcSpriteP->destFrameRect.right;
  575.         SWOffsetSprite( srcSpriteP, inset * 2, 0 );    // "Bounce" sprite off bounds
  576.     }
  577.  
  578.     if ((srcSpriteP->destFrameRect.top < srcSpriteP->moveBoundsRect.top) &&
  579.             (srcSpriteP->vertMoveDelta < 0))        // Past top bounds and moving up
  580.     {
  581.         srcSpriteP->vertMoveDelta *= -1;            // Reverse direction
  582.         inset = srcSpriteP->moveBoundsRect.top - srcSpriteP->destFrameRect.top;
  583.         SWOffsetSprite( srcSpriteP, 0, inset * 2 );    // "Bounce" sprite off bounds
  584.     }
  585.     else if ((srcSpriteP->oldFrameRect.top > srcSpriteP->moveBoundsRect.bottom)&&
  586.                 (srcSpriteP->vertMoveDelta > 0))    // Past bottom bounds and moving down
  587.     {
  588.         SysBeep(1);
  589.         srcSpriteP->userData++;
  590.  
  591.         SWSetSpriteLocation(srcSpriteP, -100, 50);
  592.  
  593.         SWSetSpriteMoveDelta(srcSpriteP, kBallHorizDelta, kBallVertDelta);
  594.     }
  595. }
  596.