home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / SpriteWorld 2.2 / SpriteWorld files / Sources / Scrolling.c < prev    next >
Encoding:
Text File  |  1999-01-12  |  86.0 KB  |  2,675 lines  |  [TEXT/CWIE]

  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. extern    SpritePtr        gCurrentSpriteBeingDrawn;
  47.  
  48.  
  49. ///--------------------------------------------------------------------------------------
  50. //    SWUpdateScrollingWindow
  51. ///--------------------------------------------------------------------------------------
  52.  
  53. SW_FUNC void SWUpdateScrollingWindow(
  54.     SpriteWorldPtr spriteWorldP)
  55. {
  56.     GWorldPtr        holdGWorld;
  57.     GDHandle        holdGDH;
  58.     
  59.     SW_ASSERT(spriteWorldP != NULL);
  60.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  61.     SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
  62.     
  63.     GetGWorld( &holdGWorld, &holdGDH );
  64.     
  65.     SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  66.     
  67.     if ( spriteWorldP->usingVBL )
  68.     {  
  69.         spriteWorldP->vblTaskRec.hasVBLFired = false;
  70.         while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  71.         {}
  72.     }
  73.     
  74.         // Copy visScrollRect to window
  75.     SWWrapWorldToScreen(spriteWorldP);
  76.                                     
  77.     SetGWorld( holdGWorld, holdGDH );
  78. }
  79.  
  80.  
  81. ///--------------------------------------------------------------------------------------
  82. //    SWUpdateScrollingSpriteWorld - should be called at the beginning of 
  83. //    a scrolling animation, so that idle sprites are set up correctly.
  84. ///--------------------------------------------------------------------------------------
  85.  
  86. SW_FUNC void SWUpdateScrollingSpriteWorld(
  87.     SpriteWorldPtr spriteWorldP,
  88.     Boolean updateWindow)
  89. {
  90.     UpdateRectStructPtr            curRectStructP,
  91.                                 nextRectStructP;
  92.     register SpriteLayerPtr        curSpriteLayerP;
  93.     register SpritePtr            curSpriteP;
  94.     short                        curTileLayer;
  95.     Rect                        *visScrollRectP = &spriteWorldP->visScrollRect;
  96.     Rect                        srcFrameRect, tempDstRect;
  97.     GWorldPtr                    saveGWorld;
  98.     GDHandle                    saveGDH;
  99.     
  100.     SW_ASSERT(spriteWorldP != NULL);
  101.     SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
  102.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  103.     SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
  104.     
  105.     GetGWorld( &saveGWorld, &saveGDH );
  106.  
  107.         // Copy the background into the work area
  108.     SetGWorld(spriteWorldP->workFrameP->framePort, nil);
  109.     (*spriteWorldP->offscreenDrawProc)(spriteWorldP->backFrameP,
  110.                         spriteWorldP->workFrameP,
  111.                         &spriteWorldP->backFrameP->frameRect,
  112.                         &spriteWorldP->workFrameP->frameRect);
  113.     
  114.             // Call the postEraseCallBack
  115.     if (spriteWorldP->postEraseCallBack != NULL)
  116.         (*spriteWorldP->postEraseCallBack)(spriteWorldP);
  117.  
  118.     
  119.         // Build the current frame of the animation in the work area
  120.     
  121.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  122.     curTileLayer = 0;
  123.  
  124.         // iterate through the layers in this world
  125.     while (curSpriteLayerP != NULL)
  126.     {
  127.         curSpriteP = curSpriteLayerP->headSpriteP;
  128.         
  129.         if (curSpriteLayerP->tileLayer > curTileLayer)
  130.             curTileLayer = curSpriteLayerP->tileLayer;
  131.  
  132.             // iterate through the sprites in this layer
  133.         while (curSpriteP != NULL)
  134.         {
  135.             SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
  136.             curSpriteP->tileDepth = curTileLayer;
  137.             
  138.             if (curSpriteP->isVisible)
  139.             {
  140.                 curSpriteP->destOffscreenRect = curSpriteP->destFrameRect;
  141.                 srcFrameRect = curSpriteP->curFrameP->frameRect;
  142.                     
  143.                     
  144.                     // Clip the sprite's destOffscreenRect with visScrollRect
  145.                     // We use the destOffscreenRect both for drawing and erasing later
  146.                 if (curSpriteP->destOffscreenRect.top < visScrollRectP->top)
  147.                 {
  148.                     srcFrameRect.top += visScrollRectP->top - 
  149.                             curSpriteP->destOffscreenRect.top;
  150.                     curSpriteP->destOffscreenRect.top =  visScrollRectP->top;
  151.                 }
  152.  
  153.                 if (curSpriteP->destOffscreenRect.bottom > visScrollRectP->bottom)
  154.                 {
  155.                     srcFrameRect.bottom += visScrollRectP->bottom - 
  156.                             curSpriteP->destOffscreenRect.bottom;
  157.                     curSpriteP->destOffscreenRect.bottom = visScrollRectP->bottom;
  158.                 }
  159.                 
  160.                 if (curSpriteP->destOffscreenRect.left < visScrollRectP->left)
  161.                 {
  162.                     srcFrameRect.left += visScrollRectP->left - 
  163.                             curSpriteP->destOffscreenRect.left;
  164.                     curSpriteP->destOffscreenRect.left = visScrollRectP->left;
  165.                 }
  166.             
  167.                 if (curSpriteP->destOffscreenRect.right > visScrollRectP->right)
  168.                 {
  169.                     srcFrameRect.right += visScrollRectP->right - 
  170.                             curSpriteP->destOffscreenRect.right;
  171.                     curSpriteP->destOffscreenRect.right = visScrollRectP->right;
  172.                 }
  173.                 
  174.                 curSpriteP->destRectIsVisible =
  175.                         ( (curSpriteP->destOffscreenRect.right >
  176.                         curSpriteP->destOffscreenRect.left) &&
  177.                         (curSpriteP->destOffscreenRect.bottom >
  178.                         curSpriteP->destOffscreenRect.top) );
  179.                 
  180.                 
  181.                     // Is sprite visible on the screen?
  182.                 if (curSpriteP->destRectIsVisible)
  183.                 {
  184.                         // Make the sprite's rect local to the offscreen area
  185.                     curSpriteP->destOffscreenRect.top -= spriteWorldP->vertScrollRectOffset;
  186.                     curSpriteP->destOffscreenRect.bottom -= spriteWorldP->vertScrollRectOffset;
  187.                     curSpriteP->destOffscreenRect.left -= spriteWorldP->horizScrollRectOffset;
  188.                     curSpriteP->destOffscreenRect.right -= spriteWorldP->horizScrollRectOffset;
  189.                     
  190.                     gCurrentSpriteBeingDrawn = curSpriteP;
  191.                     
  192.                         // Draw the sprite in the work area
  193.                     SWDrawWrappedSprite(curSpriteP, spriteWorldP->workFrameP,
  194.                         &srcFrameRect, &curSpriteP->destOffscreenRect);
  195.                         
  196.                     gCurrentSpriteBeingDrawn = NULL;
  197.                     
  198.                         // Draw tiles above sprite
  199.                     if (spriteWorldP->tilingIsOn &&
  200.                         curSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  201.                     {
  202.                         tempDstRect = curSpriteP->destOffscreenRect;
  203.                         tempDstRect.top += spriteWorldP->vertScrollRectOffset;
  204.                         tempDstRect.bottom += spriteWorldP->vertScrollRectOffset;
  205.                         tempDstRect.left += spriteWorldP->horizScrollRectOffset;
  206.                         tempDstRect.right += spriteWorldP->horizScrollRectOffset;
  207.                         SWDrawTilesAboveSprite(spriteWorldP, &tempDstRect, curSpriteP->tileDepth);
  208.                     }
  209.                 }
  210.             }
  211.             
  212.                 // Set last rect to current rect
  213.             curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
  214.             curSpriteP->oldOffscreenRect = curSpriteP->destOffscreenRect;
  215.             curSpriteP->oldRectIsVisible = curSpriteP->destRectIsVisible;
  216.             
  217.             curSpriteP->needsToBeDrawn = false;
  218.             curSpriteP->needsToBeErased = false;
  219.             
  220.             curSpriteP = curSpriteP->nextSpriteP;
  221.         }
  222.         
  223.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  224.     }
  225.     
  226.     spriteWorldP->oldVisScrollRect = spriteWorldP->visScrollRect;
  227.     
  228.     
  229.             // Call the postDrawCallBack
  230.     if (spriteWorldP->postDrawCallBack != NULL)
  231.         (*spriteWorldP->postDrawCallBack)(spriteWorldP);
  232.  
  233.     
  234.         // Copy the work area to the window
  235.     if (updateWindow)
  236.     {
  237.         SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  238.         
  239.         if (spriteWorldP->usingVBL)
  240.         {  
  241.             spriteWorldP->vblTaskRec.hasVBLFired = false;
  242.             while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  243.             {}
  244.         }
  245.         
  246.             // Copy visScrollRect to window
  247.         SWWrapWorldToScreen(spriteWorldP);
  248.     }
  249.     
  250.         // dispose of flagged background rects
  251.     nextRectStructP = spriteWorldP->headUpdateRectP;
  252.     while ( nextRectStructP != NULL )
  253.     {
  254.         curRectStructP = nextRectStructP;
  255.         nextRectStructP = curRectStructP->nextRectStructP;
  256.         DisposePtr( (Ptr)curRectStructP );
  257.     }
  258.     spriteWorldP->headUpdateRectP = NULL;
  259.     
  260.     spriteWorldP->numTilesChanged = 0;
  261.     
  262.     SetGWorld( saveGWorld, saveGDH );
  263. }
  264.  
  265.  
  266. ///--------------------------------------------------------------------------------------
  267. //    SWProcessScrollingSpriteWorld
  268. ///--------------------------------------------------------------------------------------
  269.  
  270. SW_FUNC void SWProcessScrollingSpriteWorld(
  271.     SpriteWorldPtr spriteWorldP)
  272. {
  273.  
  274.         // Process the sprites
  275.     SWProcessSpriteWorld(spriteWorldP);
  276.     if ( !spriteWorldP->frameHasOccurred )
  277.     {
  278.         return;
  279.     }
  280.  
  281.     
  282.         // Call the scrolling world move proc
  283.     if (spriteWorldP->worldMoveProc != NULL)
  284.     {
  285.         (*spriteWorldP->worldMoveProc)(spriteWorldP, spriteWorldP->followSpriteP);
  286.     }
  287.     
  288.     
  289.         // Move visScrollRect
  290.     if (spriteWorldP->horizScrollDelta || spriteWorldP->vertScrollDelta)
  291.     {
  292.         SWOffsetVisScrollRect(spriteWorldP, 
  293.             spriteWorldP->horizScrollDelta, 
  294.             spriteWorldP->vertScrollDelta);
  295.     }
  296. }
  297.  
  298.  
  299. ///--------------------------------------------------------------------------------------
  300. //    SWAnimateScrollingSpriteWorld
  301. ///--------------------------------------------------------------------------------------
  302.  
  303. SW_FUNC void SWAnimateScrollingSpriteWorld(
  304.     SpriteWorldPtr spriteWorldP)
  305. {
  306.     UpdateRectStructPtr            curRectStructP,
  307.                                 nextRectStructP;
  308.     register SpriteLayerPtr     curSpriteLayerP;
  309.     register SpritePtr             curSpriteP;
  310.     SpritePtr                     headActiveSpriteP = NULL;    // Tail of active sprite list
  311.     SpritePtr                    headIdleSpriteP = NULL;        // Tail of idle sprite list
  312.     SpritePtr                     curActiveSpriteP = NULL;
  313.     SpritePtr                     curIdleSpriteP = NULL;
  314.     Rect                        *visScrollRectP = &spriteWorldP->visScrollRect;
  315.     Rect                        tempDstRect, tempSrcRect;
  316.     short                        hScrollDelta, vScrollDelta, curTileLayer;
  317.     
  318.     SW_ASSERT(spriteWorldP != NULL);
  319.     SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
  320.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  321.     SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
  322.     
  323.     if (!spriteWorldP->frameHasOccurred)
  324.         return;
  325.     
  326.     
  327.     hScrollDelta = visScrollRectP->left - spriteWorldP->oldVisScrollRect.left;
  328.     vScrollDelta = visScrollRectP->top - spriteWorldP->oldVisScrollRect.top;
  329.     
  330.     
  331.             // Add the deadSpriteLayer if there are any Sprites in it.
  332.     if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
  333.     {
  334.         SWAddSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
  335.     }
  336.     
  337.     
  338.         // Update tiles as we scroll if tiling is turned on
  339.     if (spriteWorldP->tilingIsOn)
  340.     {
  341.             // VisScrollRect moved horizontally
  342.         if (hScrollDelta)
  343.         {
  344.                 // Get rect of new vertical section to update
  345.             tempDstRect = *visScrollRectP;
  346.             
  347.                 // Moved left
  348.             if (hScrollDelta < 0)
  349.             {
  350.                 if (tempDstRect.right > spriteWorldP->oldVisScrollRect.left)
  351.                     tempDstRect.right = spriteWorldP->oldVisScrollRect.left;
  352.             }
  353.             else    // Moved right
  354.             {
  355.                 if (tempDstRect.left < spriteWorldP->oldVisScrollRect.right)
  356.                     tempDstRect.left = spriteWorldP->oldVisScrollRect.right;
  357.             }
  358.     
  359.             (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &tempDstRect, true);
  360.             SWWrapRectToWorkArea(spriteWorldP, &tempDstRect);
  361.             
  362.             
  363.                 // Did VisScrollRect moved diagonally?
  364.             if (vScrollDelta)
  365.             {
  366.                     // Get rect of new horizontal section to update
  367.                 tempDstRect = spriteWorldP->visScrollRect;
  368.                 
  369.                     // Moved up
  370.                 if (vScrollDelta < 0)
  371.                 {
  372.                     if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.top)
  373.                         tempDstRect.bottom = spriteWorldP->oldVisScrollRect.top;
  374.                 }
  375.                 else    // Moved down
  376.                 {
  377.                     if (tempDstRect.top < spriteWorldP->oldVisScrollRect.bottom)
  378.                         tempDstRect.top = spriteWorldP->oldVisScrollRect.bottom;
  379.                 }
  380.                 
  381.                     // Clip off the part we've already updated
  382.                 if (hScrollDelta < 0)
  383.                 {
  384.                     if (tempDstRect.left < spriteWorldP->oldVisScrollRect.left)
  385.                         tempDstRect.left = spriteWorldP->oldVisScrollRect.left;
  386.                 }
  387.                 else
  388.                 {
  389.                     if (tempDstRect.right > spriteWorldP->oldVisScrollRect.right)
  390.                         tempDstRect.right = spriteWorldP->oldVisScrollRect.right;
  391.                 }
  392.                 
  393.                     // We pass false here to avoid a bug which occured in the
  394.                     // tile optimizing code when updating tiles twice in one frame
  395.                 if (tempDstRect.right > tempDstRect.left)
  396.                 {
  397.                     (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &tempDstRect, false);
  398.                     SWWrapRectToWorkArea(spriteWorldP, &tempDstRect);
  399.                 }
  400.             }
  401.         }        // VisScrollRect moved vertically only
  402.         else if (vScrollDelta)
  403.         {
  404.                 // Get rect of new horizontal section to update
  405.             tempDstRect = *visScrollRectP;
  406.             
  407.                 // Moved up
  408.             if (vScrollDelta < 0)
  409.             {
  410.                 if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.top)
  411.                     tempDstRect.bottom = spriteWorldP->oldVisScrollRect.top;
  412.             }
  413.             else    // Moved down
  414.             {
  415.                 if (tempDstRect.top < spriteWorldP->oldVisScrollRect.bottom)
  416.                     tempDstRect.top = spriteWorldP->oldVisScrollRect.bottom;
  417.             }
  418.  
  419.             (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &tempDstRect, true);
  420.             SWWrapRectToWorkArea(spriteWorldP, &tempDstRect);
  421.         }
  422.     }
  423.     
  424.     
  425.     //-----------------erase the sprites--------------------
  426.     
  427.         // Set the port to the work area so we can draw in it
  428.     SetGWorld(spriteWorldP->workFrameP->framePort, nil);
  429.     
  430.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;    
  431.     curTileLayer = 0;
  432.     
  433.         // iterate through the layers in this world
  434.     while (curSpriteLayerP != NULL)
  435.     {
  436.         curSpriteP = curSpriteLayerP->headSpriteP;
  437.         
  438.         if (curSpriteLayerP->tileLayer > curTileLayer)
  439.             curTileLayer = curSpriteLayerP->tileLayer;
  440.         
  441.             // iterate through the sprites in this layer
  442.         while (curSpriteP != NULL)
  443.         {
  444.             SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
  445.             curSpriteP->tileDepth = curTileLayer;
  446.             
  447.                 // Clip the sprite's destOffscreenRect with visScrollRect.
  448.             if (curSpriteP->isVisible)
  449.             {
  450.                 curSpriteP->destOffscreenRect = curSpriteP->destFrameRect;
  451.                 curSpriteP->clippedSourceRect = curSpriteP->curFrameP->frameRect;
  452.                 
  453.  
  454.                 if (curSpriteP->destOffscreenRect.top < visScrollRectP->top)
  455.                 {
  456.                     curSpriteP->clippedSourceRect.top += visScrollRectP->top - 
  457.                             curSpriteP->destOffscreenRect.top;
  458.                     curSpriteP->destOffscreenRect.top = visScrollRectP->top;
  459.                 }
  460.                 
  461.                 if (curSpriteP->destOffscreenRect.bottom > visScrollRectP->bottom)
  462.                 {
  463.                     curSpriteP->clippedSourceRect.bottom += visScrollRectP->bottom - 
  464.                             curSpriteP->destOffscreenRect.bottom;
  465.                     curSpriteP->destOffscreenRect.bottom = visScrollRectP->bottom;
  466.                 }
  467.                 
  468.                 if (curSpriteP->destOffscreenRect.left < visScrollRectP->left)
  469.                 {
  470.                     curSpriteP->clippedSourceRect.left += visScrollRectP->left - 
  471.                             curSpriteP->destOffscreenRect.left;
  472.                     curSpriteP->destOffscreenRect.left = visScrollRectP->left;
  473.                 }
  474.                 
  475.                 if (curSpriteP->destOffscreenRect.right > visScrollRectP->right)
  476.                 {
  477.                     curSpriteP->clippedSourceRect.right += visScrollRectP->right - 
  478.                             curSpriteP->destOffscreenRect.right;
  479.                     curSpriteP->destOffscreenRect.right = visScrollRectP->right;
  480.                 }
  481.                 
  482.                 curSpriteP->destRectIsVisible =
  483.                         (curSpriteP->destOffscreenRect.right >
  484.                         curSpriteP->destOffscreenRect.left &&
  485.                         curSpriteP->destOffscreenRect.bottom >
  486.                         curSpriteP->destOffscreenRect.top);
  487.             }
  488.             
  489.             
  490.                 // Erase the sprites
  491.             if (curSpriteP->needsToBeDrawn && curSpriteP->isVisible ||
  492.                 curSpriteP->needsToBeErased && !curSpriteP->isVisible)
  493.             {
  494.                     // Was the sprite visible on the screen last frame?
  495.                 if (curSpriteP->oldRectIsVisible)
  496.                 {
  497.                         // Add sprite to active sprite list
  498.                     if (headActiveSpriteP == NULL)
  499.                         headActiveSpriteP = curSpriteP;
  500.                     
  501.                     if (curActiveSpriteP != NULL)
  502.                             curActiveSpriteP->nextActiveSpriteP = curSpriteP;
  503.                     
  504.                     curActiveSpriteP = curSpriteP;
  505.                     
  506.                     {
  507.                         short temp;
  508.                         
  509.                             // align left edge of oldOffscreenRect for erasing
  510.                         curSpriteP->oldOffscreenRect.left &=
  511.                             (spriteWorldP->workFrameP->leftAlignFactor);
  512.                         
  513.                             // align the right edge to long word boundary
  514.                         temp = curSpriteP->oldOffscreenRect.right &
  515.                             spriteWorldP->workFrameP->rightAlignFactor;
  516.                         if (temp != 0)
  517.                         {
  518.                             curSpriteP->oldOffscreenRect.right +=
  519.                                 (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  520.                         }
  521.  
  522.                             // align left edge of oldFrameRect - necessary for
  523.                             // deltaFrameRect below, used by idle sprite collision
  524.                         curSpriteP->oldFrameRect.left &=
  525.                             (spriteWorldP->workFrameP->leftAlignFactor);
  526.                         
  527.                             // align the right edge to long word boundary
  528.                         temp = curSpriteP->oldFrameRect.right &
  529.                             spriteWorldP->workFrameP->rightAlignFactor;
  530.                         if (temp != 0)
  531.                         {
  532.                             curSpriteP->oldFrameRect.right +=
  533.                                 (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  534.                         }
  535.                     }
  536.                     
  537.                         // union last rect and current rect - this is necessary for 
  538.                         // the proper redrawing of idle sprites
  539.                     curSpriteP->deltaFrameRect.top = 
  540.                         SW_MIN(curSpriteP->oldFrameRect.top, curSpriteP->destFrameRect.top);
  541.                     curSpriteP->deltaFrameRect.left = 
  542.                         SW_MIN(curSpriteP->oldFrameRect.left, curSpriteP->destFrameRect.left);
  543.                     curSpriteP->deltaFrameRect.bottom = 
  544.                         SW_MAX(curSpriteP->oldFrameRect.bottom, curSpriteP->destFrameRect.bottom);
  545.                     curSpriteP->deltaFrameRect.right = 
  546.                         SW_MAX(curSpriteP->oldFrameRect.right, curSpriteP->destFrameRect.right);
  547.                     
  548.                     
  549.                         // Erase the sprite from the work area
  550.                     SWEraseWrappedSprite(spriteWorldP, &curSpriteP->oldOffscreenRect);
  551.                 }
  552.                 else if (curSpriteP->destRectIsVisible)    // Sprite will be drawn
  553.                 {
  554.                         // Add sprite to active sprite list
  555.                     if (headActiveSpriteP == NULL)
  556.                         headActiveSpriteP = curSpriteP;
  557.                     
  558.                     if (curActiveSpriteP != NULL)
  559.                             curActiveSpriteP->nextActiveSpriteP = curSpriteP;
  560.                     
  561.                     curActiveSpriteP = curSpriteP;
  562.                 }
  563.             }
  564.             else if (curSpriteP->isVisible)        // Visible, idle sprites
  565.             {
  566.                 if (curSpriteP->oldRectIsVisible)
  567.                 {
  568.                         // Is idle sprite moving outside the visScrollRect?
  569.                     if ((hScrollDelta > 0 &&
  570.                         (curSpriteP->destFrameRect.left < visScrollRectP->left) &&
  571.                         (curSpriteP->destFrameRect.right > spriteWorldP->oldVisScrollRect.left)) ||
  572.                         (hScrollDelta < 0 &&
  573.                         (curSpriteP->destFrameRect.left < spriteWorldP->oldVisScrollRect.right) &&
  574.                         (curSpriteP->destFrameRect.right > visScrollRectP->right)) )
  575.                     {
  576.                             // Erase piece of idle sprite outside of visScrollRect
  577.                         tempDstRect = curSpriteP->oldFrameRect;
  578.                         
  579.                             // Get section of sprite outside visScrollRect
  580.                         if (hScrollDelta > 0)
  581.                         {
  582.                             if (tempDstRect.right > visScrollRectP->left)
  583.                                 tempDstRect.right = visScrollRectP->left;
  584.                         }
  585.                         else
  586.                         {
  587.                             if (tempDstRect.left < visScrollRectP->right)
  588.                                 tempDstRect.left = visScrollRectP->right;
  589.                         }
  590.                         
  591.                             // Clip tempDstRect with oldVisScrollRect
  592.                         if (tempDstRect.top < spriteWorldP->oldVisScrollRect.top)
  593.                             tempDstRect.top = spriteWorldP->oldVisScrollRect.top;
  594.                         if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.bottom)
  595.                             tempDstRect.bottom = spriteWorldP->oldVisScrollRect.bottom;
  596.                         if (tempDstRect.left < spriteWorldP->oldVisScrollRect.left)
  597.                             tempDstRect.left = spriteWorldP->oldVisScrollRect.left;
  598.                         if (tempDstRect.right > spriteWorldP->oldVisScrollRect.right)
  599.                             tempDstRect.right = spriteWorldP->oldVisScrollRect.right;
  600.                         
  601.                             // Make the rect local to the offscreen area
  602.                         tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  603.                         tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  604.                         tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  605.                         tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  606.                         
  607.                         SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
  608.                     }
  609.                     
  610.                         // Is idle sprite moving outside the visScrollRect?
  611.                     if ((vScrollDelta > 0 &&
  612.                         (curSpriteP->destFrameRect.top < visScrollRectP->top) &&
  613.                         (curSpriteP->destFrameRect.bottom > spriteWorldP->oldVisScrollRect.top)) ||
  614.                         (vScrollDelta < 0 &&
  615.                         (curSpriteP->destFrameRect.top < spriteWorldP->oldVisScrollRect.bottom) &&
  616.                         (curSpriteP->destFrameRect.bottom > visScrollRectP->bottom)) )
  617.                     {
  618.                             // Erase piece of idle sprite outside of visScrollRect
  619.                         tempDstRect = curSpriteP->oldFrameRect;
  620.                         
  621.                             // Get section of sprite outside visScrollRect
  622.                         if (vScrollDelta > 0)
  623.                         {
  624.                             if (tempDstRect.bottom > visScrollRectP->top)
  625.                                 tempDstRect.bottom = visScrollRectP->top;
  626.                         }
  627.                         else
  628.                         {
  629.                             if (tempDstRect.top < visScrollRectP->bottom)
  630.                                 tempDstRect.top = visScrollRectP->bottom;
  631.                         }
  632.                         
  633.                             // Clip tempDstRect with oldVisScrollRect
  634.                         if (tempDstRect.top < spriteWorldP->oldVisScrollRect.top)
  635.                             tempDstRect.top = spriteWorldP->oldVisScrollRect.top;
  636.                         if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.bottom)
  637.                             tempDstRect.bottom = spriteWorldP->oldVisScrollRect.bottom;
  638.                         if (tempDstRect.left < spriteWorldP->oldVisScrollRect.left)
  639.                             tempDstRect.left = spriteWorldP->oldVisScrollRect.left;
  640.                         if (tempDstRect.right > spriteWorldP->oldVisScrollRect.right)
  641.                             tempDstRect.right = spriteWorldP->oldVisScrollRect.right;
  642.                         
  643.                             // Make the rect local to the offscreen area
  644.                         tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  645.                         tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  646.                         tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  647.                         tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  648.                         
  649.                         SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
  650.                     }
  651.                 }
  652.                             
  653.                 
  654.                     // Is the idle sprite visible on the screen?
  655.                 if (curSpriteP->destRectIsVisible)
  656.                 {
  657.                         // Add sprite to idle sprite list
  658.                     if (headIdleSpriteP == NULL)
  659.                         headIdleSpriteP = curSpriteP;
  660.                     
  661.                     if (curIdleSpriteP != NULL)
  662.                         curIdleSpriteP->nextIdleSpriteP = curSpriteP;
  663.                     
  664.                     curIdleSpriteP = curSpriteP;
  665.                 }
  666.             }
  667.  
  668.             curSpriteP = curSpriteP->nextSpriteP;
  669.         }
  670.  
  671.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;    
  672.     }
  673.     
  674.     if (curActiveSpriteP != NULL)
  675.         curActiveSpriteP->nextActiveSpriteP = NULL;
  676.     
  677.     if (curIdleSpriteP != NULL)
  678.         curIdleSpriteP->nextIdleSpriteP = NULL;
  679.     
  680.  
  681.     
  682.         // This section of code iterates through the idle sprite list, drawing the tiny
  683.         // sliver of any idle sprites that have just entered the visScrollRect.
  684.     curIdleSpriteP = headIdleSpriteP;
  685.     while (curIdleSpriteP != NULL)
  686.     {
  687.             // Draw vertical piece of idle sprite if it is coming into the visScrollRect.
  688.         if ((vScrollDelta > 0 &&
  689.             (curIdleSpriteP->destFrameRect.top < visScrollRectP->bottom) &&
  690.             (curIdleSpriteP->destFrameRect.bottom > spriteWorldP->oldVisScrollRect.bottom) ) ||
  691.             (vScrollDelta < 0 &&
  692.             (curIdleSpriteP->destFrameRect.top < spriteWorldP->oldVisScrollRect.top) &&
  693.             (curIdleSpriteP->destFrameRect.bottom > visScrollRectP->top)) )
  694.         {
  695.             tempDstRect = curIdleSpriteP->destOffscreenRect;
  696.             tempSrcRect = curIdleSpriteP->clippedSourceRect;
  697.             
  698.                 // Determine whether scrolling up or down, then get 
  699.                 // section of sprite outside oldVisScrollRect.
  700.             if (vScrollDelta < 0)
  701.             {
  702.                     // Scrolling up, so get section above oldVisScrollRect
  703.                 if (tempDstRect.bottom > spriteWorldP->oldVisScrollRect.top)
  704.                 {
  705.                     tempSrcRect.bottom += spriteWorldP->oldVisScrollRect.top - 
  706.                         tempDstRect.bottom;
  707.                     tempDstRect.bottom = spriteWorldP->oldVisScrollRect.top;
  708.                 }
  709.             }
  710.             else
  711.             {
  712.                     // Scrolling down, so get section below oldVisScrollRect
  713.                 if (tempDstRect.top < spriteWorldP->oldVisScrollRect.bottom)
  714.                 {
  715.                     tempSrcRect.top += spriteWorldP->oldVisScrollRect.bottom - 
  716.                         tempDstRect.top;
  717.                     tempDstRect.top = spriteWorldP->oldVisScrollRect.bottom;
  718.                 }
  719.             }
  720.             
  721.                 // Make the sprite's rect local to the offscreen area
  722.             tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  723.             tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  724.             tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  725.             tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  726.  
  727.                 // Draw the sprite in the work area
  728.             SWDrawWrappedSprite(curIdleSpriteP, spriteWorldP->workFrameP,
  729.                     &tempSrcRect, &tempDstRect);
  730.             
  731.                 // Draw tiles above sprite
  732.             if (spriteWorldP->tilingIsOn &&
  733.                 curIdleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  734.             {
  735.                 tempDstRect.top += spriteWorldP->vertScrollRectOffset;
  736.                 tempDstRect.bottom += spriteWorldP->vertScrollRectOffset;
  737.                 tempDstRect.left += spriteWorldP->horizScrollRectOffset;
  738.                 tempDstRect.right += spriteWorldP->horizScrollRectOffset;
  739.                 SWDrawTilesAboveSprite(spriteWorldP, &tempDstRect, curIdleSpriteP->tileDepth);
  740.             }
  741.         }
  742.         
  743.         
  744.             // Draw horizontal piece of idle sprite if it is coming into the visScrollRect.
  745.         if ((hScrollDelta > 0 &&
  746.             (curIdleSpriteP->destFrameRect.left < visScrollRectP->right) &&
  747.             (curIdleSpriteP->destFrameRect.right > spriteWorldP->oldVisScrollRect.right) ) ||
  748.             (hScrollDelta < 0 &&
  749.             (curIdleSpriteP->destFrameRect.left < spriteWorldP->oldVisScrollRect.left) &&
  750.             (curIdleSpriteP->destFrameRect.right > visScrollRectP->left)) )
  751.         {
  752.             tempDstRect = curIdleSpriteP->destOffscreenRect;
  753.             tempSrcRect = curIdleSpriteP->clippedSourceRect;
  754.             
  755.                 // Determine whether scrolling left or right, then get 
  756.                 // section of sprite outside oldVisScrollRect.
  757.             if (hScrollDelta < 0)
  758.             {
  759.                     // Scrolling left, so get section to the left of oldVisScrollRect
  760.                 if (tempDstRect.right > spriteWorldP->oldVisScrollRect.left)
  761.                 {
  762.                     tempSrcRect.right += spriteWorldP->oldVisScrollRect.left - 
  763.                         tempDstRect.right;
  764.                     tempDstRect.right = spriteWorldP->oldVisScrollRect.left;
  765.                 }
  766.             }
  767.             else
  768.             {
  769.                     // Scrolling right, so get section to the right of oldVisScrollRect
  770.                 if (tempDstRect.left < spriteWorldP->oldVisScrollRect.right)
  771.                 {
  772.                     tempSrcRect.left += spriteWorldP->oldVisScrollRect.right - 
  773.                         tempDstRect.left;
  774.                     tempDstRect.left = spriteWorldP->oldVisScrollRect.right;
  775.                 }
  776.             }
  777.             
  778.             
  779.                 // Make the sprite's rect local to the offscreen area
  780.             tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  781.             tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  782.             tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  783.             tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  784.  
  785.                 // Draw the sprite in the work area
  786.             SWDrawWrappedSprite(curIdleSpriteP, spriteWorldP->workFrameP,
  787.                     &tempSrcRect, &tempDstRect);
  788.             
  789.                 // Draw tiles above sprite
  790.             if (spriteWorldP->tilingIsOn &&
  791.                 curIdleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  792.             {
  793.                 tempDstRect.top += spriteWorldP->vertScrollRectOffset;
  794.                 tempDstRect.bottom += spriteWorldP->vertScrollRectOffset;
  795.                 tempDstRect.left += spriteWorldP->horizScrollRectOffset;
  796.                 tempDstRect.right += spriteWorldP->horizScrollRectOffset;
  797.                 SWDrawTilesAboveSprite(spriteWorldP, &tempDstRect, curIdleSpriteP->tileDepth);
  798.             }
  799.         }
  800.     
  801.         curIdleSpriteP = curIdleSpriteP->nextIdleSpriteP;
  802.     }
  803.     
  804.  
  805.         // update flagged background rects
  806.     curRectStructP = spriteWorldP->headUpdateRectP;
  807.     while ( curRectStructP != NULL )
  808.     {
  809.         tempDstRect = curRectStructP->updateRect;
  810.         
  811.             // Make the rect local to the offscreen area
  812.         tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  813.         tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  814.         tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  815.         tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  816.         
  817.             // We're not really erasing a sprite, just copying while wrapping
  818.         SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
  819.         curRectStructP = curRectStructP->nextRectStructP;
  820.     }
  821.     
  822.         // Redraw idle sprites that were erased by a tile
  823.     if (spriteWorldP->numTilesChanged > 0)
  824.         SWCheckWrappedIdleSpritesWithTiles(spriteWorldP, headIdleSpriteP);
  825.  
  826.         // Redraw idle sprites that were erased by an updateRect
  827.     if (spriteWorldP->headUpdateRectP != NULL)
  828.         SWCheckWrappedIdleSpritesWithRects(spriteWorldP, headIdleSpriteP);
  829.     
  830.         // Call the postEraseCallBack
  831.     if (spriteWorldP->postEraseCallBack != NULL)
  832.         (*spriteWorldP->postEraseCallBack)(spriteWorldP);
  833.  
  834.  
  835.     //-----------------draw the sprites-------------------
  836.  
  837.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  838.  
  839.         // iterate through the layers in this world
  840.     while (curSpriteLayerP != NULL)
  841.     {
  842.         curSpriteP = curSpriteLayerP->headSpriteP;
  843.  
  844.             // iterate through the sprites in this layer
  845.         while (curSpriteP != NULL)
  846.         {
  847.             if (curSpriteP->isVisible)
  848.             {
  849.                     // Make the sprite's rect local to the offscreen area
  850.                 curSpriteP->destOffscreenRect.top -= spriteWorldP->vertScrollRectOffset;
  851.                 curSpriteP->destOffscreenRect.bottom -= spriteWorldP->vertScrollRectOffset;
  852.                 curSpriteP->destOffscreenRect.left -= spriteWorldP->horizScrollRectOffset;
  853.                 curSpriteP->destOffscreenRect.right -= spriteWorldP->horizScrollRectOffset;
  854.                 
  855.                 if (curSpriteP->needsToBeDrawn)
  856.                 {
  857.                         // Is the sprite visible on the screen?
  858.                     if (curSpriteP->destRectIsVisible)
  859.                     {
  860.                         gCurrentSpriteBeingDrawn = curSpriteP;
  861.                         
  862.                             // Draw the sprite in the work area
  863.                         SWDrawWrappedSprite(curSpriteP, spriteWorldP->workFrameP,
  864.                             &curSpriteP->clippedSourceRect, 
  865.                             &curSpriteP->destOffscreenRect);
  866.                         
  867.                         gCurrentSpriteBeingDrawn = NULL;
  868.                         
  869.                             // Draw tiles above sprite
  870.                         if (spriteWorldP->tilingIsOn &&
  871.                             curSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  872.                         {
  873.                             tempDstRect = curSpriteP->destOffscreenRect;
  874.                             tempDstRect.top += spriteWorldP->vertScrollRectOffset;
  875.                             tempDstRect.bottom += spriteWorldP->vertScrollRectOffset;
  876.                             tempDstRect.left += spriteWorldP->horizScrollRectOffset;
  877.                             tempDstRect.right += spriteWorldP->horizScrollRectOffset;
  878.                             SWDrawTilesAboveSprite(spriteWorldP, &tempDstRect, curSpriteP->tileDepth);
  879.                         }
  880.                     }
  881.                 }
  882.                 else
  883.                 {
  884.                         // Is the idle sprite visible on the screen?
  885.                     if (curSpriteP->destRectIsVisible)
  886.                     {
  887.                         SWCheckWrappedIdleSpriteOverlap(spriteWorldP, 
  888.                             curSpriteP, headActiveSpriteP);
  889.                     }
  890.                 }
  891.             }
  892.             
  893.                 // Set last rect to current rect
  894.             curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
  895.             curSpriteP->oldOffscreenRect = curSpriteP->destOffscreenRect;
  896.             curSpriteP->oldRectIsVisible = curSpriteP->destRectIsVisible;
  897.             
  898.             curSpriteP->needsToBeDrawn = false;
  899.             curSpriteP->needsToBeErased = false;
  900.  
  901.             curSpriteP = curSpriteP->nextSpriteP;
  902.         }
  903.         
  904.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  905.     }
  906.     
  907.     spriteWorldP->oldVisScrollRect = spriteWorldP->visScrollRect;
  908.     
  909.     
  910.             // Call the postDrawCallBack
  911.     if (spriteWorldP->postDrawCallBack != NULL)
  912.         (*spriteWorldP->postDrawCallBack)(spriteWorldP);
  913.     
  914.     
  915.     //-----------------update the screen--------------------
  916.     
  917.         // Set the port to the window
  918.     SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  919.     
  920.     if (spriteWorldP->usingVBL)
  921.     {  
  922.         spriteWorldP->vblTaskRec.hasVBLFired = false;
  923.         while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  924.         {}
  925.     }
  926.     
  927.         // Copy offscreen area to screen while wrapping
  928.     SWWrapWorldToScreen(spriteWorldP);
  929.     
  930.     
  931.             // dispose of flagged background rects
  932.     nextRectStructP = spriteWorldP->headUpdateRectP;
  933.     while ( nextRectStructP != NULL )
  934.     {
  935.         curRectStructP = nextRectStructP;
  936.         nextRectStructP = curRectStructP->nextRectStructP;
  937.         DisposePtr( (Ptr)curRectStructP );
  938.     }
  939.     spriteWorldP->headUpdateRectP = NULL;
  940.     
  941.     spriteWorldP->numTilesChanged = 0;
  942.     
  943.     
  944.         // Remove the deadSpriteLayer if we added it earlier.
  945.     if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
  946.     {
  947.         SWRemoveSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
  948.     }
  949. }
  950.  
  951.  
  952. ///--------------------------------------------------------------------------------------
  953. //    SWFastAnimateScrollingSpriteWorld - essentially the same as SWAnimateScrollingSpriteWorld,
  954. //    except that this only updates that sprites/tiles that have moved or changed, by calling
  955. //    SWWrapRectToScreen. All code that handles updating tiles/sprites while scrolling has
  956. //    been removed. (Three parts: the part that draws new tiles, the part that erases idle
  957. //    sprites leaving the visScrollRect, and the part that draws idle sprites entering it.)
  958. ///--------------------------------------------------------------------------------------
  959.  
  960. SW_FUNC void SWFastAnimateScrollingSpriteWorld(
  961.     SpriteWorldPtr spriteWorldP)
  962. {
  963.     UpdateRectStructPtr            curRectStructP,
  964.                                 nextRectStructP;
  965.     register SpriteLayerPtr     curSpriteLayerP;
  966.     register SpritePtr             curSpriteP;
  967.     SpritePtr                     headActiveSpriteP = NULL;    // Tail of active sprite list
  968.     SpritePtr                    headIdleSpriteP = NULL;        // Tail of idle sprite list
  969.     SpritePtr                     curActiveSpriteP = NULL;
  970.     SpritePtr                     curIdleSpriteP = NULL;
  971.     Rect                        *visScrollRectP = &spriteWorldP->visScrollRect;
  972.     Rect                        tempDstRect;
  973.     Rect                        *changedRectP;
  974.     short                        hScrollDelta, vScrollDelta, curTileLayer, index;
  975.     
  976.     SW_ASSERT(spriteWorldP != NULL);
  977.     SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
  978.     SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
  979.     SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
  980.     
  981.     if (!spriteWorldP->frameHasOccurred)
  982.         return;
  983.     
  984.         
  985.     hScrollDelta = visScrollRectP->left - spriteWorldP->oldVisScrollRect.left;
  986.     vScrollDelta = visScrollRectP->top - spriteWorldP->oldVisScrollRect.top;
  987.     if (hScrollDelta || vScrollDelta)
  988.     {
  989.             // We let this function do everything when scrolling
  990.         SWAnimateScrollingSpriteWorld(spriteWorldP);
  991.         return;
  992.     }
  993.     
  994.     
  995.         // Add the deadSpriteLayer if there are any Sprites in it.
  996.     if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
  997.     {
  998.         SWAddSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
  999.     }
  1000.     
  1001.     
  1002.     //-----------------erase the sprites--------------------
  1003.     
  1004.         // Set the port to the work area so we can draw in it
  1005.     SetGWorld(spriteWorldP->workFrameP->framePort, nil);
  1006.     
  1007.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  1008.     curTileLayer = 0;
  1009.     
  1010.         // iterate through the layers in this world
  1011.     while (curSpriteLayerP != NULL)
  1012.     {
  1013.         curSpriteP = curSpriteLayerP->headSpriteP;
  1014.         
  1015.         if (curSpriteLayerP->tileLayer > curTileLayer)
  1016.             curTileLayer = curSpriteLayerP->tileLayer;
  1017.         
  1018.             // iterate through the sprites in this layer
  1019.         while (curSpriteP != NULL)
  1020.         {
  1021.             SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
  1022.             curSpriteP->tileDepth = curTileLayer;
  1023.             
  1024.                 // Clip the sprite's destOffscreenRect with visScrollRect.
  1025.             if (curSpriteP->isVisible)
  1026.             {
  1027.                 curSpriteP->destOffscreenRect = curSpriteP->destFrameRect;
  1028.                 curSpriteP->clippedSourceRect = curSpriteP->curFrameP->frameRect;
  1029.                 
  1030.  
  1031.                 if (curSpriteP->destOffscreenRect.top < visScrollRectP->top)
  1032.                 {
  1033.                     curSpriteP->clippedSourceRect.top += visScrollRectP->top - 
  1034.                             curSpriteP->destOffscreenRect.top;
  1035.                     curSpriteP->destOffscreenRect.top = visScrollRectP->top;
  1036.                 }
  1037.                 
  1038.                 if (curSpriteP->destOffscreenRect.bottom > visScrollRectP->bottom)
  1039.                 {
  1040.                     curSpriteP->clippedSourceRect.bottom += visScrollRectP->bottom - 
  1041.                             curSpriteP->destOffscreenRect.bottom;
  1042.                     curSpriteP->destOffscreenRect.bottom = visScrollRectP->bottom;
  1043.                 }
  1044.                 
  1045.                 if (curSpriteP->destOffscreenRect.left < visScrollRectP->left)
  1046.                 {
  1047.                     curSpriteP->clippedSourceRect.left += visScrollRectP->left - 
  1048.                             curSpriteP->destOffscreenRect.left;
  1049.                     curSpriteP->destOffscreenRect.left = visScrollRectP->left;
  1050.                 }
  1051.                 
  1052.                 if (curSpriteP->destOffscreenRect.right > visScrollRectP->right)
  1053.                 {
  1054.                     curSpriteP->clippedSourceRect.right += visScrollRectP->right - 
  1055.                             curSpriteP->destOffscreenRect.right;
  1056.                     curSpriteP->destOffscreenRect.right = visScrollRectP->right;
  1057.                 }
  1058.                 
  1059.                 curSpriteP->destRectIsVisible =
  1060.                         (curSpriteP->destOffscreenRect.right >
  1061.                         curSpriteP->destOffscreenRect.left &&
  1062.                         curSpriteP->destOffscreenRect.bottom >
  1063.                         curSpriteP->destOffscreenRect.top);
  1064.             }
  1065.             
  1066.             
  1067.                 // Erase the sprites
  1068.             if (curSpriteP->needsToBeDrawn && curSpriteP->isVisible ||
  1069.                 curSpriteP->needsToBeErased && !curSpriteP->isVisible)
  1070.             {
  1071.                     // Was the sprite visible on the screen last frame?
  1072.                 if (curSpriteP->oldRectIsVisible)
  1073.                 {
  1074.                         // Add sprite to active sprite list
  1075.                     if (headActiveSpriteP == NULL)
  1076.                         headActiveSpriteP = curSpriteP;
  1077.                     
  1078.                     if (curActiveSpriteP != NULL)
  1079.                             curActiveSpriteP->nextActiveSpriteP = curSpriteP;
  1080.                     
  1081.                     curActiveSpriteP = curSpriteP;
  1082.                     
  1083.                     {
  1084.                         short temp;
  1085.                         
  1086.                             // align left edge of oldOffscreenRect for erasing
  1087.                         curSpriteP->oldOffscreenRect.left &=
  1088.                             (spriteWorldP->workFrameP->leftAlignFactor);
  1089.                         
  1090.                             // align the right edge to long word boundary
  1091.                         temp = curSpriteP->oldOffscreenRect.right &
  1092.                             spriteWorldP->workFrameP->rightAlignFactor;
  1093.                         if (temp != 0)
  1094.                         {
  1095.                             curSpriteP->oldOffscreenRect.right +=
  1096.                                 (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  1097.                         }
  1098.  
  1099.                             // align left edge of oldFrameRect - necessary for
  1100.                             // deltaFrameRect below, used by idle sprite collision
  1101.                         curSpriteP->oldFrameRect.left &=
  1102.                             (spriteWorldP->workFrameP->leftAlignFactor);
  1103.                         
  1104.                             // align the right edge to long word boundary
  1105.                         temp = curSpriteP->oldFrameRect.right &
  1106.                             spriteWorldP->workFrameP->rightAlignFactor;
  1107.                         if (temp != 0)
  1108.                         {
  1109.                             curSpriteP->oldFrameRect.right +=
  1110.                                 (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
  1111.                         }
  1112.                     }
  1113.                     
  1114.                         // union last rect and current rect - this is necessary for 
  1115.                         // the proper redrawing of idle sprites
  1116.                     curSpriteP->deltaFrameRect.top = 
  1117.                         SW_MIN(curSpriteP->oldFrameRect.top, curSpriteP->destFrameRect.top);
  1118.                     curSpriteP->deltaFrameRect.left = 
  1119.                         SW_MIN(curSpriteP->oldFrameRect.left, curSpriteP->destFrameRect.left);
  1120.                     curSpriteP->deltaFrameRect.bottom = 
  1121.                         SW_MAX(curSpriteP->oldFrameRect.bottom, curSpriteP->destFrameRect.bottom);
  1122.                     curSpriteP->deltaFrameRect.right = 
  1123.                         SW_MAX(curSpriteP->oldFrameRect.right, curSpriteP->destFrameRect.right);
  1124.                     
  1125.                     
  1126.                         // Erase the sprite from the work area
  1127.                     SWEraseWrappedSprite(spriteWorldP, &curSpriteP->oldOffscreenRect);
  1128.                 }
  1129.                 else if (curSpriteP->destRectIsVisible)    // Sprite will be drawn
  1130.                 {
  1131.                         // Add sprite to active sprite list
  1132.                     if (headActiveSpriteP == NULL)
  1133.                         headActiveSpriteP = curSpriteP;
  1134.                     
  1135.                     if (curActiveSpriteP != NULL)
  1136.                             curActiveSpriteP->nextActiveSpriteP = curSpriteP;
  1137.                     
  1138.                     curActiveSpriteP = curSpriteP;
  1139.                 }
  1140.             }
  1141.             else if (curSpriteP->isVisible)        // Visible, idle sprites
  1142.             {
  1143.                     // Is the idle sprite visible on the screen?
  1144.                 if (curSpriteP->destRectIsVisible)
  1145.                 {
  1146.                         // Add sprite to idle sprite list
  1147.                     if (headIdleSpriteP == NULL)
  1148.                         headIdleSpriteP = curSpriteP;
  1149.                     
  1150.                     if (curIdleSpriteP != NULL)
  1151.                         curIdleSpriteP->nextIdleSpriteP = curSpriteP;
  1152.                     
  1153.                     curIdleSpriteP = curSpriteP;
  1154.                 }
  1155.             }
  1156.  
  1157.             curSpriteP = curSpriteP->nextSpriteP;
  1158.         }
  1159.  
  1160.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;    
  1161.     }
  1162.     
  1163.     if (curActiveSpriteP != NULL)
  1164.         curActiveSpriteP->nextActiveSpriteP = NULL;
  1165.     
  1166.     if (curIdleSpriteP != NULL)
  1167.         curIdleSpriteP->nextIdleSpriteP = NULL;
  1168.         
  1169.  
  1170.         // update flagged background rects
  1171.     curRectStructP = spriteWorldP->headUpdateRectP;
  1172.     while ( curRectStructP != NULL )
  1173.     {
  1174.         tempDstRect = curRectStructP->updateRect;
  1175.         
  1176.             // Make the rect local to the offscreen area
  1177.         tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
  1178.         tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
  1179.         tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
  1180.         tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
  1181.         
  1182.             // We're not really erasing a sprite, just copying while wrapping
  1183.         SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
  1184.         curRectStructP = curRectStructP->nextRectStructP;
  1185.     }
  1186.     
  1187.         // Redraw idle sprites that were erased by a tile
  1188.     if (spriteWorldP->numTilesChanged > 0)
  1189.         SWCheckWrappedIdleSpritesWithTiles(spriteWorldP, headIdleSpriteP);
  1190.  
  1191.         // Redraw idle sprites that were erased by an updateRect
  1192.     if (spriteWorldP->headUpdateRectP != NULL)
  1193.         SWCheckWrappedIdleSpritesWithRects(spriteWorldP, headIdleSpriteP);
  1194.     
  1195.         // Call the postEraseCallBack
  1196.     if (spriteWorldP->postEraseCallBack != NULL)
  1197.         (*spriteWorldP->postEraseCallBack)(spriteWorldP);
  1198.  
  1199.  
  1200.     //-----------------draw the sprites-------------------
  1201.  
  1202.     curSpriteLayerP = spriteWorldP->headSpriteLayerP;
  1203.  
  1204.         // iterate through the layers in this world
  1205.     while (curSpriteLayerP != NULL)
  1206.     {
  1207.         curSpriteP = curSpriteLayerP->headSpriteP;
  1208.  
  1209.             // iterate through the sprites in this layer
  1210.         while (curSpriteP != NULL)
  1211.         {
  1212.             if (curSpriteP->isVisible)
  1213.             {
  1214.                     // Make the sprite's rect local to the offscreen area
  1215.                 curSpriteP->destOffscreenRect.top -= spriteWorldP->vertScrollRectOffset;
  1216.                 curSpriteP->destOffscreenRect.bottom -= spriteWorldP->vertScrollRectOffset;
  1217.                 curSpriteP->destOffscreenRect.left -= spriteWorldP->horizScrollRectOffset;
  1218.                 curSpriteP->destOffscreenRect.right -= spriteWorldP->horizScrollRectOffset;
  1219.                 
  1220.                 if (curSpriteP->needsToBeDrawn)
  1221.                 {
  1222.                         // Is the sprite visible on the screen?
  1223.                     if (curSpriteP->destRectIsVisible)
  1224.                     {
  1225.                         gCurrentSpriteBeingDrawn = curSpriteP;
  1226.                         
  1227.                             // Draw the sprite in the work area
  1228.                         SWDrawWrappedSprite(curSpriteP, spriteWorldP->workFrameP,
  1229.                             &curSpriteP->clippedSourceRect, 
  1230.                             &curSpriteP->destOffscreenRect);
  1231.                         
  1232.                         gCurrentSpriteBeingDrawn = NULL;
  1233.                         
  1234.                             // Draw tiles above sprite
  1235.                         if (spriteWorldP->tilingIsOn &&
  1236.                             curSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  1237.                         {
  1238.                             tempDstRect = curSpriteP->destOffscreenRect;
  1239.                             tempDstRect.top += spriteWorldP->vertScrollRectOffset;
  1240.                             tempDstRect.bottom += spriteWorldP->vertScrollRectOffset;
  1241.                             tempDstRect.left += spriteWorldP->horizScrollRectOffset;
  1242.                             tempDstRect.right += spriteWorldP->horizScrollRectOffset;
  1243.                             SWDrawTilesAboveSprite(spriteWorldP, &tempDstRect, curSpriteP->tileDepth);
  1244.                         }
  1245.                     }
  1246.                 }
  1247.                 else
  1248.                 {
  1249.                         // Is the idle sprite visible on the screen?
  1250.                     if (curSpriteP->destRectIsVisible)
  1251.                     {
  1252.                         SWCheckWrappedIdleSpriteOverlap(spriteWorldP, 
  1253.                             curSpriteP, headActiveSpriteP);
  1254.                     }
  1255.                 }
  1256.             }
  1257.             
  1258.                 // Set last rect to current rect
  1259.             curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
  1260.             curSpriteP->oldOffscreenRect = curSpriteP->destOffscreenRect;
  1261.             curSpriteP->oldRectIsVisible = curSpriteP->destRectIsVisible;
  1262.             
  1263.             curSpriteP->needsToBeDrawn = false;
  1264.             curSpriteP->needsToBeErased = false;
  1265.  
  1266.             curSpriteP = curSpriteP->nextSpriteP;
  1267.         }
  1268.         
  1269.         curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
  1270.     }
  1271.     
  1272.     spriteWorldP->oldVisScrollRect = spriteWorldP->visScrollRect;
  1273.     
  1274.     
  1275.             // Call the postDrawCallBack
  1276.     if (spriteWorldP->postDrawCallBack != NULL)
  1277.         (*spriteWorldP->postDrawCallBack)(spriteWorldP);
  1278.     
  1279.     
  1280.     //-----------------update the screen--------------------
  1281.     
  1282.         // Set the port to the window
  1283.     SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
  1284.     
  1285.     if (spriteWorldP->usingVBL)
  1286.     {  
  1287.         spriteWorldP->vblTaskRec.hasVBLFired = false;
  1288.         while ( !spriteWorldP->vblTaskRec.hasVBLFired )
  1289.         {}
  1290.     }
  1291.     
  1292.     
  1293.     //
  1294.     ///    --------------BEGIN NEW CODE---------------
  1295.     //
  1296.     
  1297.     
  1298.         // update flagged background rects
  1299.     curRectStructP = spriteWorldP->headUpdateRectP;
  1300.     while ( curRectStructP != NULL )
  1301.     {
  1302.         SWWrapRectToScreen(spriteWorldP, &curRectStructP->updateRect);                        
  1303.         curRectStructP = curRectStructP->nextRectStructP;
  1304.     }
  1305.     
  1306.         // Update on screen the tiles that have changed
  1307.     changedRectP = spriteWorldP->changedTiles;
  1308.     for (index = 0; index < spriteWorldP->numTilesChanged; index++, changedRectP++)
  1309.     {
  1310.         SWWrapRectToScreen(spriteWorldP, changedRectP);
  1311.     }
  1312.  
  1313.     
  1314.         // update the sprites on the screen
  1315.     curSpriteP = headActiveSpriteP;
  1316.     while (curSpriteP != NULL)
  1317.     {    
  1318.         SWWrapRectToScreen(spriteWorldP, &curSpriteP->deltaFrameRect);
  1319.         curSpriteP->deltaFrameRect = curSpriteP->destFrameRect;
  1320.         curSpriteP = curSpriteP->nextActiveSpriteP;
  1321.     }
  1322.  
  1323.     //
  1324.     ///    --------------END NEW CODE---------------
  1325.     //
  1326.     
  1327.     
  1328.             // dispose of flagged background rects
  1329.     nextRectStructP = spriteWorldP->headUpdateRectP;
  1330.     while ( nextRectStructP != NULL )
  1331.     {
  1332.         curRectStructP = nextRectStructP;
  1333.         nextRectStructP = curRectStructP->nextRectStructP;
  1334.         DisposePtr( (Ptr)curRectStructP );
  1335.     }
  1336.     spriteWorldP->headUpdateRectP = NULL;
  1337.     
  1338.     spriteWorldP->numTilesChanged = 0;
  1339.     
  1340.     
  1341.         // Remove the deadSpriteLayer if we added it earlier.
  1342.     if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
  1343.     {
  1344.         SWRemoveSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
  1345.     }
  1346. }
  1347.  
  1348.  
  1349. #pragma mark -
  1350. ///--------------------------------------------------------------------------------------
  1351. //    SWDrawWrappedSprite - wraps image in dest area. For drawing sprites, not erasing,
  1352. //    since source rect stays the same.
  1353. ///--------------------------------------------------------------------------------------
  1354.  
  1355. SW_FUNC void SWDrawWrappedSprite(
  1356.     SpritePtr srcSpriteP,
  1357.     FramePtr dstFrameP,
  1358.     Rect* srcRect,
  1359.     Rect* dstRect)
  1360. {
  1361.     Rect        tempDstRect;
  1362.     
  1363.     
  1364.         // Draw main image //
  1365.     (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, srcRect, dstRect);
  1366.     
  1367.     
  1368.         // Wrap to top //
  1369.     if (dstRect->bottom > dstFrameP->frameRect.bottom)
  1370.     {
  1371.         tempDstRect.top = dstRect->top - dstFrameP->frameRect.bottom;
  1372.         tempDstRect.bottom = dstRect->bottom - dstFrameP->frameRect.bottom;
  1373.         tempDstRect.left = dstRect->left;
  1374.         tempDstRect.right = dstRect->right;
  1375.         
  1376.         (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1377.             srcRect, &tempDstRect);
  1378.         
  1379.         
  1380.             // Wrap to upper left or right corner //
  1381.         if (dstRect->right > dstFrameP->frameRect.right)
  1382.         {
  1383.             tempDstRect.left -= dstFrameP->frameRect.right;
  1384.             tempDstRect.right -= dstFrameP->frameRect.right;
  1385.             
  1386.             (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1387.                 srcRect, &tempDstRect);
  1388.         }
  1389.         else if (dstRect->left < dstFrameP->frameRect.left)
  1390.         {
  1391.             tempDstRect.left += dstFrameP->frameRect.right;
  1392.             tempDstRect.right += dstFrameP->frameRect.right;
  1393.             
  1394.             (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1395.                 srcRect, &tempDstRect);
  1396.         }
  1397.     }
  1398.     
  1399.             // Wrap to left or right side //
  1400.     if (dstRect->right > dstFrameP->frameRect.right)
  1401.     {
  1402.         tempDstRect.top = dstRect->top;
  1403.         tempDstRect.bottom = dstRect->bottom;
  1404.         tempDstRect.left = dstRect->left - dstFrameP->frameRect.right;
  1405.         tempDstRect.right = dstRect->right - dstFrameP->frameRect.right;
  1406.         
  1407.         (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1408.             srcRect, &tempDstRect);
  1409.     }
  1410.     else if (dstRect->left < dstFrameP->frameRect.left)
  1411.     {
  1412.         tempDstRect.top = dstRect->top;
  1413.         tempDstRect.bottom = dstRect->bottom;
  1414.         tempDstRect.left = dstRect->left + dstFrameP->frameRect.right;
  1415.         tempDstRect.right = dstRect->right + dstFrameP->frameRect.right;
  1416.         
  1417.         (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1418.             srcRect, &tempDstRect);
  1419.     }
  1420.     
  1421.     
  1422.             // Wrap to bottom //
  1423.     if (dstRect->top < dstFrameP->frameRect.top)
  1424.     {
  1425.         tempDstRect.top = dstRect->top + dstFrameP->frameRect.bottom;
  1426.         tempDstRect.bottom = dstRect->bottom + dstFrameP->frameRect.bottom;
  1427.         tempDstRect.left = dstRect->left;
  1428.         tempDstRect.right = dstRect->right;
  1429.         
  1430.         (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1431.             srcRect, &tempDstRect);
  1432.         
  1433.             // Wrap to lower left or right corner //
  1434.         if (dstRect->right > dstFrameP->frameRect.right)
  1435.         {
  1436.             tempDstRect.left -= dstFrameP->frameRect.right;
  1437.             tempDstRect.right -= dstFrameP->frameRect.right;
  1438.             
  1439.             (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1440.                 srcRect, &tempDstRect);
  1441.         }
  1442.         else if (dstRect->left < dstFrameP->frameRect.left)
  1443.         {
  1444.             tempDstRect.left += dstFrameP->frameRect.right;
  1445.             tempDstRect.right += dstFrameP->frameRect.right;
  1446.             
  1447.             (*srcSpriteP->frameDrawProc)(srcSpriteP->curFrameP, dstFrameP, 
  1448.                 srcRect, &tempDstRect);
  1449.         }
  1450.     }
  1451. }
  1452.  
  1453.  
  1454. ///--------------------------------------------------------------------------------------
  1455. //    SWEraseWrappedSprite - erases a wrapped sprite from the work area
  1456. ///--------------------------------------------------------------------------------------
  1457.  
  1458. SW_FUNC void SWEraseWrappedSprite(
  1459.     SpriteWorldPtr spriteWorldP,
  1460.     Rect* dstRect)
  1461. {
  1462.     Rect        tempDstRect;
  1463.     FramePtr    srcFrameP = spriteWorldP->backFrameP;
  1464.     FramePtr    dstFrameP = spriteWorldP->workFrameP;
  1465.     
  1466.     
  1467.         // Draw main image //
  1468.     (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, dstRect, dstRect);
  1469.     
  1470.     
  1471.         // Wrap to top //
  1472.     if (dstRect->bottom > dstFrameP->frameRect.bottom)
  1473.     {
  1474.         tempDstRect.top = dstRect->top - dstFrameP->frameRect.bottom;
  1475.         tempDstRect.bottom = dstRect->bottom - dstFrameP->frameRect.bottom;
  1476.         tempDstRect.left = dstRect->left;
  1477.         tempDstRect.right = dstRect->right;
  1478.         
  1479.         (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1480.             &tempDstRect, &tempDstRect);
  1481.         
  1482.             // Wrap to upper left or right corner //
  1483.         if (dstRect->right > dstFrameP->frameRect.right)
  1484.         {
  1485.             tempDstRect.left -= dstFrameP->frameRect.right;
  1486.             tempDstRect.right -= dstFrameP->frameRect.right;
  1487.             
  1488.             (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1489.                 &tempDstRect, &tempDstRect);
  1490.         }
  1491.         else if (dstRect->left < dstFrameP->frameRect.left)
  1492.         {
  1493.             tempDstRect.left += dstFrameP->frameRect.right;
  1494.             tempDstRect.right += dstFrameP->frameRect.right;
  1495.             
  1496.             (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1497.                 &tempDstRect, &tempDstRect);
  1498.         }
  1499.     }
  1500.     
  1501.             // Wrap to left or right side //
  1502.     if (dstRect->right > dstFrameP->frameRect.right)
  1503.     {
  1504.         tempDstRect.top = dstRect->top;
  1505.         tempDstRect.bottom = dstRect->bottom;
  1506.         tempDstRect.left = dstRect->left - dstFrameP->frameRect.right;
  1507.         tempDstRect.right = dstRect->right - dstFrameP->frameRect.right;
  1508.         
  1509.         (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1510.             &tempDstRect, &tempDstRect);
  1511.     }
  1512.     else if (dstRect->left < dstFrameP->frameRect.left)
  1513.     {
  1514.         tempDstRect.top = dstRect->top;
  1515.         tempDstRect.bottom = dstRect->bottom;
  1516.         tempDstRect.left = dstRect->left + dstFrameP->frameRect.right;
  1517.         tempDstRect.right = dstRect->right + dstFrameP->frameRect.right;
  1518.         
  1519.         (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1520.             &tempDstRect, &tempDstRect);
  1521.     }
  1522.     
  1523.     
  1524.             // Wrap to bottom //
  1525.     if (dstRect->top < dstFrameP->frameRect.top)
  1526.     {
  1527.         tempDstRect.top = dstRect->top + dstFrameP->frameRect.bottom;
  1528.         tempDstRect.bottom = dstRect->bottom + dstFrameP->frameRect.bottom;
  1529.         tempDstRect.left = dstRect->left;
  1530.         tempDstRect.right = dstRect->right;
  1531.         
  1532.         (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1533.             &tempDstRect, &tempDstRect);
  1534.         
  1535.             // Wrap to lower left or right corner //
  1536.         if (dstRect->right > dstFrameP->frameRect.right)
  1537.         {
  1538.             tempDstRect.left -= dstFrameP->frameRect.right;
  1539.             tempDstRect.right -= dstFrameP->frameRect.right;
  1540.             
  1541.             (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1542.                 &tempDstRect, &tempDstRect);
  1543.         }
  1544.         else if (dstRect->left < dstFrameP->frameRect.left)
  1545.         {
  1546.             tempDstRect.left += dstFrameP->frameRect.right;
  1547.             tempDstRect.right += dstFrameP->frameRect.right;
  1548.             
  1549.             (*spriteWorldP->offscreenDrawProc)(srcFrameP, dstFrameP, 
  1550.                 &tempDstRect, &tempDstRect);
  1551.         }
  1552.     }
  1553. }
  1554.  
  1555.  
  1556. ///--------------------------------------------------------------------------------------
  1557. //    SWWrapWorldToScreen - copy source rect to dest rect. Assumes they are the same
  1558. //    size, and that dstRect will fit within the bounds of the dstFrameP. Used for
  1559. //    copying the work area to the screen, with the ability of "wrapping" the source
  1560. //    rect around the work area.
  1561. ///--------------------------------------------------------------------------------------
  1562.  
  1563. SW_FUNC void SWWrapWorldToScreen(
  1564.     SpriteWorldPtr    spriteWorldP)
  1565. {    
  1566.     FramePtr    srcFrameP = spriteWorldP->workFrameP;
  1567.     FramePtr    dstFrameP = spriteWorldP->windowFrameP;
  1568.     
  1569.         // We can always add code to clip dstRect later if we want.
  1570.         // Just make sure to clip it before clipping srcRect.
  1571.     Rect    srcRect = spriteWorldP->offscreenScrollRect;
  1572.     Rect    dstRect = spriteWorldP->windRect;
  1573.     Rect    srcRectA, srcRectB, dstRectA, dstRectB;
  1574.     
  1575.                 // Size of area that was clipped in source rect
  1576.     short    topClip=0, rightClip=0, bottomClip=0, leftClip=0;
  1577.     
  1578.     
  1579.         // Clip the source rect, and save what we clipped for wrapping later //
  1580.     
  1581.         // clip off the top
  1582.     if (srcRect.top < srcFrameP->frameRect.top)
  1583.     {
  1584.         topClip = srcFrameP->frameRect.top - srcRect.top;
  1585.         srcRect.top += topClip;    
  1586.     }
  1587.     
  1588.         // clip off the bottom
  1589.     if (srcRect.bottom > srcFrameP->frameRect.bottom)
  1590.     {
  1591.         bottomClip = srcRect.bottom - srcFrameP->frameRect.bottom;
  1592.         srcRect.bottom -= bottomClip;
  1593.     }
  1594.     
  1595.         // clip off the left
  1596.     if (srcRect.left < srcFrameP->frameRect.left)
  1597.     {
  1598.         leftClip = srcFrameP->frameRect.left - srcRect.left;
  1599.         srcRect.left += leftClip;
  1600.     }
  1601.     
  1602.         // clip off the right
  1603.     if (srcRect.right > srcFrameP->frameRect.right)
  1604.     {
  1605.         rightClip = srcRect.right - srcFrameP->frameRect.right;
  1606.         srcRect.right -= rightClip;
  1607.     }
  1608.     
  1609.     
  1610.                     // Here we do the wrapping and drawing //
  1611.     
  1612.         // Draw top section //
  1613.     
  1614.     if (topClip)
  1615.     {
  1616.                 // Calculate top piece //
  1617.         
  1618.             // Wrap source rect to bottom side
  1619.         srcRectA.right = srcRect.right;                    // Copy clipped source rect
  1620.         srcRectA.left = srcRect.left;
  1621.         srcRectA.bottom = srcFrameP->frameRect.bottom;
  1622.         srcRectA.top = srcFrameP->frameRect.bottom - topClip;
  1623.         
  1624.             // Position dest rect at top side
  1625.         dstRectA.top = dstRect.top;
  1626.         dstRectA.bottom = dstRect.top + topClip;
  1627.         dstRectA.left = dstRect.left + leftClip;
  1628.         dstRectA.right = dstRect.right - rightClip;
  1629.         
  1630.         
  1631.         if (leftClip)    // Calculate top-left piece
  1632.         {
  1633.                 // Wrap source rect to lower-right corner
  1634.             srcRectB.bottom = srcFrameP->frameRect.bottom;
  1635.             srcRectB.right = srcFrameP->frameRect.right;
  1636.             srcRectB.top = srcFrameP->frameRect.bottom - topClip;
  1637.             srcRectB.left = srcFrameP->frameRect.right - leftClip;
  1638.             
  1639.                 // Position dest rect at top-left corner
  1640.             dstRectB.left = dstRect.left;
  1641.             dstRectB.top = dstRect.top;
  1642.             dstRectB.right = dstRect.left + leftClip;
  1643.             dstRectB.bottom = dstRect.top + topClip;
  1644.             
  1645.             if (spriteWorldP->doubleRectDrawProc != NULL)
  1646.             {
  1647.                     // RectB is passed first, since it is to the left of rectA
  1648.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  1649.                     &srcRectB, &dstRectB, &srcRectA, &dstRectA);
  1650.             }
  1651.             else
  1652.             {
  1653.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  1654.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  1655.             }
  1656.         }
  1657.         else if (rightClip)        // Calculate top-right piece
  1658.         {
  1659.                 // Wrap source rect to lower-left corner
  1660.             srcRectB.bottom = srcFrameP->frameRect.bottom;
  1661.             srcRectB.left = srcFrameP->frameRect.left;
  1662.             srcRectB.right = srcFrameP->frameRect.left + rightClip;
  1663.             srcRectB.top = srcFrameP->frameRect.bottom - topClip;
  1664.             
  1665.                 // Position dest rect at top-right corner
  1666.             dstRectB.top = dstRect.top;
  1667.             dstRectB.right = dstRect.right;
  1668.             dstRectB.bottom = dstRect.top + topClip;
  1669.             dstRectB.left = dstRect.right - rightClip;
  1670.             
  1671.             if (spriteWorldP->doubleRectDrawProc != NULL)
  1672.             {
  1673.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP,
  1674.                      &srcRectA, &dstRectA, &srcRectB, &dstRectB);
  1675.             }
  1676.             else
  1677.             {
  1678.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  1679.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  1680.             }
  1681.         }
  1682.         else
  1683.         {
  1684.                 // Draw just the top rect
  1685.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  1686.         }
  1687.     }
  1688.     
  1689.     
  1690.             // Draw middle section //
  1691.     
  1692.         // Calculate main middle piece (not wrapped)
  1693.     dstRectA.left = dstRect.left + leftClip;
  1694.     dstRectA.top = dstRect.top + topClip;
  1695.     dstRectA.right = dstRect.right - rightClip;
  1696.     dstRectA.bottom = dstRect.bottom - bottomClip;
  1697.     
  1698.     
  1699.     if (leftClip)    // Draw left piece
  1700.     {
  1701.             // Wrap source rect to right side
  1702.         srcRectB.top = srcRect.top;                // Copy clipped source rect
  1703.         srcRectB.bottom = srcRect.bottom;
  1704.         srcRectB.right = srcFrameP->frameRect.right;
  1705.         srcRectB.left = srcFrameP->frameRect.right - leftClip;
  1706.         
  1707.             // Position dest rect at left side
  1708.         dstRectB.left = dstRect.left;
  1709.         dstRectB.right = dstRect.left + leftClip;
  1710.         dstRectB.top = dstRect.top + topClip;
  1711.         dstRectB.bottom = dstRect.bottom - bottomClip;
  1712.         
  1713.         if (spriteWorldP->doubleRectDrawProc != NULL)
  1714.         {
  1715.                 // RectB is passed first, since it is to the left of rectA
  1716.             (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  1717.                 &srcRectB, &dstRectB, &srcRect, &dstRectA);
  1718.         }
  1719.         else
  1720.         {
  1721.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  1722.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRect, &dstRectA);
  1723.         }
  1724.     }
  1725.     else if (rightClip)        // Draw right piece
  1726.     {
  1727.             // Wrap source rect to left side
  1728.         srcRectB.top = srcRect.top;                // Copy clipped source rect
  1729.         srcRectB.bottom = srcRect.bottom;
  1730.         srcRectB.left = srcFrameP->frameRect.left;
  1731.         srcRectB.right = srcFrameP->frameRect.left + rightClip;
  1732.         
  1733.             // Position dest rect at right side
  1734.         dstRectB.right = dstRect.right;
  1735.         dstRectB.left = dstRect.right - rightClip;
  1736.         dstRectB.top = dstRect.top + topClip;
  1737.         dstRectB.bottom = dstRect.bottom - bottomClip;
  1738.         
  1739.         if (spriteWorldP->doubleRectDrawProc != NULL)
  1740.         {
  1741.             (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  1742.                 &srcRect, &dstRectA, &srcRectB, &dstRectB);
  1743.         }
  1744.         else
  1745.         {
  1746.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRect, &dstRectA);
  1747.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  1748.         }
  1749.     }
  1750.     else
  1751.     {
  1752.             // Draw just the middle piece
  1753.          (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRect, &dstRectA);
  1754.     }
  1755.     
  1756.     
  1757.         // Draw bottom section //
  1758.     
  1759.     if (bottomClip)
  1760.     {
  1761.             // Calculate bottom piece //
  1762.         
  1763.             // Wrap source rect to top side
  1764.         srcRectA.right = srcRect.right;                // Copy clipped source rect
  1765.         srcRectA.left = srcRect.left;
  1766.         srcRectA.top = srcFrameP->frameRect.top;
  1767.         srcRectA.bottom = srcFrameP->frameRect.top + bottomClip;
  1768.         
  1769.             // Position dest rect at bottom side
  1770.         dstRectA.bottom = dstRect.bottom;
  1771.         dstRectA.top = dstRect.bottom - bottomClip;
  1772.         dstRectA.left = dstRect.left + leftClip;
  1773.         dstRectA.right = dstRect.right - rightClip;
  1774.  
  1775.         
  1776.         if (leftClip)     // Draw bottom-left piece
  1777.         {
  1778.                 // Wrap source rect to upper-right corner
  1779.             srcRectB.top = srcFrameP->frameRect.top;
  1780.             srcRectB.right = srcFrameP->frameRect.right;
  1781.             srcRectB.bottom = srcFrameP->frameRect.top + bottomClip;
  1782.             srcRectB.left = srcFrameP->frameRect.right - leftClip;
  1783.             
  1784.                 // Position dest rect at bottom-left corner
  1785.             dstRectB.bottom = dstRect.bottom;
  1786.             dstRectB.left = dstRect.left;
  1787.             dstRectB.top = dstRect.bottom - bottomClip;
  1788.             dstRectB.right = dstRect.left + leftClip;
  1789.             
  1790.             if (spriteWorldP->doubleRectDrawProc != NULL)
  1791.             {
  1792.                     // RectB is passed first, since it is to the left of rectA
  1793.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  1794.                     &srcRectB, &dstRectB, &srcRectA, &dstRectA);
  1795.             }
  1796.             else
  1797.             {
  1798.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  1799.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  1800.             }
  1801.         }
  1802.         else if (rightClip)        // Draw bottom-right piece
  1803.         {
  1804.                 // Wrap source rect to upper-left corner
  1805.             srcRectB.top = srcFrameP->frameRect.top;
  1806.             srcRectB.left = srcFrameP->frameRect.left;
  1807.             srcRectB.bottom = srcFrameP->frameRect.top + bottomClip;
  1808.             srcRectB.right = srcFrameP->frameRect.left + rightClip;
  1809.             
  1810.                 // Position dest rect at bottom-right corner
  1811.             dstRectB.bottom = dstRect.bottom;
  1812.             dstRectB.right = dstRect.right;
  1813.             dstRectB.top = dstRect.bottom - bottomClip;
  1814.             dstRectB.left = dstRect.right - rightClip;
  1815.             
  1816.             if (spriteWorldP->doubleRectDrawProc != NULL)
  1817.             {
  1818.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  1819.                     &srcRectA, &dstRectA, &srcRectB, &dstRectB);
  1820.             }
  1821.             else
  1822.             {
  1823.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  1824.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  1825.             }
  1826.         }
  1827.         else
  1828.         {
  1829.                 // Draw just the bottom clip
  1830.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  1831.         }
  1832.     }
  1833. }
  1834.  
  1835.  
  1836. ///--------------------------------------------------------------------------------------
  1837. //    SWWrapRectToScreen - essentially the same as SWWrapWorldToScreen, except with some
  1838. //    extra code at the beginning to calculate the dstRect based on the srcRect, and clip it.
  1839. //    Used by SWFastAnimateScrollingSpriteWorld.
  1840. ///--------------------------------------------------------------------------------------
  1841.  
  1842. SW_FUNC void SWWrapRectToScreen(
  1843.     SpriteWorldPtr    spriteWorldP,
  1844.     Rect            *srcRectP)
  1845. {    
  1846.     FramePtr    srcFrameP = spriteWorldP->workFrameP;
  1847.     FramePtr    dstFrameP = spriteWorldP->windowFrameP;
  1848.     Rect        srcRect, dstRect, srcRectA, srcRectB, dstRectA, dstRectB;
  1849.     short        topClip=0, rightClip=0, bottomClip=0, leftClip=0;
  1850.     
  1851.     srcRect = *srcRectP;
  1852.     
  1853.         // dstRect = srcRect - spriteWorldP->visScrollRect + spriteWorldP->windRect;
  1854.     dstRect = srcRect;
  1855.     dstRect.top -= spriteWorldP->visScrollRect.top;
  1856.     dstRect.bottom -= spriteWorldP->visScrollRect.top;
  1857.     dstRect.left -= spriteWorldP->visScrollRect.left;
  1858.     dstRect.right -= spriteWorldP->visScrollRect.left;
  1859.     dstRect.top += spriteWorldP->windRect.top;
  1860.     dstRect.bottom += spriteWorldP->windRect.top;
  1861.     dstRect.left += spriteWorldP->windRect.left;
  1862.     dstRect.right += spriteWorldP->windRect.left;
  1863.  
  1864.         // Clip dstRect
  1865.     if (dstRect.top < spriteWorldP->windRect.top)
  1866.     {
  1867.         srcRect.top += spriteWorldP->windRect.top - dstRect.top;
  1868.         dstRect.top = spriteWorldP->windRect.top;
  1869.     }
  1870.     
  1871.     if (dstRect.bottom > spriteWorldP->windRect.bottom)
  1872.     {
  1873.         srcRect.bottom += spriteWorldP->windRect.bottom - dstRect.bottom;
  1874.         dstRect.bottom = spriteWorldP->windRect.bottom;
  1875.     }
  1876.     
  1877.     if (dstRect.left < spriteWorldP->windRect.left)
  1878.     {
  1879.         srcRect.left += spriteWorldP->windRect.left - dstRect.left;
  1880.         dstRect.left = spriteWorldP->windRect.left;
  1881.     }
  1882.     
  1883.     if (dstRect.right > spriteWorldP->windRect.right)
  1884.     {
  1885.         srcRect.right += spriteWorldP->windRect.right - dstRect.right;
  1886.         dstRect.right = spriteWorldP->windRect.right;
  1887.     }
  1888.     
  1889.         // Make sure rect is visible
  1890.     if ( (dstRect.right <= dstRect.left) || (dstRect.bottom <= dstRect.top) )
  1891.         return;
  1892.     
  1893.         // Make the srcRect local to the offscreen area
  1894.     srcRect.top -= spriteWorldP->vertScrollRectOffset;
  1895.     srcRect.bottom -= spriteWorldP->vertScrollRectOffset;
  1896.     srcRect.left -= spriteWorldP->horizScrollRectOffset;
  1897.     srcRect.right -= spriteWorldP->horizScrollRectOffset;
  1898.  
  1899.     
  1900.         // Clip the source rect, and save what we clipped for wrapping later //
  1901.     
  1902.         // clip off the top
  1903.     if (srcRect.top < srcFrameP->frameRect.top)
  1904.     {
  1905.         topClip = srcFrameP->frameRect.top - srcRect.top;
  1906.         srcRect.top += topClip;    
  1907.     }
  1908.     
  1909.         // clip off the bottom
  1910.     if (srcRect.bottom > srcFrameP->frameRect.bottom)
  1911.     {
  1912.         bottomClip = srcRect.bottom - srcFrameP->frameRect.bottom;
  1913.         srcRect.bottom -= bottomClip;
  1914.     }
  1915.     
  1916.         // clip off the left
  1917.     if (srcRect.left < srcFrameP->frameRect.left)
  1918.     {
  1919.         leftClip = srcFrameP->frameRect.left - srcRect.left;
  1920.         srcRect.left += leftClip;
  1921.     }
  1922.     
  1923.         // clip off the right
  1924.     if (srcRect.right > srcFrameP->frameRect.right)
  1925.     {
  1926.         rightClip = srcRect.right - srcFrameP->frameRect.right;
  1927.         srcRect.right -= rightClip;
  1928.     }
  1929.     
  1930.     
  1931.                     // Here we do the wrapping and drawing //
  1932.     
  1933.         // Draw top section //
  1934.     
  1935.     if (topClip)
  1936.     {
  1937.                 // Calculate top piece //
  1938.         
  1939.             // Wrap source rect to bottom side
  1940.         srcRectA.right = srcRect.right;                    // Copy clipped source rect
  1941.         srcRectA.left = srcRect.left;
  1942.         srcRectA.bottom = srcFrameP->frameRect.bottom;
  1943.         srcRectA.top = srcFrameP->frameRect.bottom - topClip;
  1944.         
  1945.             // Position dest rect at top side
  1946.         dstRectA.top = dstRect.top;
  1947.         dstRectA.bottom = dstRect.top + topClip;
  1948.         dstRectA.left = dstRect.left + leftClip;
  1949.         dstRectA.right = dstRect.right - rightClip;
  1950.         
  1951.         
  1952.         if (leftClip)    // Calculate top-left piece
  1953.         {
  1954.                 // Wrap source rect to lower-right corner
  1955.             srcRectB.bottom = srcFrameP->frameRect.bottom;
  1956.             srcRectB.right = srcFrameP->frameRect.right;
  1957.             srcRectB.top = srcFrameP->frameRect.bottom - topClip;
  1958.             srcRectB.left = srcFrameP->frameRect.right - leftClip;
  1959.             
  1960.                 // Position dest rect at top-left corner
  1961.             dstRectB.left = dstRect.left;
  1962.             dstRectB.top = dstRect.top;
  1963.             dstRectB.right = dstRect.left + leftClip;
  1964.             dstRectB.bottom = dstRect.top + topClip;
  1965.             
  1966.             if (spriteWorldP->doubleRectDrawProc != NULL)
  1967.             {
  1968.                     // RectB is passed first, since it is to the left of rectA
  1969.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  1970.                     &srcRectB, &dstRectB, &srcRectA, &dstRectA);
  1971.             }
  1972.             else
  1973.             {
  1974.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  1975.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  1976.             }
  1977.         }
  1978.         else if (rightClip)        // Calculate top-right piece
  1979.         {
  1980.                 // Wrap source rect to lower-left corner
  1981.             srcRectB.bottom = srcFrameP->frameRect.bottom;
  1982.             srcRectB.left = srcFrameP->frameRect.left;
  1983.             srcRectB.right = srcFrameP->frameRect.left + rightClip;
  1984.             srcRectB.top = srcFrameP->frameRect.bottom - topClip;
  1985.             
  1986.                 // Position dest rect at top-right corner
  1987.             dstRectB.top = dstRect.top;
  1988.             dstRectB.right = dstRect.right;
  1989.             dstRectB.bottom = dstRect.top + topClip;
  1990.             dstRectB.left = dstRect.right - rightClip;
  1991.             
  1992.             if (spriteWorldP->doubleRectDrawProc != NULL)
  1993.             {
  1994.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP,
  1995.                      &srcRectA, &dstRectA, &srcRectB, &dstRectB);
  1996.             }
  1997.             else
  1998.             {
  1999.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  2000.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  2001.             }
  2002.         }
  2003.         else
  2004.         {
  2005.                 // Draw just the top rect
  2006.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  2007.         }
  2008.     }
  2009.     
  2010.     
  2011.             // Draw middle section //
  2012.     
  2013.         // Calculate main middle piece (not wrapped)
  2014.     dstRectA.left = dstRect.left + leftClip;
  2015.     dstRectA.top = dstRect.top + topClip;
  2016.     dstRectA.right = dstRect.right - rightClip;
  2017.     dstRectA.bottom = dstRect.bottom - bottomClip;
  2018.     
  2019.     
  2020.     if (leftClip)    // Draw left piece
  2021.     {
  2022.             // Wrap source rect to right side
  2023.         srcRectB.top = srcRect.top;                // Copy clipped source rect
  2024.         srcRectB.bottom = srcRect.bottom;
  2025.         srcRectB.right = srcFrameP->frameRect.right;
  2026.         srcRectB.left = srcFrameP->frameRect.right - leftClip;
  2027.         
  2028.             // Position dest rect at left side
  2029.         dstRectB.left = dstRect.left;
  2030.         dstRectB.right = dstRect.left + leftClip;
  2031.         dstRectB.top = dstRect.top + topClip;
  2032.         dstRectB.bottom = dstRect.bottom - bottomClip;
  2033.         
  2034.         if (spriteWorldP->doubleRectDrawProc != NULL)
  2035.         {
  2036.                 // RectB is passed first, since it is to the left of rectA
  2037.             (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  2038.                 &srcRectB, &dstRectB, &srcRect, &dstRectA);
  2039.         }
  2040.         else
  2041.         {
  2042.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  2043.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRect, &dstRectA);
  2044.         }
  2045.     }
  2046.     else if (rightClip)        // Draw right piece
  2047.     {
  2048.             // Wrap source rect to left side
  2049.         srcRectB.top = srcRect.top;                // Copy clipped source rect
  2050.         srcRectB.bottom = srcRect.bottom;
  2051.         srcRectB.left = srcFrameP->frameRect.left;
  2052.         srcRectB.right = srcFrameP->frameRect.left + rightClip;
  2053.         
  2054.             // Position dest rect at right side
  2055.         dstRectB.right = dstRect.right;
  2056.         dstRectB.left = dstRect.right - rightClip;
  2057.         dstRectB.top = dstRect.top + topClip;
  2058.         dstRectB.bottom = dstRect.bottom - bottomClip;
  2059.         
  2060.         if (spriteWorldP->doubleRectDrawProc != NULL)
  2061.         {
  2062.             (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  2063.                 &srcRect, &dstRectA, &srcRectB, &dstRectB);
  2064.         }
  2065.         else
  2066.         {
  2067.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRect, &dstRectA);
  2068.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  2069.         }
  2070.     }
  2071.     else
  2072.     {
  2073.             // Draw just the middle piece
  2074.          (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRect, &dstRectA);
  2075.     }
  2076.     
  2077.     
  2078.         // Draw bottom section //
  2079.     
  2080.     if (bottomClip)
  2081.     {
  2082.             // Calculate bottom piece //
  2083.         
  2084.             // Wrap source rect to top side
  2085.         srcRectA.right = srcRect.right;                // Copy clipped source rect
  2086.         srcRectA.left = srcRect.left;
  2087.         srcRectA.top = srcFrameP->frameRect.top;
  2088.         srcRectA.bottom = srcFrameP->frameRect.top + bottomClip;
  2089.         
  2090.             // Position dest rect at bottom side
  2091.         dstRectA.bottom = dstRect.bottom;
  2092.         dstRectA.top = dstRect.bottom - bottomClip;
  2093.         dstRectA.left = dstRect.left + leftClip;
  2094.         dstRectA.right = dstRect.right - rightClip;
  2095.  
  2096.         
  2097.         if (leftClip)     // Draw bottom-left piece
  2098.         {
  2099.                 // Wrap source rect to upper-right corner
  2100.             srcRectB.top = srcFrameP->frameRect.top;
  2101.             srcRectB.right = srcFrameP->frameRect.right;
  2102.             srcRectB.bottom = srcFrameP->frameRect.top + bottomClip;
  2103.             srcRectB.left = srcFrameP->frameRect.right - leftClip;
  2104.             
  2105.                 // Position dest rect at bottom-left corner
  2106.             dstRectB.bottom = dstRect.bottom;
  2107.             dstRectB.left = dstRect.left;
  2108.             dstRectB.top = dstRect.bottom - bottomClip;
  2109.             dstRectB.right = dstRect.left + leftClip;
  2110.             
  2111.             if (spriteWorldP->doubleRectDrawProc != NULL)
  2112.             {
  2113.                     // RectB is passed first, since it is to the left of rectA
  2114.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  2115.                     &srcRectB, &dstRectB, &srcRectA, &dstRectA);
  2116.             }
  2117.             else
  2118.             {
  2119.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  2120.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  2121.             }
  2122.         }
  2123.         else if (rightClip)        // Draw bottom-right piece
  2124.         {
  2125.                 // Wrap source rect to upper-left corner
  2126.             srcRectB.top = srcFrameP->frameRect.top;
  2127.             srcRectB.left = srcFrameP->frameRect.left;
  2128.             srcRectB.bottom = srcFrameP->frameRect.top + bottomClip;
  2129.             srcRectB.right = srcFrameP->frameRect.left + rightClip;
  2130.             
  2131.                 // Position dest rect at bottom-right corner
  2132.             dstRectB.bottom = dstRect.bottom;
  2133.             dstRectB.right = dstRect.right;
  2134.             dstRectB.top = dstRect.bottom - bottomClip;
  2135.             dstRectB.left = dstRect.right - rightClip;
  2136.             
  2137.             if (spriteWorldP->doubleRectDrawProc != NULL)
  2138.             {
  2139.                 (*spriteWorldP->doubleRectDrawProc)(srcFrameP, dstFrameP, 
  2140.                     &srcRectA, &dstRectA, &srcRectB, &dstRectB);
  2141.             }
  2142.             else
  2143.             {
  2144.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  2145.                 (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectB, &dstRectB);
  2146.             }
  2147.         }
  2148.         else
  2149.         {
  2150.                 // Draw just the bottom clip
  2151.             (*spriteWorldP->screenDrawProc)(srcFrameP, dstFrameP, &srcRectA, &dstRectA);
  2152.         }
  2153.     }
  2154. }
  2155.  
  2156.  
  2157.  
  2158. ///--------------------------------------------------------------------------------------
  2159. //    SWCheckWrappedIdleSpriteOverlap - same as SWCheckIdleSpriteOverlap, 
  2160. //    but for scrolling SpriteWorlds.
  2161. ///--------------------------------------------------------------------------------------
  2162.  
  2163. SW_FUNC void SWCheckWrappedIdleSpriteOverlap(
  2164.     SpriteWorldPtr            spriteWorldP,
  2165.     register SpritePtr        idleSpriteP,
  2166.     SpritePtr                headActiveSpriteP)
  2167. {
  2168.     Rect                *visScrollRectP = &spriteWorldP->visScrollRect;
  2169.     register SpritePtr    activeSpriteP = headActiveSpriteP;
  2170.     Rect                srcSectRect,
  2171.                         dstSectRect;
  2172.     
  2173.     
  2174.         // iterate through the active sprites
  2175.     while (activeSpriteP != NULL)
  2176.     {        
  2177.             // do the sprites overlap?
  2178.         if ((idleSpriteP->oldFrameRect.top < activeSpriteP->deltaFrameRect.bottom) &&
  2179.              (idleSpriteP->oldFrameRect.bottom > activeSpriteP->deltaFrameRect.top) &&
  2180.              (idleSpriteP->oldFrameRect.left < activeSpriteP->deltaFrameRect.right) &&
  2181.              (idleSpriteP->oldFrameRect.right > activeSpriteP->deltaFrameRect.left))
  2182.         {
  2183.                 // calculate the intersection between the idle sprite's destination
  2184.                 // rect, and the active sprite's delta rect
  2185.             dstSectRect.left = 
  2186.                 SW_MAX(idleSpriteP->destFrameRect.left, activeSpriteP->deltaFrameRect.left);
  2187.             dstSectRect.top = 
  2188.                 SW_MAX(idleSpriteP->destFrameRect.top, activeSpriteP->deltaFrameRect.top);
  2189.             dstSectRect.right = 
  2190.                 SW_MIN(idleSpriteP->destFrameRect.right, activeSpriteP->deltaFrameRect.right);
  2191.             dstSectRect.bottom = 
  2192.                 SW_MIN(idleSpriteP->destFrameRect.bottom, activeSpriteP->deltaFrameRect.bottom);
  2193.             
  2194.                 // Clip the sprite's dstSectRect with visScrollRect
  2195.             if (dstSectRect.top < visScrollRectP->top)
  2196.                 dstSectRect.top = visScrollRectP->top;
  2197.             if (dstSectRect.bottom > visScrollRectP->bottom)
  2198.                 dstSectRect.bottom = visScrollRectP->bottom;
  2199.             if (dstSectRect.left < visScrollRectP->left)
  2200.                 dstSectRect.left = visScrollRectP->left;
  2201.             if (dstSectRect.right > visScrollRectP->right)
  2202.                 dstSectRect.right = visScrollRectP->right;
  2203.             
  2204.                 // Calculate the source rect
  2205.             srcSectRect = idleSpriteP->curFrameP->frameRect;
  2206.             
  2207.             srcSectRect.left += (dstSectRect.left - idleSpriteP->destFrameRect.left);
  2208.             srcSectRect.top += (dstSectRect.top - idleSpriteP->destFrameRect.top);
  2209.             srcSectRect.right -= (idleSpriteP->destFrameRect.right - dstSectRect.right);
  2210.             srcSectRect.bottom -= (idleSpriteP->destFrameRect.bottom - dstSectRect.bottom);
  2211.             
  2212.             
  2213.                 // Make the sprite's dest rect local to the offscreen area
  2214.             dstSectRect.top -= spriteWorldP->vertScrollRectOffset;
  2215.             dstSectRect.bottom -= spriteWorldP->vertScrollRectOffset;
  2216.             dstSectRect.left -= spriteWorldP->horizScrollRectOffset;
  2217.             dstSectRect.right -= spriteWorldP->horizScrollRectOffset;
  2218.         
  2219.             gCurrentSpriteBeingDrawn = idleSpriteP;
  2220.  
  2221.                 // Copy a piece of the sprite image onto the back drop piece    
  2222.             SWDrawWrappedSprite(idleSpriteP, spriteWorldP->workFrameP,
  2223.                 &srcSectRect, &dstSectRect);
  2224.             
  2225.             gCurrentSpriteBeingDrawn = NULL;
  2226.             
  2227.             if (spriteWorldP->tilingIsOn &&
  2228.                 idleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  2229.             {
  2230.                 dstSectRect.top += spriteWorldP->vertScrollRectOffset;
  2231.                 dstSectRect.bottom += spriteWorldP->vertScrollRectOffset;
  2232.                 dstSectRect.left += spriteWorldP->horizScrollRectOffset;
  2233.                 dstSectRect.right += spriteWorldP->horizScrollRectOffset;
  2234.                 SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect, idleSpriteP->tileDepth);
  2235.             }
  2236.         }
  2237.         
  2238.         activeSpriteP = activeSpriteP->nextActiveSpriteP;
  2239.     }
  2240. }
  2241.  
  2242.  
  2243. ///--------------------------------------------------------------------------------------
  2244. //    SWCheckWrappedIdleSpritesWithTiles - redraw sprites erased by tiles that changed
  2245. ///--------------------------------------------------------------------------------------
  2246.  
  2247. SW_FUNC void SWCheckWrappedIdleSpritesWithTiles(
  2248.     SpriteWorldPtr    spriteWorldP,
  2249.     SpritePtr        headIdleSpriteP)
  2250. {
  2251.     Rect        *visScrollRectP = &spriteWorldP->visScrollRect;
  2252.     Rect        srcSectRect, dstSectRect;
  2253.     register    SpritePtr idleSpriteP;
  2254.     Rect        *changedRectP;
  2255.     short        index;
  2256.     
  2257.  
  2258.         // Cycle through the changedTiles array of rects
  2259.     changedRectP = spriteWorldP->changedTiles;
  2260.     for (index = 0; index < spriteWorldP->numTilesChanged; index++, changedRectP++)
  2261.     {
  2262.         idleSpriteP = headIdleSpriteP;
  2263.     
  2264.             // iterate through the idle sprites
  2265.         while (idleSpriteP != NULL)
  2266.         {
  2267.                 // does the idle sprite overlap the changedRect?
  2268.             if ((idleSpriteP->oldFrameRect.top < changedRectP->bottom) &&
  2269.                  (idleSpriteP->oldFrameRect.bottom > changedRectP->top) &&
  2270.                  (idleSpriteP->oldFrameRect.left < changedRectP->right) &&
  2271.                  (idleSpriteP->oldFrameRect.right > changedRectP->left))
  2272.             {
  2273.                     // calculate the intersection between the idle sprite's old
  2274.                     // rect and the changedRectP
  2275.                 dstSectRect.left = SW_MAX(idleSpriteP->oldFrameRect.left, 
  2276.                                         changedRectP->left);
  2277.                 dstSectRect.top = SW_MAX(idleSpriteP->oldFrameRect.top, 
  2278.                                         changedRectP->top);
  2279.                 dstSectRect.right = SW_MIN(idleSpriteP->oldFrameRect.right, 
  2280.                                         changedRectP->right);
  2281.                 dstSectRect.bottom = SW_MIN(idleSpriteP->oldFrameRect.bottom, 
  2282.                                         changedRectP->bottom);
  2283.                 
  2284.                     // Clip the sprite's dstSectRect with visScrollRect
  2285.                 if (dstSectRect.top < visScrollRectP->top)
  2286.                     dstSectRect.top = visScrollRectP->top;
  2287.                 if (dstSectRect.bottom > visScrollRectP->bottom)
  2288.                     dstSectRect.bottom = visScrollRectP->bottom;
  2289.                 if (dstSectRect.left < visScrollRectP->left)
  2290.                     dstSectRect.left = visScrollRectP->left;
  2291.                 if (dstSectRect.right > visScrollRectP->right)
  2292.                     dstSectRect.right = visScrollRectP->right;
  2293.                     
  2294.                     // Calculate the source rect
  2295.                 srcSectRect = idleSpriteP->curFrameP->frameRect;
  2296.                 
  2297.                 srcSectRect.left += (dstSectRect.left - idleSpriteP->oldFrameRect.left);
  2298.                 srcSectRect.top += (dstSectRect.top - idleSpriteP->oldFrameRect.top);
  2299.                 srcSectRect.right -= (idleSpriteP->oldFrameRect.right - dstSectRect.right);
  2300.                 srcSectRect.bottom -= (idleSpriteP->oldFrameRect.bottom - dstSectRect.bottom);
  2301.                 
  2302.                 
  2303.                     // Make the sprite's dest rect local to the offscreen area
  2304.                 dstSectRect.top -= spriteWorldP->vertScrollRectOffset;
  2305.                 dstSectRect.bottom -= spriteWorldP->vertScrollRectOffset;
  2306.                 dstSectRect.left -= spriteWorldP->horizScrollRectOffset;
  2307.                 dstSectRect.right -= spriteWorldP->horizScrollRectOffset;
  2308.     
  2309.                 gCurrentSpriteBeingDrawn = idleSpriteP;
  2310.     
  2311.                     // Copy a piece of the sprite image onto the back drop piece    
  2312.                 SWDrawWrappedSprite(idleSpriteP, spriteWorldP->workFrameP,
  2313.                     &srcSectRect, &dstSectRect);
  2314.                     
  2315.                 gCurrentSpriteBeingDrawn = NULL;
  2316.                 
  2317.                 if (spriteWorldP->tilingIsOn &&
  2318.                     idleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  2319.                 {
  2320.                     dstSectRect.top += spriteWorldP->vertScrollRectOffset;
  2321.                     dstSectRect.bottom += spriteWorldP->vertScrollRectOffset;
  2322.                     dstSectRect.left += spriteWorldP->horizScrollRectOffset;
  2323.                     dstSectRect.right += spriteWorldP->horizScrollRectOffset;
  2324.                     SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect, idleSpriteP->tileDepth);
  2325.                 }
  2326.             }
  2327.             
  2328.             idleSpriteP = idleSpriteP->nextIdleSpriteP;
  2329.         }
  2330.     }
  2331. }
  2332.  
  2333.  
  2334. ///--------------------------------------------------------------------------------------
  2335. //    SWCheckWrappedIdleSpritesWithRects - redraw sprites erased by updateRects
  2336. ///--------------------------------------------------------------------------------------
  2337.  
  2338. SW_FUNC void SWCheckWrappedIdleSpritesWithRects(
  2339.     SpriteWorldPtr    spriteWorldP,
  2340.     SpritePtr        headIdleSpriteP)
  2341. {
  2342.     UpdateRectStructPtr    curRectStructP;
  2343.     register SpritePtr    idleSpriteP;
  2344.     Rect                *visScrollRectP = &spriteWorldP->visScrollRect;
  2345.     Rect                srcSectRect, dstSectRect;
  2346.     Rect                *changedRectP;
  2347.     
  2348.     
  2349.     curRectStructP = spriteWorldP->headUpdateRectP;
  2350.     
  2351.     while (curRectStructP != NULL)
  2352.     {
  2353.         changedRectP = &curRectStructP->updateRect;
  2354.         idleSpriteP = headIdleSpriteP;
  2355.     
  2356.             // iterate through the idle sprites
  2357.         while (idleSpriteP != NULL)
  2358.         {
  2359.                 // does the idle sprite overlap the changedRect?
  2360.             if ((idleSpriteP->oldFrameRect.top < changedRectP->bottom) &&
  2361.                  (idleSpriteP->oldFrameRect.bottom > changedRectP->top) &&
  2362.                  (idleSpriteP->oldFrameRect.left < changedRectP->right) &&
  2363.                  (idleSpriteP->oldFrameRect.right > changedRectP->left))
  2364.             {
  2365.                     // calculate the intersection between the idle sprite's old
  2366.                     // rect and the changedRectP
  2367.                 dstSectRect.left = SW_MAX(idleSpriteP->oldFrameRect.left, 
  2368.                                         changedRectP->left);
  2369.                 dstSectRect.top = SW_MAX(idleSpriteP->oldFrameRect.top, 
  2370.                                         changedRectP->top);
  2371.                 dstSectRect.right = SW_MIN(idleSpriteP->oldFrameRect.right, 
  2372.                                         changedRectP->right);
  2373.                 dstSectRect.bottom = SW_MIN(idleSpriteP->oldFrameRect.bottom, 
  2374.                                         changedRectP->bottom);
  2375.                 
  2376.                     // Clip the sprite's dstSectRect with visScrollRect
  2377.                 if (dstSectRect.top < visScrollRectP->top)
  2378.                     dstSectRect.top = visScrollRectP->top;
  2379.                 if (dstSectRect.bottom > visScrollRectP->bottom)
  2380.                     dstSectRect.bottom = visScrollRectP->bottom;
  2381.                 if (dstSectRect.left < visScrollRectP->left)
  2382.                     dstSectRect.left = visScrollRectP->left;
  2383.                 if (dstSectRect.right > visScrollRectP->right)
  2384.                     dstSectRect.right = visScrollRectP->right;
  2385.                     
  2386.                     // Calculate the source rect
  2387.                 srcSectRect = idleSpriteP->curFrameP->frameRect;
  2388.                 
  2389.                 srcSectRect.left += (dstSectRect.left - idleSpriteP->oldFrameRect.left);
  2390.                 srcSectRect.top += (dstSectRect.top - idleSpriteP->oldFrameRect.top);
  2391.                 srcSectRect.right -= (idleSpriteP->oldFrameRect.right - dstSectRect.right);
  2392.                 srcSectRect.bottom -= (idleSpriteP->oldFrameRect.bottom - dstSectRect.bottom);
  2393.                 
  2394.                 
  2395.                     // Make the sprite's dest rect local to the offscreen area
  2396.                 dstSectRect.top -= spriteWorldP->vertScrollRectOffset;
  2397.                 dstSectRect.bottom -= spriteWorldP->vertScrollRectOffset;
  2398.                 dstSectRect.left -= spriteWorldP->horizScrollRectOffset;
  2399.                 dstSectRect.right -= spriteWorldP->horizScrollRectOffset;
  2400.                 
  2401.                 gCurrentSpriteBeingDrawn = idleSpriteP;
  2402.     
  2403.                     // Copy a piece of the sprite image onto the back drop piece    
  2404.                 SWDrawWrappedSprite(idleSpriteP, spriteWorldP->workFrameP,
  2405.                     &srcSectRect, &dstSectRect);
  2406.                     
  2407.                 gCurrentSpriteBeingDrawn = NULL;
  2408.                 
  2409.                 if (spriteWorldP->tilingIsOn &&
  2410.                     idleSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
  2411.                 {
  2412.                     dstSectRect.top += spriteWorldP->vertScrollRectOffset;
  2413.                     dstSectRect.bottom += spriteWorldP->vertScrollRectOffset;
  2414.                     dstSectRect.left += spriteWorldP->horizScrollRectOffset;
  2415.                     dstSectRect.right += spriteWorldP->horizScrollRectOffset;
  2416.                     SWDrawTilesAboveSprite(spriteWorldP, &dstSectRect, idleSpriteP->tileDepth);
  2417.                 }
  2418.             }
  2419.  
  2420.             idleSpriteP = idleSpriteP->nextIdleSpriteP;
  2421.         }
  2422.         
  2423.         curRectStructP = curRectStructP->nextRectStructP;
  2424.     }
  2425. }
  2426.  
  2427.  
  2428. #pragma mark -
  2429. ///--------------------------------------------------------------------------------------
  2430. //  SWSetScrollingWorldMoveBounds
  2431. ///--------------------------------------------------------------------------------------
  2432.  
  2433. SW_FUNC void SWSetScrollingWorldMoveBounds(
  2434.     SpriteWorldPtr    spriteWorldP,
  2435.     Rect* scrollRectMoveBounds)
  2436. {
  2437.     spriteWorldP->scrollRectMoveBounds = *scrollRectMoveBounds;
  2438.     
  2439.         // Make sure the visScrollRect is still within its bounds
  2440.     SWMoveVisScrollRect(spriteWorldP, 
  2441.             spriteWorldP->visScrollRect.left,
  2442.             spriteWorldP->visScrollRect.top);
  2443. }
  2444.  
  2445.  
  2446. ///--------------------------------------------------------------------------------------
  2447. //    SWSetScrollingWorldMoveProc
  2448. ///--------------------------------------------------------------------------------------
  2449.  
  2450. SW_FUNC void SWSetScrollingWorldMoveProc(
  2451.     SpriteWorldPtr spriteWorldP, 
  2452.     WorldMoveProcPtr worldMoveProcP, 
  2453.     SpritePtr followSpriteP)
  2454. {
  2455.     spriteWorldP->worldMoveProc = worldMoveProcP;
  2456.     spriteWorldP->followSpriteP = followSpriteP;
  2457. }
  2458.  
  2459.  
  2460. ///--------------------------------------------------------------------------------------
  2461. //    SWSetDoubleRectDrawProc
  2462. ///--------------------------------------------------------------------------------------
  2463.  
  2464. SW_FUNC void SWSetDoubleRectDrawProc(
  2465.     SpriteWorldPtr        spriteWorldP,
  2466.     DoubleDrawProcPtr    drawProc)
  2467. {
  2468.     spriteWorldP->doubleRectDrawProc = drawProc;
  2469. }
  2470.  
  2471.  
  2472. ///--------------------------------------------------------------------------------------
  2473. //  SWSetSpriteWorldScrollDelta
  2474. ///--------------------------------------------------------------------------------------
  2475.  
  2476. SW_FUNC void SWSetSpriteWorldScrollDelta(
  2477.     SpriteWorldPtr    spriteWorldP,
  2478.     short            horizDelta,
  2479.     short            vertDelta)
  2480. {
  2481.     spriteWorldP->horizScrollDelta = horizDelta;
  2482.     spriteWorldP->vertScrollDelta = vertDelta;
  2483. }
  2484.  
  2485.  
  2486. ///--------------------------------------------------------------------------------------
  2487. //  SWMoveVisScrollRect - move visScrollRect to an absolute vertical and 
  2488. //    horizontal location
  2489. ///--------------------------------------------------------------------------------------
  2490.  
  2491. SW_FUNC void SWMoveVisScrollRect(
  2492.     SpriteWorldPtr    spriteWorldP,
  2493.     short            horizPos,
  2494.     short            vertPos)
  2495. {
  2496.     short    width, height;
  2497.     
  2498.     height = spriteWorldP->visScrollRect.bottom - spriteWorldP->visScrollRect.top;
  2499.     width = spriteWorldP->visScrollRect.right - spriteWorldP->visScrollRect.left;
  2500.     
  2501.     
  2502.             // Move visScrollRect and keep within moveBounds //
  2503.  
  2504.     
  2505.         // Move vertically
  2506.     if ((long)vertPos < spriteWorldP->scrollRectMoveBounds.top)
  2507.     {
  2508.         spriteWorldP->visScrollRect.top = spriteWorldP->scrollRectMoveBounds.top;
  2509.         spriteWorldP->visScrollRect.bottom = spriteWorldP->visScrollRect.top + height;
  2510.     }
  2511.     else if ((long)vertPos + height > spriteWorldP->scrollRectMoveBounds.bottom)
  2512.     {
  2513.         spriteWorldP->visScrollRect.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  2514.         spriteWorldP->visScrollRect.top = spriteWorldP->visScrollRect.bottom - height;
  2515.     }
  2516.     else
  2517.     {
  2518.         spriteWorldP->visScrollRect.top = vertPos;
  2519.         spriteWorldP->visScrollRect.bottom = vertPos + height;
  2520.     }
  2521.     
  2522.     
  2523.         // Move horizontally
  2524.     if ((long)horizPos < spriteWorldP->scrollRectMoveBounds.left)
  2525.     {
  2526.         spriteWorldP->visScrollRect.left = spriteWorldP->scrollRectMoveBounds.left;
  2527.         spriteWorldP->visScrollRect.right = spriteWorldP->visScrollRect.left + width;
  2528.     }
  2529.     else if ((long)horizPos + width > spriteWorldP->scrollRectMoveBounds.right)
  2530.     {
  2531.         spriteWorldP->visScrollRect.right = spriteWorldP->scrollRectMoveBounds.right;
  2532.         spriteWorldP->visScrollRect.left = spriteWorldP->visScrollRect.right - width;
  2533.     }
  2534.     else
  2535.     {
  2536.         spriteWorldP->visScrollRect.left = horizPos;
  2537.         spriteWorldP->visScrollRect.right = horizPos + width;
  2538.     }
  2539.     
  2540.     
  2541.     SWCalculateOffscreenScrollRect(spriteWorldP);
  2542. }
  2543.  
  2544.  
  2545. ///--------------------------------------------------------------------------------------
  2546. //  SWOffsetVisScrollRect - move visScrollRect to an absolute vertical and 
  2547. //    horizontal location, while keeping within the bounds of scrollRectMoveBounds
  2548. ///--------------------------------------------------------------------------------------
  2549.  
  2550. SW_FUNC void SWOffsetVisScrollRect(
  2551.     SpriteWorldPtr    spriteWorldP,
  2552.     short            horizOffset,
  2553.     short            vertOffset)
  2554. {
  2555.             // Move visScrollRect and keep within moveBounds //
  2556.  
  2557.         // Move vertically
  2558.     if ((long)spriteWorldP->visScrollRect.top + vertOffset <
  2559.             spriteWorldP->scrollRectMoveBounds.top)
  2560.     {
  2561.         spriteWorldP->visScrollRect.bottom -= spriteWorldP->visScrollRect.top -
  2562.             spriteWorldP->scrollRectMoveBounds.top;
  2563.         spriteWorldP->visScrollRect.top = spriteWorldP->scrollRectMoveBounds.top;
  2564.     }
  2565.     else if ((long)spriteWorldP->visScrollRect.bottom + vertOffset >
  2566.             spriteWorldP->scrollRectMoveBounds.bottom)
  2567.     {
  2568.         spriteWorldP->visScrollRect.top -= spriteWorldP->visScrollRect.bottom -
  2569.             spriteWorldP->scrollRectMoveBounds.bottom;
  2570.         spriteWorldP->visScrollRect.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  2571.     }
  2572.     else
  2573.     {
  2574.         spriteWorldP->visScrollRect.top += vertOffset;
  2575.         spriteWorldP->visScrollRect.bottom += vertOffset;
  2576.     }
  2577.     
  2578.     
  2579.         // Move horizontally
  2580.     if ((long)spriteWorldP->visScrollRect.left + horizOffset <
  2581.             spriteWorldP->scrollRectMoveBounds.left)
  2582.     {
  2583.         spriteWorldP->visScrollRect.right -= spriteWorldP->visScrollRect.left -
  2584.             spriteWorldP->scrollRectMoveBounds.left;
  2585.         spriteWorldP->visScrollRect.left = spriteWorldP->scrollRectMoveBounds.left;
  2586.     }
  2587.     else if ((long)spriteWorldP->visScrollRect.right + horizOffset >
  2588.             spriteWorldP->scrollRectMoveBounds.right)
  2589.     {
  2590.         spriteWorldP->visScrollRect.left -= spriteWorldP->visScrollRect.right -
  2591.             spriteWorldP->scrollRectMoveBounds.right;
  2592.         spriteWorldP->visScrollRect.right = spriteWorldP->scrollRectMoveBounds.right;
  2593.     }
  2594.     else
  2595.     {
  2596.         spriteWorldP->visScrollRect.left += horizOffset;
  2597.         spriteWorldP->visScrollRect.right += horizOffset;
  2598.     }
  2599.     
  2600.     
  2601.     SWCalculateOffscreenScrollRect(spriteWorldP);
  2602. }
  2603.  
  2604.  
  2605. ///--------------------------------------------------------------------------------------
  2606. //  SWResizeVisScrollRect - make the visScrollRect a new width and height.
  2607. //    Used by SWChangeWorldRect. Make sure to call SWUpdateScrollingSpriteWorld after
  2608. //    calling this.
  2609. ///--------------------------------------------------------------------------------------
  2610.  
  2611. SW_FUNC void SWResizeVisScrollRect(
  2612.     SpriteWorldPtr    spriteWorldP,
  2613.     short            width,
  2614.     short            height)
  2615. {
  2616.         // Will expanding it vertically move it past its bounds?
  2617.     if ((long)spriteWorldP->visScrollRect.top + height > 
  2618.         spriteWorldP->scrollRectMoveBounds.bottom)
  2619.     {
  2620.         spriteWorldP->visScrollRect.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
  2621.         spriteWorldP->visScrollRect.top = spriteWorldP->visScrollRect.bottom - height;
  2622.     }
  2623.     else
  2624.     {
  2625.         spriteWorldP->visScrollRect.bottom = spriteWorldP->visScrollRect.top + height;
  2626.     }
  2627.     
  2628.     
  2629.         // Will expanding it horizontally move it past its bounds?
  2630.     if ((long)spriteWorldP->visScrollRect.left + width > 
  2631.         spriteWorldP->scrollRectMoveBounds.right)
  2632.     {
  2633.         spriteWorldP->visScrollRect.right = spriteWorldP->scrollRectMoveBounds.right;
  2634.         spriteWorldP->visScrollRect.left = spriteWorldP->visScrollRect.right - width;
  2635.     }
  2636.     else
  2637.     {
  2638.         spriteWorldP->visScrollRect.right = spriteWorldP->visScrollRect.left + width;
  2639.     }
  2640.     
  2641.     spriteWorldP->oldVisScrollRect = spriteWorldP->visScrollRect;
  2642.     SWCalculateOffscreenScrollRect(spriteWorldP);
  2643. }
  2644.  
  2645.  
  2646. ///--------------------------------------------------------------------------------------
  2647. //  SWCalculateOffscreenScrollRect (wrap offscreenScrollRect in the work area)
  2648. ///--------------------------------------------------------------------------------------
  2649.  
  2650. SW_FUNC void SWCalculateOffscreenScrollRect(
  2651.     SpriteWorldPtr spriteWorldP)
  2652. {
  2653.     Rect *offscreenScrollRectP = &spriteWorldP->offscreenScrollRect;
  2654.     Rect *visScrollRectP = &spriteWorldP->visScrollRect;
  2655.     
  2656.     
  2657.     spriteWorldP->vertScrollRectOffset = spriteWorldP->backRect.bottom * 
  2658.         (visScrollRectP->top / spriteWorldP->backRect.bottom);
  2659.     
  2660.     spriteWorldP->horizScrollRectOffset = spriteWorldP->backRect.right *
  2661.         (visScrollRectP->left / spriteWorldP->backRect.right);
  2662.     
  2663.     
  2664.     offscreenScrollRectP->top = visScrollRectP->top - 
  2665.             spriteWorldP->vertScrollRectOffset;
  2666.     offscreenScrollRectP->bottom = visScrollRectP->bottom - 
  2667.             spriteWorldP->vertScrollRectOffset;
  2668.     offscreenScrollRectP->left = visScrollRectP->left - 
  2669.             spriteWorldP->horizScrollRectOffset;
  2670.     offscreenScrollRectP->right = visScrollRectP->right - 
  2671.             spriteWorldP->horizScrollRectOffset;
  2672. }
  2673.  
  2674.  
  2675.