home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Pascal / Snippets / PNL Libraries / Libraries / SpriteWorld / SpriteWorld files / Sources / Scrolling.c < prev    next >
Encoding:
Text File  |  1997-04-16  |  53.2 KB  |  1,698 lines  |  [TEXT/KAHL]

  1. ///--------------------------------------------------------------------------------------
  2. //    Scrolling.c
  3. //
  4. //    By:    Vern Jensen
  5. //    
  6. //    Created: 8/29/95
  7. //
  8. //    Description:    Routines for making fast scrolling games with SpriteWorld
  9. ///--------------------------------------------------------------------------------------
  10.  
  11.  
  12.  
  13. #ifndef __QUICKDRAW__
  14. #include <QuickDraw.h>
  15. #endif
  16.  
  17. #ifndef __MEMORY__
  18. #include <Memory.h>
  19. #endif
  20.  
  21. #ifndef __GESTALT__
  22. #include <Gestalt.h>
  23. #endif
  24.  
  25. #ifndef __SPRITEWORLD__
  26. #include "SpriteWorld.h"
  27. #endif
  28.  
  29. #ifndef __SPRITEWORLDUTILS__
  30. #include "SpriteWorldUtils.h"
  31. #endif
  32.  
  33. #ifndef __BLITPIXIE__
  34. #include "BlitPixie.h"
  35. #endif
  36.  
  37. #ifndef __SCROLLING__
  38. #include "Scrolling.h"
  39. #endif
  40.  
  41. #ifndef __TILING__
  42. #include "Tiling.h"
  43. #endif
  44.  
  45.  
  46.  
  47. ///--------------------------------------------------------------------------------------
  48. //    SWUpdateScrollingWindow
  49. ///--------------------------------------------------------------------------------------
  50.  
  51. SW_FUNC void SWUpdateScrollingWindow(
  52.     SpriteWorldPtr spriteWorldP)
  53. {
  54.     GWorldPtr        holdGWorld;
  55.     GDHandle        holdGDH;
  56.     
  57.     SWAssert( spriteWorldP != NULL && spriteWorldP->windowFrameP != NULL );
  58.     
  59.     GetGWorld( &holdGWorld, &holdGDH );
  60.     
  61.     SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  62.     
  63.     if ( spriteWorldP->usingVBL )
  64.     {  
  65.         spriteWorldP->vblTaskRec.hasVBLFired = false;
  66.         while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  67.         {}
  68.     }
  69.     
  70.         // Copy visScrollRect to window
  71.     SWWrapWorldToScreen(spriteWorldP);
  72.                                     
  73.     SetGWorld( holdGWorld, holdGDH );
  74. }
  75.  
  76.  
  77. ///--------------------------------------------------------------------------------------
  78. //    SWUpdateScrollingSpriteWorld - should be called at the beginning of 
  79. //    a scrolling animation, so that idle sprites are set up correctly.
  80. ///--------------------------------------------------------------------------------------
  81.  
  82. SW_FUNC void SWUpdateScrollingSpriteWorld(
  83.     SpriteWorldPtr spriteWorldP,
  84.     Boolean updateWindow)
  85. {
  86.     register     SpriteLayerPtr curSpriteLayerP;
  87.     register     SpritePtr curSpriteP;
  88.     Rect        *visScrollRectP = &spriteWorldP->visScrollRect;
  89.     Rect        srcFrameRect, tempDstRect;
  90.     GWorldPtr    saveGWorld;
  91.     GDHandle    saveGDH;
  92.     
  93.     SWAssert( spriteWorldP != NULL && spriteWorldP->workFrameP != NULL );
  94.     
  95.     GetGWorld( &saveGWorld, &saveGDH );
  96.     
  97.     spriteWorldP->numTilesChanged = 0;
  98.  
  99.  
  100.         // Copy the background into the work area
  101.     SetGWorld(spriteWorldP->workFrameP->framePort, nil);
  102.     (*spriteWorldP->offscreenDrawProc)(spriteWorldP->backFrameP,
  103.                         spriteWorldP->workFrameP,
  104.                         &spriteWorldP->backFrameP->frameRect,
  105.                         &spriteWorldP->workFrameP->frameRect);
  106.     
  107.     
  108.     
  109.         // Build the current frame of the animation in the work area
  110.     
  111.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  112.  
  113.         // iterate through the layers in this world
  114.     while (curSpriteLayerP != NULL)
  115.     {
  116.         curSpriteP = curSpriteLayerP->headSpriteP;
  117.  
  118.             // iterate through the sprites in this layer
  119.         while (curSpriteP != NULL)
  120.         {
  121.             if (curSpriteP->isVisible)
  122.             {
  123.                 curSpriteP->destOffscreenRect = curSpriteP->destFrameRect;
  124.                 
  125.                 SWAssert( curSpriteP->curFrameP != NULL );
  126.                 
  127.                 srcFrameRect = curSpriteP->curFrameP->frameRect;
  128.                     
  129.                     
  130.                     // Clip the sprite's destOffscreenRect with visScrollRect
  131.                     // We use the destOffscreenRect both for drawing and erasing later
  132.                 if (curSpriteP->destOffscreenRect.top < visScrollRectP->top)
  133.                 {
  134.                     srcFrameRect.top += visScrollRectP->top - 
  135.                             curSpriteP->destOffscreenRect.top;
  136.                     curSpriteP->destOffscreenRect.top =  visScrollRectP->top;
  137.                 }
  138.  
  139.                 if (curSpriteP->destOffscreenRect.bottom > visScrollRectP->bottom)
  140.                 {
  141.                     srcFrameRect.bottom += visScrollRectP->bottom - 
  142.                             curSpriteP->destOffscreenRect.bottom;
  143.                     curSpriteP->destOffscreenRect.bottom = visScrollRectP->bottom;
  144.                 }
  145.                 
  146.                 if (curSpriteP->destOffscreenRect.left < visScrollRectP->left)
  147.                 {
  148.                     srcFrameRect.left += visScrollRectP->left - 
  149.                             curSpriteP->destOffscreenRect.left;
  150.                     curSpriteP->destOffscreenRect.left = visScrollRectP->left;
  151.                 }
  152.             
  153.                 if (curSpriteP->destOffscreenRect.right > visScrollRectP->right)
  154.                 {
  155.                     srcFrameRect.right += visScrollRectP->right - 
  156.                             curSpriteP->destOffscreenRect.right;
  157.                     curSpriteP->destOffscreenRect.right = visScrollRectP->right;
  158.                 }
  159.                 
  160.                 curSpriteP->destRectIsVisible =
  161.                         ( (curSpriteP->destOffscreenRect.right >
  162.                         curSpriteP->destOffscreenRect.left) &&
  163.                         (curSpriteP->destOffscreenRect.bottom >
  164.                         curSpriteP->destOffscreenRect.top) );
  165.                 
  166.                 
  167.                     // Is sprite visible on the screen?
  168.                 if (curSpriteP->destRectIsVisible)
  169.                 {
  170.                         // Make the sprite's rect local to the offscreen area
  171.                     curSpriteP->destOffscreenRect.top -= spriteWorldP->vertScrollRectOffset;
  172.                     curSpriteP->destOffscreenRect.bottom -= spriteWorldP->vertScrollRectOffset;
  173.                     curSpriteP->destOffscreenRect.left -= spriteWorldP->horizScrollRectOffset;
  174.                     curSpriteP->destOffscreenRect.right -= spriteWorldP->horizScrollRectOffset;
  175.                     
  176.                         // Draw the sprite in the work area
  177.                     SWDrawWrappedSprite(curSpriteP, spriteWorldP->workFrameP,
  178.                         &srcFrameRect, &curSpriteP->destOffscreenRect);
  179.                     
  180.                         // Draw tiles above sprite
  181.                     if (curSpriteP->isUnderTiles && spriteWorldP->tilingIsOn)
  182.                     {
  183.                         tempDstRect = curSpriteP->destOffscreenRect;
  184.                         tempDstRect.top += spriteWorldP->vertScrollRectOffset;
  185.                         tempDstRect.bottom += spriteWorldP->vertScrollRectOffset;
  186.                         tempDstRect.left += spriteWorldP->horizScrollRectOffset;
  187.                         tempDstRect.right += spriteWorldP->horizScrollRectOffset;
  188.                         SWDrawTilesAboveSprite(spriteWorldP, &tempDstRect);
  189.                     }
  190.                 }
  191.             }
  192.                 // Set the old rect to the current rect
  193.             curSpriteP->oldOffscreenRect = curSpriteP->destOffscreenRect;
  194.             curSpriteP->oldRectIsVisible = curSpriteP->destRectIsVisible;
  195.             
  196.             curSpriteP = curSpriteP->nextSpriteP;
  197.         }
  198.         
  199.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  200.     }
  201.     
  202.     spriteWorldP->oldVisScrollRect = spriteWorldP->visScrollRect;
  203.     
  204.         // Copy the work area to the window
  205.         
  206.     if (updateWindow)
  207.     {
  208.         SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  209.         
  210.         if (spriteWorldP->usingVBL)
  211.         {  
  212.             spriteWorldP->vblTaskRec.hasVBLFired = false;
  213.             while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  214.             {}
  215.         }
  216.         
  217.             // Copy visScrollRect to window
  218.         SWWrapWorldToScreen(spriteWorldP);
  219.     }
  220.     
  221.     SetGWorld( saveGWorld, saveGDH );
  222. }
  223.  
  224.  
  225. ///--------------------------------------------------------------------------------------
  226. //    SWProcessScrollingSpriteWorld
  227. ///--------------------------------------------------------------------------------------
  228.  
  229. SW_FUNC void SWProcessScrollingSpriteWorld(
  230.     SpriteWorldPtr spriteWorldP)
  231. {
  232.  
  233.     SWAssert( spriteWorldP != NULL );
  234.     
  235.         // Process the sprites
  236.     SWProcessSpriteWorld(spriteWorldP);
  237.     if ( !spriteWorldP->frameHasOccured )
  238.     {
  239.         return;
  240.     }
  241.  
  242.     
  243.         // Call the scrolling world move proc
  244.     if (spriteWorldP->worldMoveProc != NULL)
  245.     {
  246.         (*spriteWorldP->worldMoveProc)(spriteWorldP, spriteWorldP->followSpriteP);
  247.     }
  248.     
  249.     
  250.         // Move visScrollRect
  251.     if (spriteWorldP->horizScrollDelta || spriteWorldP->vertScrollDelta)
  252.     {
  253.         SWOffsetVisScrollRect(spriteWorldP, 
  254.             spriteWorldP->horizScrollDelta, 
  255.             spriteWorldP->vertScrollDelta);
  256.     }
  257. }
  258.  
  259.  
  260. ///--------------------------------------------------------------------------------------
  261. //    SWAnimateScrollingSpriteWorld
  262. ///--------------------------------------------------------------------------------------
  263.  
  264. SW_FUNC void SWAnimateScrollingSpriteWorld(
  265.     SpriteWorldPtr spriteWorldP)
  266. {
  267.     register SpriteLayerPtr     curSpriteLayerP;
  268.     register SpritePtr             curSpriteP;
  269.     SpritePtr                     headActiveSpriteP = NULL;    // First active sprite in world
  270.     SpritePtr                    headIdleSpriteP = NULL;        // First idle sprite in world
  271.     SpritePtr                     curActiveSpriteP = NULL;
  272.     SpritePtr                    curIdleSpriteP = NULL;
  273.     
  274.     Rect    *visScrollRectP = &spriteWorldP->visScrollRect;
  275.     Rect    tempDstRect;
  276.     
  277.     SWAssert( spriteWorldP != NULL );
  278.     
  279.     if (!spriteWorldP->frameHasOccured)
  280.         return;
  281.     
  282.     
  283.         // Update tiles as we scroll if tiling routines are turned on
  284.     if (spriteWorldP->tilingIsOn)
  285.     {
  286.             // VisScrollRect moved horizontally
  287.         if (spriteWorldP->oldVisScrollRect.left != spriteWorldP->visScrollRect.left)
  288.         {
  289.                 // Get rect of new vertical section to update
  290.             tempDstRect = spriteWorldP->visScrollRect;
  291.             
  292.                 // Moved left
  293.             if (tempDstRect.left < spriteWorldP->oldVisScrollRect.left)
  294.             {
  295.                 if (tempDstRect.right > spriteWorldP->oldVisScrollRect.left)
  296.                     tempDstRect.right = spriteWorldP->oldVisScrollRect.left;
  297.             }
  298.             else    // Moved right
  299.             {
  300.                 if (tempDstRect.left < spriteWorldP->oldVisScrollRect.right)
  301.                     tempDstRect.left = spriteWorldP->oldVisScrollRect.right;
  302.             }
  303.     
  304.             SWDrawTilesInRect(spriteWorldP, &tempDstRect, true);
  305.             SWWrapRectToWorkArea(spriteWorldP, &tempDstRect);
  306.             
  307.             
  308.                 // Did VisScrollRect moved diagonally?
  309.             if (spriteWorldP->oldVisScrollRect.top != spriteWorldP->visScrollRect.top)
  310.             {
  311.                     // Get rect of new horizontal section to update
  312.                 tempDstRect = spriteWorldP->visScrollRect;
  313.                 
  314.                     // Moved up
  315.                 if (tempDstRect.top < spriteWorldP->oldVisScrollRect.top)
  316.                 {
  317.                     if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.top)
  318.                         tempDstRect.bottom = spriteWorldP->oldVisScrollRect.top;
  319.                 }
  320.                 else    // Moved down
  321.                 {
  322.                     if (tempDstRect.top < spriteWorldP->oldVisScrollRect.bottom)
  323.                         tempDstRect.top = spriteWorldP->oldVisScrollRect.bottom;
  324.                 }
  325.                 
  326.                     // Clip off the part we've already updated
  327.                 if (tempDstRect.left < spriteWorldP->oldVisScrollRect.left)
  328.                 {
  329.                     if (tempDstRect.left < spriteWorldP->oldVisScrollRect.left)
  330.                         tempDstRect.left = spriteWorldP->oldVisScrollRect.left;
  331.                 }
  332.                 else
  333.                 {
  334.                     if (tempDstRect.right > spriteWorldP->oldVisScrollRect.right)
  335.                         tempDstRect.right = spriteWorldP->oldVisScrollRect.right;
  336.                 }
  337.                 
  338.                     // We pass false here to avoid a bug which occured in the
  339.                     // tile optimizing code when updating tiles twice in one frame
  340.                 if (tempDstRect.right > tempDstRect.left)
  341.                 {
  342.                     SWDrawTilesInRect(spriteWorldP, &tempDstRect, false);
  343.                     SWWrapRectToWorkArea(spriteWorldP, &tempDstRect);
  344.                 }
  345.             }
  346.         }
  347.         else    // VisScrollRect moved vertically only
  348.         if (spriteWorldP->oldVisScrollRect.top != spriteWorldP->visScrollRect.top)
  349.         {
  350.                 // Get rect of new horizontal section to update
  351.             tempDstRect = spriteWorldP->visScrollRect;
  352.             
  353.                 // Moved up
  354.             if (tempDstRect.top < spriteWorldP->oldVisScrollRect.top)
  355.             {
  356.                 if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.top)
  357.                     tempDstRect.bottom = spriteWorldP->oldVisScrollRect.top;
  358.             }
  359.             else    // Moved down
  360.             {
  361.                 if (tempDstRect.top < spriteWorldP->oldVisScrollRect.bottom)
  362.                     tempDstRect.top = spriteWorldP->oldVisScrollRect.bottom;
  363.             }
  364.  
  365.             SWDrawTilesInRect(spriteWorldP, &tempDstRect, true);
  366.             SWWrapRectToWorkArea(spriteWorldP, &tempDstRect);
  367.         }
  368.     }
  369.     
  370.     
  371.     //-----------------erase the sprites--------------------
  372.     
  373.     SWAssert( spriteWorldP->workFrameP != NULL );
  374.     
  375.         // Set the port to the work area so we can draw in it
  376.     SetGWorld(spriteWorldP->workFrameP->framePort, nil);
  377.     
  378.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;    
  379.     
  380.         // iterate through the layers in this world
  381.     while (curSpriteLayerP != NULL)
  382.     {
  383.         curSpriteP = curSpriteLayerP->headSpriteP;
  384.         
  385.             // iterate through the sprites in this layer
  386.         while (curSpriteP != NULL)
  387.         {
  388.                 // Loop through all visible sprites, whether in visScrollRect or not,
  389.                 // and clip the sprite's destOffscreenRect with visScrollRect.
  390.             if (curSpriteP->isVisible)
  391.             {
  392.                 curSpriteP->destOffscreenRect = curSpriteP->destFrameRect;
  393.                 curSpriteP->clippedSourceRect = curSpriteP->curFrameP->frameRect;
  394.                 
  395.  
  396.                 if (curSpriteP->destOffscreenRect.top < visScrollRectP->top)
  397.                 {
  398.                     curSpriteP->clippedSourceRect.top += visScrollRectP->top - 
  399.                             curSpriteP->destOffscreenRect.top;
  400.                     curSpriteP->destOffscreenRect.top = visScrollRectP->top;
  401.                 }
  402.                 
  403.                 if (curSpriteP->destOffscreenRect.bottom > visScrollRectP->bottom)
  404.                 {
  405.                     curSpriteP->clippedSourceRect.bottom += visScrollRectP->bottom - 
  406.                             curSpriteP->destOffscreenRect.bottom;
  407.                     curSpriteP->destOffscreenRect.bottom = visScrollRectP->bottom;
  408.                 }
  409.                 
  410.                 if (curSpriteP->destOffscreenRect.left < visScrollRectP->left)
  411.                 {
  412.                     curSpriteP->clippedSourceRect.left += visScrollRectP->left - 
  413.                             curSpriteP->destOffscreenRect.left;
  414.                     curSpriteP->destOffscreenRect.left = visScrollRectP->left;
  415.                 }
  416.                 
  417.                 if (curSpriteP->destOffscreenRect.right > visScrollRectP->right)
  418.                 {
  419.                     curSpriteP->clippedSourceRect.right += visScrollRectP->right - 
  420.                             curSpriteP->destOffscreenRect.right;
  421.                     curSpriteP->destOffscreenRect.right = visScrollRectP->right;
  422.                 }
  423.                 
  424.                 curSpriteP->destRectIsVisible =
  425.                         (curSpriteP->destOffscreenRect.right >
  426.                         curSpriteP->destOffscreenRect.left &&
  427.                         curSpriteP->destOffscreenRect.bottom >
  428.                         curSpriteP->destOffscreenRect.top);
  429.             }
  430.             
  431.             
  432.                 // Erase the sprites
  433.             if (curSpriteP->needsToBeDrawn && curSpriteP->isVisible ||
  434.                     curSpriteP->needsToBeErased && !curSpriteP->isVisible)
  435.             {
  436.                     // Was the sprite visible on the screen last frame?
  437.                 if (curSpriteP->oldRectIsVisible)
  438.                 {
  439.                     if (headActiveSpriteP == NULL)
  440.                         headActiveSpriteP = curSpriteP;
  441.                     
  442.                     if (curActiveSpriteP != NULL)
  443.                         curActiveSpriteP->nextActiveSpriteP = curSpriteP;
  444.                     
  445.                     curActiveSpriteP = curSpriteP;
  446.                     
  447.                     {
  448.                         short temp;
  449.                         
  450.                             // align the left edge to long word boundary
  451.                             // for drawing
  452.                         curSpriteP->oldOffscreenRect.left &=
  453.                             (spriteWorldP->workFrameP->leftAlignFactor);
  454.                         
  455.                             // align the right edge to long word boundary
  456.                         temp = curSpriteP->oldOffscreenRect.right &
  457.                             spriteWorldP->workFrameP->rightAlignFactor;
  458.                         if (temp != 0)
  459.                         {
  460.                             curSpriteP->oldOffscreenRect.right +=
  461.                                 (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  462.                         }
  463.  
  464.                             // align the left edge to long word boundary
  465.                             // for SWRedrawErasedIdleSprites
  466.                         curSpriteP->oldFrameRect.left &=
  467.                             (spriteWorldP->workFrameP->leftAlignFactor);
  468.                         
  469.                             // align the right edge to long word boundary
  470.                         temp = curSpriteP->oldFrameRect.right &
  471.                             spriteWorldP->workFrameP->rightAlignFactor;
  472.                         if (temp != 0)
  473.                         {
  474.                             curSpriteP->oldFrameRect.right +=
  475.                                 (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  476.                         }
  477.                     }
  478.                     
  479.                         // Erase the sprite from the work area
  480.                     SWEraseWrappedSprite(spriteWorldP, &curSpriteP->oldOffscreenRect);
  481.                 }
  482.                 else if (curSpriteP->destRectIsVisible)    // Sprite will be drawn
  483.                 {
  484.                         // Add sprite to active sprite list
  485.                     if (headActiveSpriteP == NULL)
  486.                         headActiveSpriteP = curSpriteP;
  487.                     
  488.                     if (curActiveSpriteP != NULL)
  489.                         curActiveSpriteP->nextActiveSpriteP = curSpriteP;
  490.                     
  491.                     curActiveSpriteP = curSpriteP;
  492.                 }
  493.             }
  494.             else if (curSpriteP->isVisible)        // Visible, idle sprites
  495.             {
  496.                     // Is dest sprite rect smaller than old sprite rect?
  497.                 if (curSpriteP->oldRectIsVisible)
  498.                 {
  499.                     if (curSpriteP->destOffscreenRect.right -
  500.                         curSpriteP->destOffscreenRect.left <
  501.                         curSpriteP->oldOffscreenRect.right -
  502.                         curSpriteP->oldOffscreenRect.left)
  503.                     {
  504.                             // Erase part of idle sprite outside of visScrollRect
  505.                         tempDstRect = curSpriteP->oldFrameRect;
  506.                         
  507.                             // Get section of sprite outside visScrollRect
  508.                         if (tempDstRect.left < visScrollRectP->left)
  509.                             tempDstRect.right = visScrollRectP->left;
  510.                         else
  511.                             tempDstRect.left = visScrollRectP->right;
  512.                         
  513.                             // Make the rect local to the offscreen area
  514.                         tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  515.                         tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  516.                         tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  517.                         tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  518.                         
  519.                             // Erase piece of idle sprite outside of visScrollRect
  520.                         SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
  521.                     }
  522.                     
  523.                     if (curSpriteP->destOffscreenRect.bottom -
  524.                         curSpriteP->destOffscreenRect.top <
  525.                         curSpriteP->oldOffscreenRect.bottom -
  526.                         curSpriteP->oldOffscreenRect.top)
  527.                     {
  528.                             // Erase part of idle sprite outside of visScrollRect
  529.                         tempDstRect = curSpriteP->oldFrameRect;
  530.                         
  531.                             // Get section of sprite outside visScrollRect
  532.                         if (tempDstRect.top < visScrollRectP->top)
  533.                             tempDstRect.bottom = visScrollRectP->top;
  534.                         else
  535.                             tempDstRect.top = visScrollRectP->bottom;
  536.                         
  537.                             // Make the rect local to the offscreen area
  538.                         tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  539.                         tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  540.                         tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  541.                         tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  542.                         
  543.                             // Erase piece of idle sprite outside of visScrollRect
  544.                         SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
  545.                     }
  546.                 }
  547.                                 
  548.                 
  549.                     // Is the idle sprite visible on the screen?
  550.                 if (curSpriteP->destRectIsVisible)
  551.                 {
  552.                         // Redraw idle sprite if it is coming into the visScrollRect.
  553.                     if (curSpriteP->destOffscreenRect.right -
  554.                         curSpriteP->destOffscreenRect.left >
  555.                         curSpriteP->oldOffscreenRect.right -
  556.                         curSpriteP->oldOffscreenRect.left ||
  557.                         curSpriteP->destOffscreenRect.bottom -
  558.                         curSpriteP->destOffscreenRect.top >
  559.                         curSpriteP->oldOffscreenRect.bottom -
  560.                         curSpriteP->oldOffscreenRect.top)
  561.                     {
  562.                         curSpriteP->needsToBeDrawn = true;
  563.                         
  564.                             // Add sprite to active sprite list
  565.                         if (headActiveSpriteP == NULL)
  566.                             headActiveSpriteP = curSpriteP;
  567.                         
  568.                         if (curActiveSpriteP != NULL)
  569.                             curActiveSpriteP->nextActiveSpriteP = curSpriteP;
  570.                         
  571.                         curActiveSpriteP = curSpriteP;
  572.                     }
  573.                     else    // Add sprite to idle sprite list
  574.                     {
  575.                         if (headIdleSpriteP == NULL)
  576.                             headIdleSpriteP = curSpriteP;
  577.                         
  578.                         if (curIdleSpriteP != NULL)
  579.                             curIdleSpriteP->nextIdleSpriteP = curSpriteP;
  580.                         
  581.                         curIdleSpriteP = curSpriteP;
  582.                     }
  583.                 }
  584.             }
  585.  
  586.             curSpriteP = curSpriteP->nextSpriteP;
  587.         }
  588.  
  589.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;    
  590.     }
  591.  
  592.     if (curActiveSpriteP != NULL)
  593.         curActiveSpriteP->nextActiveSpriteP = NULL;    // Last active sprite in chain
  594.             
  595.     if (curIdleSpriteP != NULL)
  596.         curIdleSpriteP->nextIdleSpriteP = NULL;        // Last idle sprite in chain
  597.  
  598.  
  599.         // Redraw idle sprites that were erased when active sprites were erased
  600.     SWRedrawErasedIdleSprites(spriteWorldP, headActiveSpriteP, headIdleSpriteP);
  601.     
  602.     
  603.         // Redraw idle sprites which were erased when the background was changed
  604.     while (spriteWorldP->numTilesChanged > 0)
  605.         SWRedrawIdleSpritesInRect(spriteWorldP, headIdleSpriteP,
  606.                 &spriteWorldP->changedTiles[--spriteWorldP->numTilesChanged]);
  607.  
  608.  
  609.  
  610.     //-----------------draw the sprites-------------------
  611.  
  612.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  613.  
  614.         // iterate through the layers in this world
  615.     while (curSpriteLayerP != NULL)
  616.     {
  617.         curSpriteP = curSpriteLayerP->headSpriteP;
  618.  
  619.             // iterate through the sprites in this layer
  620.         while (curSpriteP != NULL)
  621.         {
  622.             if (curSpriteP->isVisible)
  623.             {
  624.                     // Make the sprite's rect local to the offscreen area
  625.                 curSpriteP->destOffscreenRect.top -= spriteWorldP->vertScrollRectOffset;
  626.                 curSpriteP->destOffscreenRect.bottom -= spriteWorldP->vertScrollRectOffset;
  627.                 curSpriteP->destOffscreenRect.left -= spriteWorldP->horizScrollRectOffset;
  628.                 curSpriteP->destOffscreenRect.right -= spriteWorldP->horizScrollRectOffset;
  629.                 
  630.                 if (curSpriteP->needsToBeDrawn)
  631.                 {
  632.                         // Is the sprite visible on the screen?
  633.                     if (curSpriteP->destRectIsVisible)
  634.                     {
  635.                             // Draw the sprite in the work area
  636.                         SWDrawWrappedSprite(curSpriteP, spriteWorldP->workFrameP,
  637.                             &curSpriteP->clippedSourceRect, 
  638.                             &curSpriteP->destOffscreenRect);
  639.                         
  640.                             // Draw tiles above sprite
  641.                         if (curSpriteP->isUnderTiles && spriteWorldP->tilingIsOn)
  642.                         {
  643.                             tempDstRect = curSpriteP->destOffscreenRect;
  644.                             tempDstRect.top += spriteWorldP->vertScrollRectOffset;
  645.                             tempDstRect.bottom += spriteWorldP->vertScrollRectOffset;
  646.                             tempDstRect.left += spriteWorldP->horizScrollRectOffset;
  647.                             tempDstRect.right += spriteWorldP->horizScrollRectOffset;
  648.                             SWDrawTilesAboveSprite(spriteWorldP, &tempDstRect);
  649.                         }
  650.                     }
  651.                 }
  652.                 else
  653.                 {
  654.                         // Is the idle sprite visible on the screen?
  655.                     if (curSpriteP->destRectIsVisible)
  656.                     {
  657.                         SWCheckWrappedIdleSpriteOverlap(spriteWorldP, 
  658.                             curSpriteP, headActiveSpriteP);
  659.                     }
  660.                 }
  661.             }
  662.             
  663.                 // Set last rect to current rect
  664.             curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
  665.             curSpriteP->oldOffscreenRect = curSpriteP->destOffscreenRect;
  666.             curSpriteP->oldRectIsVisible = curSpriteP->destRectIsVisible;
  667.             
  668.             curSpriteP->needsToBeDrawn = false;
  669.             curSpriteP->needsToBeErased = false;
  670.  
  671.             curSpriteP = curSpriteP->nextSpriteP;
  672.         }
  673.         
  674.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  675.     }
  676.     
  677.     spriteWorldP->oldVisScrollRect = spriteWorldP->visScrollRect;
  678.     
  679.     
  680.     //-----------------update the screen--------------------
  681.     
  682.         // Set the port to the window
  683.     SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  684.     
  685.     if (spriteWorldP->usingVBL)
  686.     {  
  687.         spriteWorldP->vblTaskRec.hasVBLFired = false;
  688.         while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  689.         {}
  690.     }
  691.     
  692.         // Copy offscreen area to screen while wrapping
  693.     SWWrapWorldToScreen(spriteWorldP);
  694. }
  695.  
  696.  
  697. ///--------------------------------------------------------------------------------------
  698. //    SWDrawWrappedSprite - wraps image in dest area. For drawing sprites, not erasing,
  699. //    since source rect stays the same.
  700. ///--------------------------------------------------------------------------------------
  701.  
  702. SW_FUNC void SWDrawWrappedSprite(
  703.     SpritePtr srcSpriteP,
  704.     FramePtr dstFrameP,
  705.     Rect* srcRect,
  706.     Rect* dstRect)
  707. {
  708.     Rect        tempDstRect;
  709.     
  710.     SWAssert( srcSpriteP != NULL && dstFrameP != NULL && srcRect != NULL && dstRect != NULL );
  711.     
  712.         // Draw main image //
  713.     (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, srcRect, dstRect);
  714.     
  715.     
  716.         // Wrap to top //
  717.     if (dstRect->bottom > dstFrameP->frameRect.bottom)
  718.     {
  719.         tempDstRect.top = dstRect->top - dstFrameP->frameRect.bottom;
  720.         tempDstRect.bottom = dstRect->bottom - dstFrameP->frameRect.bottom;
  721.         tempDstRect.left = dstRect->left;
  722.         tempDstRect.right = dstRect->right;
  723.         
  724.         (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  725.             srcRect, &tempDstRect);
  726.         
  727.         
  728.             // Wrap to upper left or right corner //
  729.         if (dstRect->right > dstFrameP->frameRect.right)
  730.         {
  731.             tempDstRect.left -= dstFrameP->frameRect.right;
  732.             tempDstRect.right -= dstFrameP->frameRect.right;
  733.             
  734.             (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  735.                 srcRect, &tempDstRect);
  736.         }
  737.         else if (dstRect->left < dstFrameP->frameRect.left)
  738.         {
  739.             tempDstRect.left += dstFrameP->frameRect.right;
  740.             tempDstRect.right += dstFrameP->frameRect.right;
  741.             
  742.             (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  743.                 srcRect, &tempDstRect);
  744.         }
  745.     }
  746.     
  747.             // Wrap to left or right side //
  748.     if (dstRect->right > dstFrameP->frameRect.right)
  749.     {
  750.         tempDstRect.top = dstRect->top;
  751.         tempDstRect.bottom = dstRect->bottom;
  752.         tempDstRect.left = dstRect->left - dstFrameP->frameRect.right;
  753.         tempDstRect.right = dstRect->right - dstFrameP->frameRect.right;
  754.         
  755.         (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  756.             srcRect, &tempDstRect);
  757.     }
  758.     else if (dstRect->left < dstFrameP->frameRect.left)
  759.     {
  760.         tempDstRect.top = dstRect->top;
  761.         tempDstRect.bottom = dstRect->bottom;
  762.         tempDstRect.left = dstRect->left + dstFrameP->frameRect.right;
  763.         tempDstRect.right = dstRect->right + dstFrameP->frameRect.right;
  764.         
  765.         (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  766.             srcRect, &tempDstRect);
  767.     }
  768.     
  769.     
  770.             // Wrap to bottom //
  771.     if (dstRect->top < dstFrameP->frameRect.top)
  772.     {
  773.         tempDstRect.top = dstRect->top + dstFrameP->frameRect.bottom;
  774.         tempDstRect.bottom = dstRect->bottom + dstFrameP->frameRect.bottom;
  775.         tempDstRect.left = dstRect->left;
  776.         tempDstRect.right = dstRect->right;
  777.         
  778.         (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  779.             srcRect, &tempDstRect);
  780.         
  781.             // Wrap to lower left or right corner //
  782.         if (dstRect->right > dstFrameP->frameRect.right)
  783.         {
  784.             tempDstRect.left -= dstFrameP->frameRect.right;
  785.             tempDstRect.right -= dstFrameP->frameRect.right;
  786.             
  787.             (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  788.                 srcRect, &tempDstRect);
  789.         }
  790.         else if (dstRect->left < dstFrameP->frameRect.left)
  791.         {
  792.             tempDstRect.left += dstFrameP->frameRect.right;
  793.             tempDstRect.right += dstFrameP->frameRect.right;
  794.             
  795.             (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  796.                 srcRect, &tempDstRect);
  797.         }
  798.     }
  799. }
  800.  
  801.  
  802. ///--------------------------------------------------------------------------------------
  803. //    SWEraseWrappedSprite - erases a wrapped sprite from the work area
  804. ///--------------------------------------------------------------------------------------
  805.  
  806. SW_FUNC void SWEraseWrappedSprite(
  807.     SpriteWorldPtr spriteWorldP,
  808.     Rect* dstRect)
  809. {
  810.     Rect        tempDstRect;
  811.     FramePtr    srcFrameP = spriteWorldP->backFrameP;
  812.     FramePtr    dstFrameP = spriteWorldP->workFrameP;
  813.     
  814.     SWAssert( spriteWorldP != NULL && dstRect != NULL );
  815.     
  816.         // Draw main image //
  817.     (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, dstRect, dstRect);
  818.     
  819.     
  820.         // Wrap to top //
  821.     if (dstRect->bottom > dstFrameP->frameRect.bottom)
  822.     {
  823.         tempDstRect.top = dstRect->top - dstFrameP->frameRect.bottom;
  824.         tempDstRect.bottom = dstRect->bottom - dstFrameP->frameRect.bottom;
  825.         tempDstRect.left = dstRect->left;
  826.         tempDstRect.right = dstRect->right;
  827.         
  828.         (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  829.             &tempDstRect, &tempDstRect);
  830.         
  831.             // Wrap to upper left or right corner //
  832.         if (dstRect->right > dstFrameP->frameRect.right)
  833.         {
  834.             tempDstRect.left -= dstFrameP->frameRect.right;
  835.             tempDstRect.right -= dstFrameP->frameRect.right;
  836.             
  837.             (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  838.                 &tempDstRect, &tempDstRect);
  839.         }
  840.         else if (dstRect->left < dstFrameP->frameRect.left)
  841.         {
  842.             tempDstRect.left += dstFrameP->frameRect.right;
  843.             tempDstRect.right += dstFrameP->frameRect.right;
  844.             
  845.             (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  846.                 &tempDstRect, &tempDstRect);
  847.         }
  848.     }
  849.     
  850.             // Wrap to left or right side //
  851.     if (dstRect->right > dstFrameP->frameRect.right)
  852.     {
  853.         tempDstRect.top = dstRect->top;
  854.         tempDstRect.bottom = dstRect->bottom;
  855.         tempDstRect.left = dstRect->left - dstFrameP->frameRect.right;
  856.         tempDstRect.right = dstRect->right - dstFrameP->frameRect.right;
  857.         
  858.         (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  859.             &tempDstRect, &tempDstRect);
  860.     }
  861.     else if (dstRect->left < dstFrameP->frameRect.left)
  862.     {
  863.         tempDstRect.top = dstRect->top;
  864.         tempDstRect.bottom = dstRect->bottom;
  865.         tempDstRect.left = dstRect->left + dstFrameP->frameRect.right;
  866.         tempDstRect.right = dstRect->right + dstFrameP->frameRect.right;
  867.         
  868.         (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  869.             &tempDstRect, &tempDstRect);
  870.     }
  871.     
  872.     
  873.             // Wrap to bottom //
  874.     if (dstRect->top < dstFrameP->frameRect.top)
  875.     {
  876.         tempDstRect.top = dstRect->top + dstFrameP->frameRect.bottom;
  877.         tempDstRect.bottom = dstRect->bottom + dstFrameP->frameRect.bottom;
  878.         tempDstRect.left = dstRect->left;
  879.         tempDstRect.right = dstRect->right;
  880.         
  881.         (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  882.             &tempDstRect, &tempDstRect);
  883.         
  884.             // Wrap to lower left or right corner //
  885.         if (dstRect->right > dstFrameP->frameRect.right)
  886.         {
  887.             tempDstRect.left -= dstFrameP->frameRect.right;
  888.             tempDstRect.right -= dstFrameP->frameRect.right;
  889.             
  890.             (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  891.                 &tempDstRect, &tempDstRect);
  892.         }
  893.         else if (dstRect->left < dstFrameP->frameRect.left)
  894.         {
  895.             tempDstRect.left += dstFrameP->frameRect.right;
  896.             tempDstRect.right += dstFrameP->frameRect.right;
  897.             
  898.             (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  899.                 &tempDstRect, &tempDstRect);
  900.         }
  901.     }
  902. }
  903.  
  904.  
  905. ///--------------------------------------------------------------------------------------
  906. //    SWWrapWorldToScreen - copy source rect to dest rect. Assumes they are the same
  907. //    size, and that destRect will fit within the bounds of the dstFrameP. Used for
  908. //    copying the work area to the screen, with the ability of "wrapping" the source
  909. //    rect around the work area.
  910. ///--------------------------------------------------------------------------------------
  911.  
  912.  
  913. SW_FUNC void SWWrapWorldToScreen(
  914.     SpriteWorldPtr    spriteWorldP)
  915. {    
  916.     FramePtr    srcFrameP = spriteWorldP->workFrameP;
  917.     FramePtr    dstFrameP = spriteWorldP->windowFrameP;
  918.     
  919.         // We can always add code to clip dstRect later if we want.
  920.         // Just make sure to clip it before clipping srcRect.
  921.     Rect    srcRect = spriteWorldP->offscreenScrollRect;
  922.     Rect    dstRect = spriteWorldP->windowFrameP->frameRect;
  923.     Rect    tempSrcRect, tempDstRect;
  924.     
  925.                 // Size of area that was clipped in source rect
  926.     short    topClip=0, rightClip=0, bottomClip=0, leftClip=0;
  927.     
  928.     SWAssert( spriteWorldP != NULL && srcFrameP != NULL && dstFrameP != NULL );
  929.  
  930.     
  931.         // Clip the source rect, and save what we clipped for wrapping later //
  932.     
  933.         // clip off the top
  934.     if (srcRect.top < srcFrameP->frameRect.top)
  935.     {
  936.         topClip = srcFrameP->frameRect.top - srcRect.top;
  937.         srcRect.top += topClip;    
  938.     }
  939.     
  940.         // clip off the bottom
  941.     if (srcRect.bottom > srcFrameP->frameRect.bottom)
  942.     {
  943.         bottomClip = srcRect.bottom - srcFrameP->frameRect.bottom;
  944.         srcRect.bottom -= bottomClip;
  945.     }
  946.     
  947.         // clip off the left
  948.     if (srcRect.left < srcFrameP->frameRect.left)
  949.     {
  950.         leftClip = srcFrameP->frameRect.left - srcRect.left;
  951.         srcRect.left += leftClip;
  952.     }
  953.     
  954.         // clip off the right
  955.     if (srcRect.right > srcFrameP->frameRect.right)
  956.     {
  957.         rightClip = srcRect.right - srcFrameP->frameRect.right;
  958.         srcRect.right -= rightClip;
  959.     }
  960.     
  961.     
  962.                     // Do the wrapping and drawing //
  963.     
  964.         // Draw top section, starting at left and going right //
  965.     
  966.     if (topClip)
  967.     {
  968.         if (leftClip)    // Draw top-left piece //
  969.         {
  970.                 // Wrap source rect to lower-right corner //
  971.             tempSrcRect.bottom = srcFrameP->frameRect.bottom;
  972.             tempSrcRect.right = srcFrameP->frameRect.right;
  973.             tempSrcRect.top = srcFrameP->frameRect.bottom - topClip;
  974.             tempSrcRect.left = srcFrameP->frameRect.right - leftClip;
  975.             
  976.                 // Position dest rect at top-left corner //
  977.             tempDstRect.left = dstRect.left;
  978.             tempDstRect.top = dstRect.top;
  979.             tempDstRect.right = dstRect.left + leftClip;
  980.             tempDstRect.bottom = dstRect.top + topClip;
  981.             
  982.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, 
  983.                 &tempSrcRect, &tempDstRect);
  984.         }
  985.         
  986.         
  987.             // Draw top piece //
  988.         
  989.             // Wrap source rect to bottom side //
  990.         tempSrcRect.right = srcRect.right;                // Copy clipped source rect
  991.         tempSrcRect.left = srcRect.left;
  992.         tempSrcRect.bottom = srcFrameP->frameRect.bottom;
  993.         tempSrcRect.top = srcFrameP->frameRect.bottom - topClip;
  994.         
  995.             // Position dest rect at top side //
  996.         tempDstRect.top = dstRect.top;
  997.         tempDstRect.bottom = dstRect.top + topClip;
  998.         tempDstRect.left = dstRect.left + leftClip;
  999.         tempDstRect.right = dstRect.right - rightClip;
  1000.         
  1001.         (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, 
  1002.             &tempSrcRect, &tempDstRect);
  1003.         
  1004.         
  1005.         if (rightClip)    // Draw top-right piece //
  1006.         {
  1007.                 // Wrap source rect to lower-left corner //
  1008.             tempSrcRect.bottom = srcFrameP->frameRect.bottom;
  1009.             tempSrcRect.left = srcFrameP->frameRect.left;
  1010.             tempSrcRect.right = srcFrameP->frameRect.left + rightClip;
  1011.             tempSrcRect.top = srcFrameP->frameRect.bottom - topClip;
  1012.             
  1013.                 // Position dest rect at top-right corner //
  1014.             tempDstRect.top = dstRect.top;
  1015.             tempDstRect.right = dstRect.right;
  1016.             tempDstRect.bottom = dstRect.top + topClip;
  1017.             tempDstRect.left = dstRect.right - rightClip;
  1018.             
  1019.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, 
  1020.                 &tempSrcRect, &tempDstRect);
  1021.         }
  1022.     }
  1023.     
  1024.     
  1025.         // Draw middle section, starting at left and going right //
  1026.     
  1027.     if (leftClip)    // Draw left piece //
  1028.     {
  1029.             // Wrap source rect to right side //
  1030.         tempSrcRect.top = srcRect.top;                // Copy clipped source rect
  1031.         tempSrcRect.bottom = srcRect.bottom;
  1032.         tempSrcRect.right = srcFrameP->frameRect.right;
  1033.         tempSrcRect.left = srcFrameP->frameRect.right - leftClip;
  1034.         
  1035.             // Position dest rect at left side //
  1036.         tempDstRect.left = dstRect.left;
  1037.         tempDstRect.right = dstRect.left + leftClip;
  1038.         tempDstRect.top = dstRect.top + topClip;
  1039.         tempDstRect.bottom = dstRect.bottom - bottomClip;
  1040.         
  1041.         (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, 
  1042.             &tempSrcRect, &tempDstRect);
  1043.     }
  1044.     
  1045.     
  1046.             // Draw main middle piece (not wrapped) //
  1047.     
  1048.         // Position dest rect at middle //
  1049.     tempDstRect.left = dstRect.left + leftClip;
  1050.     tempDstRect.top = dstRect.top + topClip;
  1051.     tempDstRect.right = dstRect.right - rightClip;
  1052.     tempDstRect.bottom = dstRect.bottom - bottomClip;
  1053.     
  1054.     (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, 
  1055.         &srcRect, &tempDstRect);
  1056.     
  1057.     
  1058.     if (rightClip)    // Draw right piece //
  1059.     {
  1060.             // Wrap source rect to left side //
  1061.         tempSrcRect.top = srcRect.top;                // Copy clipped source rect
  1062.         tempSrcRect.bottom = srcRect.bottom;
  1063.         tempSrcRect.left = srcFrameP->frameRect.left;
  1064.         tempSrcRect.right = srcFrameP->frameRect.left + rightClip;
  1065.         
  1066.             // Position dest rect at right side //
  1067.         tempDstRect.right = dstRect.right;
  1068.         tempDstRect.left = dstRect.right - rightClip;
  1069.         tempDstRect.top = dstRect.top + topClip;
  1070.         tempDstRect.bottom = dstRect.bottom - bottomClip;
  1071.         
  1072.         (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, 
  1073.             &tempSrcRect, &tempDstRect);
  1074.     }
  1075.     
  1076.     
  1077.     
  1078.         // Draw bottom section, starting at left and going right //
  1079.     
  1080.     if (bottomClip)
  1081.     {
  1082.         if (leftClip)     // Draw bottom-left piece //
  1083.         {
  1084.                 // Wrap source rect to upper-right corner //
  1085.             tempSrcRect.top = srcFrameP->frameRect.top;
  1086.             tempSrcRect.right = srcFrameP->frameRect.right;
  1087.             tempSrcRect.bottom = srcFrameP->frameRect.top + bottomClip;
  1088.             tempSrcRect.left = srcFrameP->frameRect.right - leftClip;
  1089.             
  1090.                 // Position dest rect at bottom-left corner //
  1091.             tempDstRect.bottom = dstRect.bottom;
  1092.             tempDstRect.left = dstRect.left;
  1093.             tempDstRect.top = dstRect.bottom - bottomClip;
  1094.             tempDstRect.right = dstRect.left + leftClip;
  1095.             
  1096.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, 
  1097.                 &tempSrcRect, &tempDstRect);
  1098.         }
  1099.         
  1100.         
  1101.             // Draw bottom piece //
  1102.         
  1103.             // Wrap source rect to top side //
  1104.         tempSrcRect.right = srcRect.right;                // Copy clipped source rect
  1105.         tempSrcRect.left = srcRect.left;
  1106.         tempSrcRect.top = srcFrameP->frameRect.top;
  1107.         tempSrcRect.bottom = srcFrameP->frameRect.top + bottomClip;
  1108.         
  1109.             // Position dest rect at bottom side //
  1110.         tempDstRect.bottom = dstRect.bottom;
  1111.         tempDstRect.top = dstRect.bottom - bottomClip;
  1112.         tempDstRect.left = dstRect.left + leftClip;
  1113.         tempDstRect.right = dstRect.right - rightClip;
  1114.         
  1115.         (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, 
  1116.             &tempSrcRect, &tempDstRect);
  1117.  
  1118.         
  1119.         if (rightClip)    // Draw bottom-right piece //
  1120.         {
  1121.                 // Wrap source rect to upper-left corner //
  1122.             tempSrcRect.top = srcFrameP->frameRect.top;
  1123.             tempSrcRect.left = srcFrameP->frameRect.left;
  1124.             tempSrcRect.bottom = srcFrameP->frameRect.top + bottomClip;
  1125.             tempSrcRect.right = srcFrameP->frameRect.left + rightClip;
  1126.             
  1127.                 // Position dest rect at bottom-right corner //
  1128.             tempDstRect.bottom = dstRect.bottom;
  1129.             tempDstRect.right = dstRect.right;
  1130.             tempDstRect.top = dstRect.bottom - bottomClip;
  1131.             tempDstRect.left = dstRect.right - rightClip;
  1132.             
  1133.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, 
  1134.                 &tempSrcRect, &tempDstRect);
  1135.         }
  1136.     }
  1137. }
  1138.  
  1139.  
  1140. ///--------------------------------------------------------------------------------------
  1141. //    SWCheckWrappedIdleSpriteOverlap - same as SWCheckIdleSpriteOverlap, 
  1142. //    but for scrolling SpriteWorlds.
  1143. ///--------------------------------------------------------------------------------------
  1144.  
  1145. SW_FUNC void SWCheckWrappedIdleSpriteOverlap(
  1146.     SpriteWorldPtr            spriteWorldP,
  1147.     register SpritePtr        idleSpriteP,
  1148.     SpritePtr                headActiveSpriteP)
  1149. {
  1150.     Rect    *visScrollRectP = &spriteWorldP->visScrollRect;
  1151.     register SpriteLayerPtr curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  1152.     register SpritePtr curSpriteP = curSpriteLayerP->headSpriteP;
  1153.     
  1154.     register SpritePtr activeSpriteP = headActiveSpriteP;
  1155.     short    srcHorizOffset;
  1156.     short    srcVertOffset;
  1157.     
  1158.     SWAssert( spriteWorldP != NULL && idleSpriteP != NULL );
  1159.     
  1160.         // In case the first layer(s) have no sprites
  1161.     while (curSpriteP == NULL && activeSpriteP != NULL)
  1162.     {
  1163.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  1164.         curSpriteP = curSpriteLayerP->headSpriteP;
  1165.     }
  1166.     
  1167.     
  1168.         // iterate through the active sprites
  1169.     while (activeSpriteP != NULL)
  1170.     {
  1171.             // Skip all active sprites above the idle sprite
  1172.         while (curSpriteP != activeSpriteP)
  1173.         {
  1174.                 // Have we cycled through all active sprites below the idle sprite?
  1175.             if (curSpriteP == idleSpriteP)
  1176.                 return;
  1177.             
  1178.             
  1179.             curSpriteP = curSpriteP->nextSpriteP;
  1180.             
  1181.                 // Cycle curSpriteP through all the sprite layers
  1182.             while (curSpriteP == NULL)
  1183.             {
  1184.                 curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  1185.                 curSpriteP = curSpriteLayerP->headSpriteP;
  1186.             }
  1187.         }
  1188.         
  1189.         
  1190.             // do the sprites overlap?
  1191.         if ((idleSpriteP->oldFrameRect.top < activeSpriteP->destFrameRect.bottom) &&
  1192.              (idleSpriteP->oldFrameRect.bottom > activeSpriteP->destFrameRect.top) &&
  1193.              (idleSpriteP->oldFrameRect.left < activeSpriteP->destFrameRect.right) &&
  1194.              (idleSpriteP->oldFrameRect.right > activeSpriteP->destFrameRect.left))
  1195.         {
  1196.             Rect srcSectRect, dstSectRect;
  1197.             
  1198.                 // calculate the intersection between the idle sprite's destination
  1199.                 // rect, and the active sprite's delta rect
  1200.             dstSectRect.left =
  1201.                     SW_MAX(idleSpriteP->destFrameRect.left, activeSpriteP->destFrameRect.left);
  1202.             dstSectRect.top =
  1203.                     SW_MAX(idleSpriteP->destFrameRect.top, activeSpriteP->destFrameRect.top);
  1204.             dstSectRect.right =
  1205.                     SW_MIN(idleSpriteP->destFrameRect.right, activeSpriteP->destFrameRect.right);
  1206.             dstSectRect.bottom =
  1207.                     SW_MIN(idleSpriteP->destFrameRect.bottom, activeSpriteP->destFrameRect.bottom);
  1208.             
  1209.                 // Calculate the source rect
  1210.             srcSectRect = dstSectRect;
  1211.             
  1212.             srcHorizOffset = idleSpriteP->curFrameP->frameRect.left;
  1213.             srcVertOffset = idleSpriteP->curFrameP->frameRect.top;
  1214.             
  1215.             srcSectRect.left -= (idleSpriteP->destFrameRect.left - srcHorizOffset);
  1216.             srcSectRect.right -= (idleSpriteP->destFrameRect.left - srcHorizOffset);
  1217.             srcSectRect.top -= (idleSpriteP->destFrameRect.top - srcVertOffset);
  1218.             srcSectRect.bottom -= (idleSpriteP->destFrameRect.top  - srcVertOffset);
  1219.             
  1220.             
  1221.             
  1222.                 // Clip the sprite's dstSectRect with visScrollRect
  1223.             
  1224.             if (dstSectRect.top < visScrollRectP->top)
  1225.             {
  1226.                 srcSectRect.top += visScrollRectP->top - dstSectRect.top;
  1227.                 dstSectRect.top = visScrollRectP->top;
  1228.             }
  1229.             
  1230.             if (dstSectRect.bottom > visScrollRectP->bottom)
  1231.             {
  1232.                 srcSectRect.bottom += visScrollRectP->bottom - dstSectRect.bottom;
  1233.                 dstSectRect.bottom = visScrollRectP->bottom;
  1234.             }
  1235.             
  1236.             if (dstSectRect.left < visScrollRectP->left)
  1237.             {
  1238.                 srcSectRect.left += visScrollRectP->left - dstSectRect.left;
  1239.                 dstSectRect.left = visScrollRectP->left;
  1240.             }
  1241.             
  1242.             if (dstSectRect.right > visScrollRectP->right)
  1243.             {
  1244.                 srcSectRect.right += visScrollRectP->right - dstSectRect.right;
  1245.                 dstSectRect.right = visScrollRectP->right;
  1246.             }
  1247.             
  1248.  
  1249.                 // Make the sprite's dest rect local to the offscreen area
  1250.             dstSectRect.top -= spriteWorldP->vertScrollRectOffset;
  1251.             dstSectRect.bottom -= spriteWorldP->vertScrollRectOffset;
  1252.             dstSectRect.left -= spriteWorldP->horizScrollRectOffset;
  1253.             dstSectRect.right -= spriteWorldP->horizScrollRectOffset;
  1254.  
  1255.                 // copy a piece of the sprite image onto the back drop piece    
  1256.             SWDrawWrappedSprite(idleSpriteP, spriteWorldP->workFrameP,
  1257.                 &srcSectRect, &dstSectRect);
  1258.             
  1259.             if (idleSpriteP->isUnderTiles && spriteWorldP->tilingIsOn)
  1260.             {
  1261.                 dstSectRect.top += spriteWorldP->vertScrollRectOffset;
  1262.                 dstSectRect.bottom += spriteWorldP->vertScrollRectOffset;
  1263.                 dstSectRect.left += spriteWorldP->horizScrollRectOffset;
  1264.                 dstSectRect.right += spriteWorldP->horizScrollRectOffset;
  1265.                 SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect);
  1266.             }
  1267.         }
  1268.         
  1269.         activeSpriteP = activeSpriteP->nextActiveSpriteP;
  1270.     }
  1271. }
  1272.  
  1273.  
  1274. ///--------------------------------------------------------------------------------------
  1275. //    SWRedrawErasedIdleSprites - redraw an idle sprite if it was erased
  1276. //    when an active sprite overlapping it was erased.
  1277. ///--------------------------------------------------------------------------------------
  1278.  
  1279. SW_FUNC void SWRedrawErasedIdleSprites(
  1280.     SpriteWorldPtr    spriteWorldP,
  1281.     SpritePtr        headActiveSpriteP,
  1282.     SpritePtr        headIdleSpriteP)
  1283. {
  1284.     Rect        *visScrollRectP = &spriteWorldP->visScrollRect;
  1285.     register     SpritePtr activeSpriteP;
  1286.     register    SpritePtr idleSpriteP;
  1287.     short        srcHorizOffset;
  1288.     short        srcVertOffset;
  1289.     
  1290.     SWAssert( spriteWorldP != NULL );
  1291.     
  1292.     idleSpriteP = headIdleSpriteP;
  1293.     
  1294.         // iterate through the idle sprites
  1295.     while (idleSpriteP != NULL)
  1296.     {
  1297.         activeSpriteP = headActiveSpriteP;
  1298.         
  1299.             // iterate through the active sprites
  1300.         while (activeSpriteP != NULL)
  1301.         {
  1302.                 // did the sprites overlap?
  1303.             if ((idleSpriteP->oldFrameRect.top < activeSpriteP->oldFrameRect.bottom) &&
  1304.                  (idleSpriteP->oldFrameRect.bottom > activeSpriteP->oldFrameRect.top) &&
  1305.                  (idleSpriteP->oldFrameRect.left < activeSpriteP->oldFrameRect.right) &&
  1306.                  (idleSpriteP->oldFrameRect.right > activeSpriteP->oldFrameRect.left))
  1307.             {
  1308.                 Rect srcSectRect, dstSectRect;
  1309.                 
  1310.                     // calculate the intersection between the idle sprite's old
  1311.                     // rect and the active sprite's old rect
  1312.                 dstSectRect.left =
  1313.                         SW_MAX(idleSpriteP->oldFrameRect.left, activeSpriteP->oldFrameRect.left);
  1314.                 dstSectRect.top =
  1315.                         SW_MAX(idleSpriteP->oldFrameRect.top, activeSpriteP->oldFrameRect.top);
  1316.                 dstSectRect.right =
  1317.                         SW_MIN(idleSpriteP->oldFrameRect.right, activeSpriteP->oldFrameRect.right);
  1318.                 dstSectRect.bottom =
  1319.                         SW_MIN(idleSpriteP->oldFrameRect.bottom, activeSpriteP->oldFrameRect.bottom);
  1320.                 
  1321.                     // Calculate the source rect
  1322.                 srcSectRect = dstSectRect;
  1323.                 
  1324.                 srcHorizOffset = idleSpriteP->curFrameP->frameRect.left;
  1325.                 srcVertOffset = idleSpriteP->curFrameP->frameRect.top;
  1326.                 
  1327.                 srcSectRect.left -= (idleSpriteP->oldFrameRect.left - srcHorizOffset);
  1328.                 srcSectRect.right -= (idleSpriteP->oldFrameRect.left - srcHorizOffset);
  1329.                 srcSectRect.top -= (idleSpriteP->oldFrameRect.top - srcVertOffset);
  1330.                 srcSectRect.bottom -= (idleSpriteP->oldFrameRect.top  - srcVertOffset);
  1331.                 
  1332.                 
  1333.                     // Clip the sprite's dstSectRect with visScrollRect
  1334.                 
  1335.                 if (dstSectRect.top < visScrollRectP->top)
  1336.                 {
  1337.                     srcSectRect.top += visScrollRectP->top - dstSectRect.top;
  1338.                     dstSectRect.top = visScrollRectP->top;
  1339.                 }
  1340.                 
  1341.                 if (dstSectRect.bottom > visScrollRectP->bottom)
  1342.                 {
  1343.                     srcSectRect.bottom += visScrollRectP->bottom - dstSectRect.bottom;
  1344.                     dstSectRect.bottom = visScrollRectP->bottom;
  1345.                 }
  1346.                 
  1347.                 if (dstSectRect.left < visScrollRectP->left)
  1348.                 {
  1349.                     srcSectRect.left += visScrollRectP->left - dstSectRect.left;
  1350.                     dstSectRect.left = visScrollRectP->left;
  1351.                 }
  1352.                 
  1353.                 if (dstSectRect.right > visScrollRectP->right)
  1354.                 {
  1355.                     srcSectRect.right += visScrollRectP->right - dstSectRect.right;
  1356.                     dstSectRect.right = visScrollRectP->right;
  1357.                 }
  1358.                 
  1359.  
  1360.                     // Make the sprite's dest rect local to the offscreen area
  1361.                 dstSectRect.top -= spriteWorldP->vertScrollRectOffset;
  1362.                 dstSectRect.bottom -= spriteWorldP->vertScrollRectOffset;
  1363.                 dstSectRect.left -= spriteWorldP->horizScrollRectOffset;
  1364.                 dstSectRect.right -= spriteWorldP->horizScrollRectOffset;
  1365.  
  1366.                     // copy a piece of the sprite image onto the back drop piece    
  1367.                 SWDrawWrappedSprite(idleSpriteP, spriteWorldP->workFrameP,
  1368.                     &srcSectRect, &dstSectRect);
  1369.                 
  1370.                 if (idleSpriteP->isUnderTiles && spriteWorldP->tilingIsOn)
  1371.                 {
  1372.                     dstSectRect.top += spriteWorldP->vertScrollRectOffset;
  1373.                     dstSectRect.bottom += spriteWorldP->vertScrollRectOffset;
  1374.                     dstSectRect.left += spriteWorldP->horizScrollRectOffset;
  1375.                     dstSectRect.right += spriteWorldP->horizScrollRectOffset;
  1376.                     SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect);
  1377.                 }
  1378.             }
  1379.             
  1380.             activeSpriteP = activeSpriteP->nextActiveSpriteP;
  1381.         }
  1382.         
  1383.         idleSpriteP = idleSpriteP->nextIdleSpriteP;
  1384.     }
  1385. }
  1386.  
  1387.  
  1388. ///--------------------------------------------------------------------------------------
  1389. //    SWRedrawIdleSpritesInRect - used by SWAnimateScrollingSpriteWorld
  1390. ///--------------------------------------------------------------------------------------
  1391.  
  1392. SW_FUNC void SWRedrawIdleSpritesInRect(
  1393.     SpriteWorldPtr    spriteWorldP,
  1394.     SpritePtr        headIdleSpriteP,
  1395.     Rect            *updateRect)
  1396. {
  1397.     Rect        *visScrollRectP = &spriteWorldP->visScrollRect;
  1398.     register    SpritePtr idleSpriteP;
  1399.     short        srcHorizOffset;
  1400.     short        srcVertOffset;
  1401.     
  1402.     SWAssert( spriteWorldP != NULL && updateRect != NULL );
  1403.  
  1404.     idleSpriteP = headIdleSpriteP;
  1405.     
  1406.         // iterate through the idle sprites
  1407.     while (idleSpriteP != NULL)
  1408.     {
  1409.             // is the idle sprite in the updateRect?
  1410.         if ((idleSpriteP->oldFrameRect.top < updateRect->bottom) &&
  1411.              (idleSpriteP->oldFrameRect.bottom > updateRect->top) &&
  1412.              (idleSpriteP->oldFrameRect.left < updateRect->right) &&
  1413.              (idleSpriteP->oldFrameRect.right > updateRect->left))
  1414.         {
  1415.             Rect srcSectRect, dstSectRect;
  1416.             
  1417.                 // calculate the intersection between the idle sprite's old
  1418.                 // rect and the updateRect
  1419.             dstSectRect.left =
  1420.                 SW_MAX(idleSpriteP->oldFrameRect.left, updateRect->left);
  1421.             dstSectRect.top =
  1422.                 SW_MAX(idleSpriteP->oldFrameRect.top, updateRect->top);
  1423.             dstSectRect.right =
  1424.                 SW_MIN(idleSpriteP->oldFrameRect.right, updateRect->right);
  1425.             dstSectRect.bottom =
  1426.                 SW_MIN(idleSpriteP->oldFrameRect.bottom, updateRect->bottom);
  1427.             
  1428.                 // Calculate the source rect
  1429.             srcSectRect = dstSectRect;
  1430.             
  1431.             srcHorizOffset = idleSpriteP->curFrameP->frameRect.left;
  1432.             srcVertOffset = idleSpriteP->curFrameP->frameRect.top;
  1433.             
  1434.             srcSectRect.left -= (idleSpriteP->oldFrameRect.left - srcHorizOffset);
  1435.             srcSectRect.right -= (idleSpriteP->oldFrameRect.left - srcHorizOffset);
  1436.             srcSectRect.top -= (idleSpriteP->oldFrameRect.top - srcVertOffset);
  1437.             srcSectRect.bottom -= (idleSpriteP->oldFrameRect.top  - srcVertOffset);
  1438.             
  1439.             
  1440.                 // Clip the sprite's dstSectRect with visScrollRect
  1441.             
  1442.             if (dstSectRect.top < visScrollRectP->top)
  1443.             {
  1444.                 srcSectRect.top += visScrollRectP->top - dstSectRect.top;
  1445.                 dstSectRect.top = visScrollRectP->top;
  1446.             }
  1447.             
  1448.             if (dstSectRect.bottom > visScrollRectP->bottom)
  1449.             {
  1450.                 srcSectRect.bottom += visScrollRectP->bottom - dstSectRect.bottom;
  1451.                 dstSectRect.bottom = visScrollRectP->bottom;
  1452.             }
  1453.             
  1454.             if (dstSectRect.left < visScrollRectP->left)
  1455.             {
  1456.                 srcSectRect.left += visScrollRectP->left - dstSectRect.left;
  1457.                 dstSectRect.left = visScrollRectP->left;
  1458.             }
  1459.             
  1460.             if (dstSectRect.right > visScrollRectP->right)
  1461.             {
  1462.                 srcSectRect.right += visScrollRectP->right - dstSectRect.right;
  1463.                 dstSectRect.right = visScrollRectP->right;
  1464.             }
  1465.             
  1466.  
  1467.                 // Make the sprite's dest rect local to the offscreen area
  1468.             dstSectRect.top -= spriteWorldP->vertScrollRectOffset;
  1469.             dstSectRect.bottom -= spriteWorldP->vertScrollRectOffset;
  1470.             dstSectRect.left -= spriteWorldP->horizScrollRectOffset;
  1471.             dstSectRect.right -= spriteWorldP->horizScrollRectOffset;
  1472.  
  1473.                 // copy a piece of the sprite image onto the back drop piece    
  1474.             SWDrawWrappedSprite(idleSpriteP, spriteWorldP->workFrameP,
  1475.                 &srcSectRect, &dstSectRect);
  1476.             
  1477.             if (idleSpriteP->isUnderTiles && spriteWorldP->tilingIsOn)
  1478.             {
  1479.                 dstSectRect.top += spriteWorldP->vertScrollRectOffset;
  1480.                 dstSectRect.bottom += spriteWorldP->vertScrollRectOffset;
  1481.                 dstSectRect.left += spriteWorldP->horizScrollRectOffset;
  1482.                 dstSectRect.right += spriteWorldP->horizScrollRectOffset;
  1483.                 SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect);
  1484.             }
  1485.         }
  1486.         
  1487.         idleSpriteP = idleSpriteP->nextIdleSpriteP;
  1488.     }
  1489. }
  1490.  
  1491.  
  1492. ///--------------------------------------------------------------------------------------
  1493. //  SWSetScrollingWorldMoveBounds
  1494. ///--------------------------------------------------------------------------------------
  1495.  
  1496.  
  1497. SW_FUNC void SWSetScrollingWorldMoveBounds(
  1498.     SpriteWorldPtr    spriteWorldP,
  1499.     Rect* scrollRectMoveBounds)
  1500. {
  1501.     SWAssert( spriteWorldP != NULL && scrollRectMoveBounds != NULL );
  1502.  
  1503.     spriteWorldP->scrollRectMoveBounds = *scrollRectMoveBounds;
  1504. }
  1505.  
  1506.  
  1507. ///--------------------------------------------------------------------------------------
  1508. //    SWSetScrollingWorldMoveProc
  1509. ///--------------------------------------------------------------------------------------
  1510.  
  1511. SW_FUNC void SWSetScrollingWorldMoveProc(
  1512.     SpriteWorldPtr spriteWorldP, 
  1513.     WorldMoveProcPtr worldMoveProcP, 
  1514.     SpritePtr followSpriteP)
  1515. {
  1516.     SWAssert( spriteWorldP != NULL && worldMoveProcP != NULL );
  1517.  
  1518.     spriteWorldP->worldMoveProc = worldMoveProcP;
  1519.     spriteWorldP->followSpriteP = followSpriteP;
  1520. }
  1521.  
  1522.  
  1523. ///--------------------------------------------------------------------------------------
  1524. //  SWSetSpriteWorldScrollDelta
  1525. ///--------------------------------------------------------------------------------------
  1526.  
  1527. SW_FUNC void SWSetSpriteWorldScrollDelta(
  1528.     SpriteWorldPtr    spriteWorldP,
  1529.     short            horizDelta,
  1530.     short            vertDelta)
  1531. {
  1532.     SWAssert( spriteWorldP != NULL );
  1533.  
  1534.     spriteWorldP->horizScrollDelta = horizDelta;
  1535.     spriteWorldP->vertScrollDelta = vertDelta;
  1536. }
  1537.  
  1538.  
  1539. ///--------------------------------------------------------------------------------------
  1540. //  SWMoveVisScrollRect - move visScrollRect to an absolute vertical and 
  1541. //    horizontal location
  1542. ///--------------------------------------------------------------------------------------
  1543.  
  1544.  
  1545. SW_FUNC void SWMoveVisScrollRect(
  1546.     SpriteWorldPtr    spriteWorldP,
  1547.     short            horizPos,
  1548.     short            vertPos)
  1549. {
  1550.     short    width, height;
  1551.  
  1552.     SWAssert( spriteWorldP != NULL );
  1553.     
  1554.     height = spriteWorldP->visScrollRect.bottom - spriteWorldP->visScrollRect.top;
  1555.     width = spriteWorldP->visScrollRect.right - spriteWorldP->visScrollRect.left;
  1556.     
  1557.     
  1558.             // Move visScrollRect and keep within moveBounds //
  1559.  
  1560.     
  1561.         // Move vertically
  1562.     if ((long)vertPos < spriteWorldP->scrollRectMoveBounds.top)
  1563.     {
  1564.         spriteWorldP->visScrollRect.bottom -= spriteWorldP->visScrollRect.top -
  1565.             spriteWorldP->scrollRectMoveBounds.top;
  1566.         spriteWorldP->visScrollRect.top = spriteWorldP->scrollRectMoveBounds.top;
  1567.     }
  1568.     else if ((long)vertPos + height > spriteWorldP->scrollRectMoveBounds.bottom)
  1569.     {
  1570.         spriteWorldP->visScrollRect.top -= spriteWorldP->visScrollRect.bottom -
  1571.             spriteWorldP->scrollRectMoveBounds.bottom;
  1572.         spriteWorldP->visScrollRect.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  1573.     }
  1574.     else
  1575.     {
  1576.         spriteWorldP->visScrollRect.top = vertPos;
  1577.         spriteWorldP->visScrollRect.bottom = vertPos + height;
  1578.     }
  1579.     
  1580.     
  1581.         // Move horizontally
  1582.     if ((long)horizPos < spriteWorldP->scrollRectMoveBounds.left)
  1583.     {
  1584.         spriteWorldP->visScrollRect.right -= spriteWorldP->visScrollRect.left -
  1585.             spriteWorldP->scrollRectMoveBounds.left;
  1586.         spriteWorldP->visScrollRect.left = spriteWorldP->scrollRectMoveBounds.left;
  1587.     }
  1588.     else if ((long)horizPos + width > spriteWorldP->scrollRectMoveBounds.right)
  1589.     {
  1590.         spriteWorldP->visScrollRect.left -= spriteWorldP->visScrollRect.right -
  1591.             spriteWorldP->scrollRectMoveBounds.right;
  1592.         spriteWorldP->visScrollRect.right = spriteWorldP->scrollRectMoveBounds.right;
  1593.     }
  1594.     else
  1595.     {
  1596.         spriteWorldP->visScrollRect.left = horizPos;
  1597.         spriteWorldP->visScrollRect.right = horizPos + width;
  1598.     }
  1599.     
  1600.     
  1601.     SWCalculateOffscreenScrollRect(spriteWorldP);
  1602. }
  1603.  
  1604.  
  1605. ///--------------------------------------------------------------------------------------
  1606. //  SWOffsetVisScrollRect - move visScrollRect to an absolute vertical and 
  1607. //    horizontal location, while keeping within the bounds of scrollRectMoveBounds
  1608. ///--------------------------------------------------------------------------------------
  1609.  
  1610. SW_FUNC void SWOffsetVisScrollRect(
  1611.     SpriteWorldPtr    spriteWorldP,
  1612.     short            horizOffset,
  1613.     short            vertOffset)
  1614. {
  1615.             // Move visScrollRect and keep within moveBounds //
  1616.  
  1617.     SWAssert( spriteWorldP != NULL );
  1618.  
  1619.         // Move vertically
  1620.     if ((long)spriteWorldP->visScrollRect.top + vertOffset <
  1621.             spriteWorldP->scrollRectMoveBounds.top)
  1622.     {
  1623.         spriteWorldP->visScrollRect.bottom -= spriteWorldP->visScrollRect.top -
  1624.             spriteWorldP->scrollRectMoveBounds.top;
  1625.         spriteWorldP->visScrollRect.top = spriteWorldP->scrollRectMoveBounds.top;
  1626.     }
  1627.     else if ((long)spriteWorldP->visScrollRect.bottom + vertOffset >
  1628.             spriteWorldP->scrollRectMoveBounds.bottom)
  1629.     {
  1630.         spriteWorldP->visScrollRect.top -= spriteWorldP->visScrollRect.bottom -
  1631.             spriteWorldP->scrollRectMoveBounds.bottom;
  1632.         spriteWorldP->visScrollRect.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  1633.     }
  1634.     else
  1635.     {
  1636.         spriteWorldP->visScrollRect.top += vertOffset;
  1637.         spriteWorldP->visScrollRect.bottom += vertOffset;
  1638.     }
  1639.     
  1640.     
  1641.         // Move horizontally
  1642.     if ((long)spriteWorldP->visScrollRect.left + horizOffset <
  1643.             spriteWorldP->scrollRectMoveBounds.left)
  1644.     {
  1645.         spriteWorldP->visScrollRect.right -= spriteWorldP->visScrollRect.left -
  1646.             spriteWorldP->scrollRectMoveBounds.left;
  1647.         spriteWorldP->visScrollRect.left = spriteWorldP->scrollRectMoveBounds.left;
  1648.     }
  1649.     else if ((long)spriteWorldP->visScrollRect.right + horizOffset >
  1650.             spriteWorldP->scrollRectMoveBounds.right)
  1651.     {
  1652.         spriteWorldP->visScrollRect.left -= spriteWorldP->visScrollRect.right -
  1653.             spriteWorldP->scrollRectMoveBounds.right;
  1654.         spriteWorldP->visScrollRect.right = spriteWorldP->scrollRectMoveBounds.right;
  1655.     }
  1656.     else
  1657.     {
  1658.         spriteWorldP->visScrollRect.left += horizOffset;
  1659.         spriteWorldP->visScrollRect.right += horizOffset;
  1660.     }
  1661.     
  1662.     
  1663.     SWCalculateOffscreenScrollRect(spriteWorldP);
  1664. }
  1665.  
  1666.  
  1667. ///--------------------------------------------------------------------------------------
  1668. //  SWCalculateOffscreenScrollRect (wrap offscreenScrollRect in the work area)
  1669. ///--------------------------------------------------------------------------------------
  1670.  
  1671.  
  1672. SW_FUNC void SWCalculateOffscreenScrollRect(
  1673.     SpriteWorldPtr spriteWorldP)
  1674. {
  1675.     Rect *offscreenScrollRectP = &spriteWorldP->offscreenScrollRect;
  1676.     Rect *visScrollRectP = &spriteWorldP->visScrollRect;
  1677.     
  1678.     SWAssert( spriteWorldP != NULL );
  1679.     
  1680.     spriteWorldP->vertScrollRectOffset = spriteWorldP->backRect.bottom * 
  1681.         (visScrollRectP->top / spriteWorldP->backRect.bottom);
  1682.     
  1683.     spriteWorldP->horizScrollRectOffset = spriteWorldP->backRect.right *
  1684.         (visScrollRectP->left / spriteWorldP->backRect.right);
  1685.     
  1686.     
  1687.     offscreenScrollRectP->top = visScrollRectP->top - 
  1688.             spriteWorldP->vertScrollRectOffset;
  1689.     offscreenScrollRectP->bottom = visScrollRectP->bottom - 
  1690.             spriteWorldP->vertScrollRectOffset;
  1691.     offscreenScrollRectP->left = visScrollRectP->left - 
  1692.             spriteWorldP->horizScrollRectOffset;
  1693.     offscreenScrollRectP->right = visScrollRectP->right - 
  1694.             spriteWorldP->horizScrollRectOffset;
  1695. }
  1696.  
  1697.  
  1698.