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

  1. ///--------------------------------------------------------------------------------------
  2. // Scrolling Demo.c - Modified version
  3. //
  4. // By Vern Jensen. Created sometime in 1997
  5. ///--------------------------------------------------------------------------------------
  6.  
  7.  
  8. #include <SWFPSReport.h>
  9. #include <SWIncludes.h>
  10. #include <SWGameUtils.h>
  11.  
  12. #include "SWApplication.h"
  13. #include "Scrolling Demo.h"
  14.  
  15. #define kMaxWindowWidth                640            // User can expand window to this size
  16. #define kMaxWindowHeight            480
  17.  
  18. #define    kInterlacedMode                false        // Turns Interlaced mode on/off
  19. #define kSyncToVBL                    false        // Sync SpriteWorld to VBL?
  20. #define kMaxFPS                        30            // Set to 0 for unrestricted speed
  21.     
  22. #define    kSpriteMoveDelta            20            // Try 5, 10, 20, or 40
  23. #define kDiamondSpace                8            // How far apart the diamonds are spaced
  24.                                                 // (try 1!)
  25.  
  26. #define kSpriteMoveDistance            80            // How far the sprite can move from
  27.                                                 // the center of the screen, in pixels.
  28.                                                 // Try making this value higher!
  29.  
  30.     // Number of ticks to wait before changing tile image; 0 = change every frame
  31. #define kDiamondFrameRate            8            // How often diamond tiles change frames
  32. #define kWallFrameRate                120            // How often wall changes frames
  33.  
  34. #define kBWPictResIDOffset            100
  35. #define kTileWidth                    40
  36. #define kTileHeight                    40
  37. #define kTileMapRows                100
  38. #define kTileMapCols                150
  39.  
  40. #define kStartRow                    5            // Starting position of sprite
  41. #define kStartCol                    5            // in tile col and row
  42.  
  43.  
  44. #define    kLeftArrowKey                0x7B
  45. #define    kRightArrowKey                0x7C
  46. #define    kDownArrowKey                0x7D
  47. #define    kUpArrowKey                    0x7E
  48.  
  49. #define    kLeftKeyPad                    0x56
  50. #define    kRightKeyPad                0x58
  51. #define    kDownKeyPad                    0x54
  52. #define    kUpKeyPad                    0x5B
  53.  
  54. #define kEscKey                        0x35
  55.  
  56.  
  57. #define kNoKey                        0
  58. #define kLeftKey                    1
  59. #define kUpKey                        2
  60. #define kRightKey                    3
  61. #define kDownKey                    4
  62.  
  63.  
  64. enum tileIDs
  65. {
  66.     kWallTile,
  67.     kLastWallTile,
  68.     kGrassTile,
  69.     kBlackTile,
  70.     kDiamondTile,
  71.     kDiamondTile2,
  72.     kLastDiamondTile,
  73.     
  74.     kTunnelTile1,
  75.     kTunnelTile2,
  76.     kTunnelTile3,
  77.     kTunnelTile4,
  78.     kTunnelTile5,
  79.     kTunnelTile6,
  80.     kWireTile1,
  81.     kWireTile2,
  82.     
  83.     kMaxNumTiles
  84. };
  85.  
  86.  
  87.  
  88. /***********/
  89. /* Globals */
  90. /***********/
  91.  
  92. SpriteWorldPtr        gSpriteWorldP;
  93. SpriteLayerPtr        gSpriteLayerP;
  94. SpriteLayerPtr        gMouseSpriteLayerP;
  95. TileMapStructPtr    gTileMapStructP;
  96. TileMapPtr            gTileMap;
  97. SpritePtr            gSimpleSpriteP, gDiamondMeterSpriteP, gMouseSpriteP;
  98. DrawProcPtr            gSpriteDrawProc;
  99. DrawProcPtr            gScreenDrawProc;
  100. DoubleDrawProcPtr    gDoubleRectDrawProc;
  101. WindowPtr            gWindowP;
  102. Rect                gScreenMidRect;
  103. Boolean                gDone = false;
  104.  
  105. short                gNumDiamondsInMap = 0;    // Number of diamonds in the TileMap
  106. short                gNumDiamonds = 0;        // Number of diamonds sprite has collected
  107.  
  108. struct moveKeys        // Keeps track of which keys are up and which are down
  109. {
  110.     Boolean    up;
  111.     Boolean    right;
  112.     Boolean    down;
  113.     Boolean    left;
  114. } gKeys;
  115.  
  116.  
  117. ///--------------------------------------------------------------------------------------
  118. // Main
  119. ///--------------------------------------------------------------------------------------
  120.  
  121. void    main( void )
  122. {
  123.     Initialize(kNumberOfMoreMastersCalls);
  124.     
  125.     if (SWHasSystem7())
  126.     {
  127.         AllowKeyUpEvents();    // Part of SWGameUtils.c
  128.         SetCursor(*GetCursor(watchCursor));
  129.         
  130.         CreateSpriteWorld();
  131.         CreateBallSprite();
  132.         CreateDiamondMeterSprite();
  133.         CreateMouseSprite();
  134.         
  135.         SetCursor(&qd.arrow);
  136.         HideCursor();
  137.         
  138.         SetUpAnimation();
  139.         RunAnimation();
  140.         ShutDown();
  141.         
  142.         RestoreEventMask();    // Call this after AllowKeyUpEvents
  143.     }
  144.     else
  145.     {
  146.         CantRunOnThisMachine();
  147.     }
  148. }
  149.  
  150.  
  151. ///--------------------------------------------------------------------------------------
  152. // CreateSpriteWorld
  153. ///--------------------------------------------------------------------------------------
  154.  
  155. void    CreateSpriteWorld( void )
  156. {
  157.     Rect        offscreenRect, worldRect, windRect;
  158.     OSErr        err;
  159.     short        row, col;
  160.     short        resIDOffset;
  161.     WindowPeek    windowPeek;
  162.     WStateData    *wStateData;
  163.     
  164.     gWindowP = GetNewCWindow(129, NULL, (WindowPtr)-1L);
  165.     
  166.     if (gWindowP != NULL)
  167.     {
  168.             // Center window in screen
  169.         windRect = gWindowP->portRect;
  170.         if (qd.screenBits.bounds.bottom < 440 || qd.screenBits.bounds.right < 600)
  171.         {
  172.                 // We're running in 512x384, so make the window smaller so it can be moved
  173.             windRect.bottom -= 80;
  174.             windRect.right -= 80;
  175.             SizeWindow(gWindowP, windRect.right - windRect.left, 
  176.                         windRect.bottom - windRect.top, false);
  177.         }
  178.         CenterRect(&windRect, &qd.screenBits.bounds);
  179.         windRect.top += 10;
  180.         windRect.bottom += 10;
  181.         
  182.         AlignRect(&windRect);
  183.         MoveWindow(gWindowP, windRect.left, windRect.top, false);
  184.         
  185.         ShowWindow(gWindowP);
  186.         SetPort(gWindowP);
  187.         
  188.         if (kInterlacedMode)
  189.             PaintRect(&gWindowP->portRect);    // Blacken window for Interlaced mode
  190.     }
  191.     else
  192.         CantFindResource();
  193.     
  194.         // Change window's standard size to its current size. (Used when zooming window.)
  195.     windowPeek = (WindowPeek)gWindowP;
  196.     wStateData = (WStateData *) *(windowPeek->dataHandle);
  197.     wStateData->stdState = (**(windowPeek->contRgn)).rgnBBox;
  198.  
  199.     
  200.     err = SWEnterSpriteWorld();
  201.     FatalError(err);
  202.     
  203.     
  204.     worldRect = gWindowP->portRect;
  205.     
  206.         // Set size of offscreen area
  207.     offscreenRect = worldRect;
  208.     OffsetRect(&offscreenRect, -offscreenRect.left, -offscreenRect.top);
  209.     offscreenRect.right = SW_MAX(offscreenRect.right, kMaxWindowWidth);
  210.     offscreenRect.bottom = SW_MAX(offscreenRect.bottom, kMaxWindowHeight);
  211.  
  212.         // Make offscreen area evenly divisible by tile width & height
  213.     if ( (offscreenRect.right/kTileWidth)*kTileWidth != offscreenRect.right)
  214.         offscreenRect.right = (offscreenRect.right/kTileWidth)*kTileWidth + kTileWidth;
  215.     
  216.     if ( (offscreenRect.bottom/kTileHeight)*kTileHeight != offscreenRect.bottom)
  217.         offscreenRect.bottom = (offscreenRect.bottom/kTileHeight)*kTileHeight + kTileHeight;
  218.     
  219.         // Create the scrolling sprite world
  220.     err = SWCreateSpriteWorldFromWindow(&gSpriteWorldP, (CWindowPtr)gWindowP, 
  221.             &worldRect, &offscreenRect, 0);
  222.     FatalError(err);
  223.     
  224.     
  225.             // Create the sprite layers
  226.     err = SWCreateSpriteLayer(&gSpriteLayerP);
  227.     FatalError(err);
  228.     err = SWCreateSpriteLayer(&gMouseSpriteLayerP);
  229.     FatalError(err);
  230.     
  231.         // add the layers to the world
  232.     SWAddSpriteLayer(gSpriteWorldP, gSpriteLayerP);            // Bottom layer
  233.     SWAddSpriteLayer(gSpriteWorldP, gMouseSpriteLayerP);    // Top layer
  234.  
  235.  
  236.     err = SWInitTiling(gSpriteWorldP, kTileHeight, kTileWidth, kMaxNumTiles);
  237.     FatalError(err);
  238.     
  239.     err = SWCreateTileMap(&gTileMapStructP, kTileMapRows, kTileMapCols);
  240.     FatalError(err);
  241.     
  242.     SWInstallTileMap(gSpriteWorldP, gTileMapStructP, 0);
  243.     gTileMap = gTileMapStructP->tileMap;
  244.     
  245.     SWSetSpriteLayerUnderTileLayer(gSpriteLayerP, 0);
  246.     
  247.  
  248.         // Determine whether to load B&W or color graphics
  249.     if (gSpriteWorldP->pixelDepth <= 2)
  250.         resIDOffset = kBWPictResIDOffset;
  251.     else
  252.         resIDOffset = 0;
  253.  
  254.         // Load first set of tiles
  255.     err = SWLoadTilesFromPictResource(
  256.         gSpriteWorldP, 
  257.         kWallTile,                // startTileID 
  258.         kLastDiamondTile,        // endTileID
  259.         200 + resIDOffset,        // pictResID
  260.         0,                        // maskResID
  261.         kNoMask,                // maskType
  262.         1,                        // horizBorderWidth
  263.         1);                        // vertBorderHeight
  264.     FatalError(err);
  265.     
  266.         // Load masked set of tiles
  267.     err = SWLoadTilesFromPictResource(
  268.         gSpriteWorldP, 
  269.         kTunnelTile1,            // startTileID 
  270.         kWireTile2,                // endTileID
  271.         201 + resIDOffset,        // pictResID
  272.         401,                    // maskResID
  273.         kFatMask,                // maskType
  274.         1,                        // horizBorderWidth
  275.         1);                        // vertBorderHeight
  276.     FatalError(err);
  277.  
  278.     
  279.         // Set up tileMap
  280.     for (row = 0; row < kTileMapRows; row++)
  281.     {
  282.         for (col = 0; col < kTileMapCols; col++)
  283.         {
  284.             if (row == 0 || col == 0 || row == kTileMapRows-1 || col == kTileMapCols-1)
  285.                 gTileMap[row][col] = kWallTile;
  286.             else if (row > kTileMapRows / 2)
  287.                 gTileMap[row][col] = kWireTile1;
  288.             else if ((row/kDiamondSpace)*kDiamondSpace == row && 
  289.                      (col/kDiamondSpace)*kDiamondSpace == col)
  290.             {
  291.                 gTileMap[row][col] = kDiamondTile;
  292.                 gNumDiamondsInMap++;
  293.             }
  294.             else
  295.                 gTileMap[row][col] = kGrassTile;
  296.         }
  297.     }
  298.     
  299.  
  300.         // Add tunnel to tileMap
  301.     row = kTileMapRows / 2;
  302.  
  303.     for (col = 1; col < kTileMapCols-1; col += 2)
  304.     {
  305.         gTileMap[row][col] = kTunnelTile1;
  306.         gTileMap[row][col+1] = kTunnelTile2;
  307.         gTileMap[row+1][col] = kTunnelTile4;
  308.         gTileMap[row+1][col+1] = kTunnelTile5;
  309.     }
  310.     
  311.     
  312.         // Determine what DrawProcs to use
  313.     if (gSpriteWorldP->pixelDepth == 8)        // 256 colors
  314.     {
  315.         if (kInterlacedMode)
  316.         {
  317.             gSpriteDrawProc = BP8BitInterlacedMaskDrawProc;
  318.             gScreenDrawProc = BP8BitInterlacedRectDrawProc;
  319.             gDoubleRectDrawProc = BP8BitInterlacedDoubleRectDrawProc;
  320.             SWSetTileMaskDrawProc(gSpriteWorldP, BP8BitInterlacedPartialMaskDrawProc);
  321.         }
  322.         else
  323.         {
  324.             gSpriteDrawProc = BlitPixie8BitMaskDrawProc;
  325.             gScreenDrawProc = BlitPixie8BitRectDrawProc;
  326.             gDoubleRectDrawProc = BlitPixie8BitDoubleRectDrawProc;
  327.             SWSetTileMaskDrawProc(gSpriteWorldP, BlitPixie8BitPartialMaskDrawProc);
  328.         }
  329.     }
  330.     else if ( !(SW_PPC && gSpriteWorldP->pixelDepth < 8) )    // Not 256 colors
  331.     {
  332.             // Use interlaced drawProcs unless in B&W, where interlacing is ugly
  333.         if (kInterlacedMode && gSpriteWorldP->pixelDepth > 2)
  334.         {
  335.             gSpriteDrawProc = BPAllBitInterlacedMaskDrawProc;
  336.             gScreenDrawProc = BPAllBitInterlacedRectDrawProc;
  337.             SWSetTileMaskDrawProc(gSpriteWorldP, BPAllBitInterlacedPartialMaskDrawProc);
  338.             if (gSpriteWorldP->pixelDepth == 16)
  339.                 gDoubleRectDrawProc = BP16BitInterlacedDoubleRectDrawProc;
  340.         }
  341.         else
  342.         {
  343.             gSpriteDrawProc = BlitPixieAllBitMaskDrawProc;
  344.             gScreenDrawProc = BlitPixieAllBitRectDrawProc;
  345.             SWSetTileMaskDrawProc(gSpriteWorldP, BlitPixieAllBitPartialMaskDrawProc);
  346.             if (gSpriteWorldP->pixelDepth == 16)
  347.                 gDoubleRectDrawProc = BlitPixie16BitDoubleRectDrawProc;
  348.         }
  349.     }
  350.     else
  351.     {
  352.         gSpriteDrawProc = SWStdSpriteDrawProc;
  353.         gScreenDrawProc = SWStdWorldDrawProc;
  354.         gDoubleRectDrawProc = NULL;
  355.     }
  356. }
  357.     
  358.  
  359. ///--------------------------------------------------------------------------------------
  360. // CreateBallSprite
  361. ///--------------------------------------------------------------------------------------
  362.  
  363. void    CreateBallSprite( void )
  364. {
  365.     OSErr                err;
  366.     
  367.         // Create the ball sprite
  368.     err = SWCreateSpriteFromCicnResource(gSpriteWorldP, &gSimpleSpriteP, NULL, 
  369.             128, 1, kFatMask);    
  370.     FatalError(err);
  371.     
  372.         // Set up the ball sprite
  373.     SWAddSprite(gSpriteLayerP, gSimpleSpriteP);
  374.     SWSetSpriteMoveProc(gSimpleSpriteP, KeySpriteMoveProc);
  375.     SWSetSpriteLocation(gSimpleSpriteP, kStartCol * kTileWidth, kStartRow * kTileHeight);
  376.     SWSetSpriteMoveDelta(gSimpleSpriteP, 0, 0);
  377.     SWSetSpriteDrawProc(gSimpleSpriteP, gSpriteDrawProc);
  378. }
  379.  
  380.  
  381. ///--------------------------------------------------------------------------------------
  382. // CreateDiamondMeterSprite
  383. ///--------------------------------------------------------------------------------------
  384.  
  385. void    CreateDiamondMeterSprite( void )
  386. {
  387.     short                spriteResID;
  388.     OSErr                err;
  389.     
  390.         // Calculate resource ID for diamond meter sprite
  391.     if (gSpriteWorldP->pixelDepth <= 2)
  392.         spriteResID = 302;
  393.     else
  394.         spriteResID = 202;
  395.     
  396.         // Create the diamond meter sprite
  397.     err = SWCreateSpriteFromPictResource(gSpriteWorldP,
  398.                 &gDiamondMeterSpriteP, 
  399.                 NULL,            // pointer to memory for sprite
  400.                 spriteResID,     // picture resource id
  401.                 402,            // mask resource id
  402.                 1,                 // max frames
  403.                 kPixelMask);        // mask type
  404.     FatalError(err);
  405.     
  406.     SWAddSprite(gSpriteLayerP, gDiamondMeterSpriteP);
  407.     SWSetSpriteDrawProc(gDiamondMeterSpriteP, gSpriteDrawProc);
  408. }
  409.  
  410.  
  411. ///--------------------------------------------------------------------------------------
  412. // CreateMouseSprite
  413. ///--------------------------------------------------------------------------------------
  414.  
  415. void    CreateMouseSprite( void )
  416. {
  417.     OSErr                err;
  418.     
  419.         // Create the mouse sprite
  420.     err = SWCreateSpriteFromCicnResource(gSpriteWorldP, &gMouseSpriteP, NULL, 
  421.             130, 1, kPixelMask);    
  422.     FatalError(err);
  423.  
  424.     SWAddSprite(gMouseSpriteLayerP, gMouseSpriteP);
  425.     SWSetSpriteDrawProc(gMouseSpriteP, gSpriteDrawProc);
  426. }
  427.  
  428.  
  429. ///--------------------------------------------------------------------------------------
  430. // SetUpAnimation
  431. ///--------------------------------------------------------------------------------------
  432.  
  433. void    SetUpAnimation( void )
  434. {
  435.     Rect        moveBoundsRect, worldRect;
  436.     
  437.     SWLockSpriteWorld(gSpriteWorldP);
  438.     
  439.         // Set up data used by the SmoothScrollingWorldMoveProc
  440.     gScreenMidRect = gSimpleSpriteP->curFrameP->frameRect;
  441.     worldRect = gSpriteWorldP->windRect;
  442.     OffsetRect(&worldRect, -worldRect.left, -worldRect.top);
  443.     CenterRect( &gScreenMidRect, &worldRect );
  444.     
  445.     SWSetSpriteWorldMaxFPS(gSpriteWorldP, kMaxFPS);
  446.     SWSyncSpriteWorldToVBL(gSpriteWorldP, kSyncToVBL);
  447.     
  448.         // movement boundary = size of tileMap
  449.     SetRect(&moveBoundsRect, 0,0, kTileMapCols * kTileWidth, kTileMapRows * kTileHeight);
  450.     
  451.     SWSetScrollingWorldMoveBounds(gSpriteWorldP, &moveBoundsRect);
  452.     SWSetScrollingWorldMoveProc(gSpriteWorldP, SmoothScrollingWorldMoveProc, gSimpleSpriteP);
  453.     
  454.     SWSetTileChangeProc(gSpriteWorldP, TileChangeProc);
  455.     
  456.         // Move visScrollRect to starting sprite position
  457.     SWMoveVisScrollRect(gSpriteWorldP, 
  458.         gSpriteWorldP->followSpriteP->destFrameRect.left - gSpriteWorldP->backRect.right/2,
  459.         gSpriteWorldP->followSpriteP->destFrameRect.top - gSpriteWorldP->backRect.bottom/2);
  460.     
  461.         // Set starting position of diamond meter sprite
  462.     DiamondMeterSpriteMoveProc(gDiamondMeterSpriteP);
  463.  
  464.     SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, gScreenDrawProc);
  465.     SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, gScreenDrawProc);
  466.     SWSetDoubleRectDrawProc(gSpriteWorldP, gDoubleRectDrawProc);
  467.     
  468.         // Make sure CopyBits, if used, doesn't try to colorize things
  469.     SWSetPortToWindow(gSpriteWorldP);
  470.     ForeColor(blackColor);
  471.     BackColor(whiteColor);
  472.     
  473.     SWSetPortToWorkArea(gSpriteWorldP);
  474.     ForeColor(blackColor);
  475.     PaintRect(&gSpriteWorldP->backRect);
  476.     SWDrawTilesInBackground(gSpriteWorldP);
  477.     SWUpdateScrollingSpriteWorld(gSpriteWorldP, true);
  478.     ShowCursor();
  479. }
  480.  
  481.  
  482. ///--------------------------------------------------------------------------------------
  483. //  RunAnimation
  484. ///--------------------------------------------------------------------------------------
  485.  
  486. void    RunAnimation( void )
  487. {
  488.     EventRecord            event;
  489.     unsigned long        frames;
  490.     
  491.     frames = 0;
  492.     StartTimer();
  493.  
  494.     while (!gDone)
  495.     {
  496.         if ( WaitNextEvent(everyEvent, &event, 0L, NULL) )
  497.             DispatchEvent(&event);
  498.  
  499.             // Make sure window wasn't "rolled up" with WindowShade
  500.         if ( !EmptyRgn( gWindowP->visRgn ) )
  501.         {
  502.             SWProcessScrollingSpriteWorld(gSpriteWorldP);
  503.     
  504.                 // Move diamond meter & mouse sprites to new visScrollRect location
  505.             DiamondMeterSpriteMoveProc(gDiamondMeterSpriteP);
  506.             MouseSpriteMoveProc(gMouseSpriteP);
  507.                 
  508.             SWAnimateScrollingSpriteWorld(gSpriteWorldP);
  509.             
  510.             if (gSpriteWorldP->frameHasOccurred)
  511.                 frames++;
  512.         }
  513.     }
  514.     
  515.     ShowResults(frames);
  516. }
  517.  
  518. ///--------------------------------------------------------------------------------------
  519. //  DispatchEvent
  520. ///--------------------------------------------------------------------------------------
  521.  
  522. void DispatchEvent(EventRecord* event)
  523. {
  524.     short            theKey, theChar;
  525.     Boolean            isDown;
  526.     
  527.     switch(event->what)
  528.     {
  529.         case mouseDown:
  530.             HandleMouseDown( event );
  531.             break;
  532.         case mouseUp:
  533.             break;
  534.         case keyUp:
  535.         case keyDown:
  536.         case autoKey:
  537.             theKey = (event->message & keyCodeMask) >> 8;
  538.             theChar = event->message & charCodeMask;
  539.             isDown = (event->what != keyUp);
  540.             
  541.             if ( (theKey == kLeftArrowKey) || (theKey == kLeftKeyPad) )
  542.                 gKeys.left = isDown;
  543.             else if ( (theKey == kRightArrowKey) || (theKey == kRightKeyPad) )
  544.                 gKeys.right = isDown;
  545.             else if ( (theKey == kDownArrowKey) || (theKey == kDownKeyPad) )
  546.                 gKeys.down = isDown;
  547.             else if ( (theKey == kUpArrowKey) || (theKey == kUpKeyPad) )
  548.                 gKeys.up = isDown;
  549.             else if ( (theKey == kEscKey) || (theChar == 'Q') || (theChar == 'q') )
  550.                 gDone = true;
  551.             break;
  552.             break;
  553.         case updateEvt:
  554.             break;
  555.         case diskEvt:
  556.             break;
  557.         case activateEvt:
  558.             break;
  559.         case networkEvt:
  560.             break;
  561.         case driverEvt:
  562.             break;
  563.         case app1Evt:
  564.             break;
  565.         case app2Evt:
  566.             break;
  567.         case app3Evt:
  568.             break;
  569.         case osEvt:
  570.             if ( ( event->message & suspendResumeMessage ) == resumeFlag )
  571.             {
  572.                 SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, gScreenDrawProc);
  573.                 SWSetDoubleRectDrawProc(gSpriteWorldP, gDoubleRectDrawProc);
  574.             }
  575.             else
  576.             {
  577.                 SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, SWStdWorldDrawProc);
  578.                 SWSetDoubleRectDrawProc(gSpriteWorldP, NULL);
  579.             }
  580.             break;
  581.         case kHighLevelEvent:
  582.             break;
  583.         default:
  584.         break;
  585.     }
  586. }
  587.  
  588.  
  589. ///--------------------------------------------------------------------------------------
  590. //  HandleMouseDown
  591. ///--------------------------------------------------------------------------------------
  592.  
  593. void    HandleMouseDown( EventRecord *eventPtr )
  594. {
  595.     WindowPtr        theWindow;
  596.     Rect            windRect;
  597.     short            thePart;
  598.     Point            thePoint;
  599.     long            windowSize;
  600.     Rect            worldRect;
  601.     
  602.     
  603.     thePoint = eventPtr->where;
  604.     thePart = FindWindow( thePoint, &theWindow );
  605.  
  606.     switch ( thePart )
  607.     {
  608.         case inSysWindow : 
  609.             SystemClick( eventPtr, theWindow );
  610.             break;
  611.         case inDrag:
  612.             DragWindow( theWindow, thePoint, &((**(GetGrayRgn())).rgnBBox) );
  613.             windRect = (*((WindowPeek)gWindowP)->contRgn)->rgnBBox;
  614.             
  615.             AlignRect(&windRect);
  616.             MoveWindow(gWindowP, windRect.left, windRect.top, false);
  617.             
  618.             SWWindowMoved( gSpriteWorldP );
  619.             break;
  620.         case inZoomOut:
  621.         case inZoomIn:
  622.             if ( TrackBox(theWindow, thePoint, thePart) )
  623.             {
  624.                 ZoomWindow(theWindow, thePart, true);
  625.                 SWChangeWorldRect( gSpriteWorldP, &theWindow->portRect, false);
  626.                 SWDrawTilesInBackground( gSpriteWorldP );
  627.                 SWUpdateScrollingSpriteWorld( gSpriteWorldP , false );
  628.             
  629.                     // Reset data used by SmoothScrollingWorldMoveProc
  630.                 worldRect = gSpriteWorldP->windRect;
  631.                 OffsetRect(&worldRect, -worldRect.left, -worldRect.top);
  632.                 CenterRect( &gScreenMidRect, &worldRect );
  633.             }
  634.             break;
  635.         case inMenuBar:
  636.             break;
  637.         case inGoAway:
  638.             if ( TrackGoAway(theWindow, thePoint) )
  639.                 gDone = true;
  640.             break;
  641.         case inGrow:
  642.             SetRect(&windRect, 80, 80, 
  643.                 gSpriteWorldP->originalBackRect.right - gSpriteWorldP->originalBackRect.left+1, 
  644.                 gSpriteWorldP->originalBackRect.bottom - gSpriteWorldP->originalBackRect.top+1); 
  645.             windowSize = GrowWindow( theWindow, eventPtr->where, &windRect );
  646.             SizeWindow( theWindow, LoWord(windowSize), HiWord(windowSize), true);
  647.             SWChangeWorldRect( gSpriteWorldP, &theWindow->portRect, false);
  648.             SWDrawTilesInBackground( gSpriteWorldP );
  649.             SWUpdateScrollingSpriteWorld( gSpriteWorldP , false );
  650.             
  651.                 // Reset data used by SmoothScrollingWorldMoveProc
  652.             worldRect = gSpriteWorldP->windRect;
  653.             OffsetRect(&worldRect, -worldRect.left, -worldRect.top);
  654.             CenterRect( &gScreenMidRect, &worldRect );
  655.             break;
  656.         case inContent:
  657.             break;
  658.     }
  659. }
  660.  
  661.  
  662. ///--------------------------------------------------------------------------------------
  663. //  ShutDown (clean up and dispose of the SpriteWorld)
  664. ///--------------------------------------------------------------------------------------
  665.  
  666. void    ShutDown( void )
  667. {
  668.     SWDisposeSpriteWorld(&gSpriteWorldP);
  669.     SWExitSpriteWorld();
  670.     
  671.     FlushEvents(everyEvent, 0);
  672.     ShowCursor();
  673. }
  674.  
  675.  
  676. ///--------------------------------------------------------------------------------------
  677. //  TileChangeProc
  678. ///--------------------------------------------------------------------------------------
  679.  
  680. SW_FUNC void TileChangeProc(
  681.     SpriteWorldPtr spriteWorldP)
  682. {
  683.     short            curImage;
  684.     static short    wallDelay = 0, diamondDelay = 0;
  685.     static short    oldTicks = 0;
  686.     short            ticksPassed, ticks;
  687.     
  688.         // Initialize oldTicks the first time this function is called
  689.     if (oldTicks == 0)
  690.         oldTicks = TickCount();
  691.     
  692.     ticks = TickCount();
  693.     ticksPassed = ticks - oldTicks;        // Number of ticks passed since last call
  694.     oldTicks = ticks;
  695.     
  696.         // kWallTile
  697.     wallDelay += ticksPassed;
  698.     if (wallDelay >= kWallFrameRate)
  699.     {
  700.         curImage = spriteWorldP->curTileImage[kWallTile];
  701.         if (curImage < kLastWallTile)
  702.             curImage++;
  703.         else
  704.             curImage = kWallTile;
  705.         
  706.         SWChangeTileImage(spriteWorldP, kWallTile, curImage);
  707.         wallDelay = 0;
  708.     }
  709.     
  710.     
  711.         // kDiamondTile
  712.     diamondDelay += ticksPassed;
  713.     if (diamondDelay >= kDiamondFrameRate)
  714.     {
  715.         curImage = spriteWorldP->curTileImage[kDiamondTile];
  716.         if (curImage < kLastDiamondTile)
  717.             curImage++;
  718.         else
  719.             curImage = kDiamondTile;
  720.         
  721.         SWChangeTileImage(spriteWorldP, kDiamondTile, curImage);
  722.         diamondDelay = 0;
  723.     }
  724. }
  725.  
  726.  
  727. ///--------------------------------------------------------------------------------------
  728. //  KeySpriteMoveProc
  729. ///--------------------------------------------------------------------------------------
  730.  
  731. SW_FUNC void KeySpriteMoveProc(SpritePtr srcSpriteP)
  732. {
  733.     short    row, col;
  734.     short    rowDelta, colDelta;
  735.     short    tile;
  736.     
  737.     
  738.     row = srcSpriteP->destFrameRect.top / kTileHeight;
  739.     col = srcSpriteP->destFrameRect.left / kTileWidth;
  740.  
  741.     if (row * kTileHeight == srcSpriteP->destFrameRect.top &&
  742.         col * kTileWidth == srcSpriteP->destFrameRect.left)
  743.     {
  744.         tile = gTileMap[row][col];
  745.         
  746.             // Leave black trail behind sprite
  747.         if (tile == kGrassTile || tile == kDiamondTile)
  748.             SWDrawTile(gSpriteWorldP, 0, row, col, kBlackTile);
  749.         else if (tile == kTunnelTile2 || tile == kTunnelTile5 || tile == kWireTile1)
  750.             SWDrawTile(gSpriteWorldP, 0, row, col, tile+1);
  751.             
  752.         if (tile == kDiamondTile)
  753.         {
  754.             gNumDiamonds++;            // Increase number of diamonds sprite has collected
  755.             UpdateDiamondMeter();    // Update meter
  756.         }
  757.         
  758.  
  759.         rowDelta = 0;
  760.         colDelta = 0;
  761.         
  762.         if (gKeys.left)
  763.             colDelta = -1;
  764.         else if (gKeys.right)
  765.             colDelta = 1;
  766.         else if (gKeys.up)
  767.             rowDelta = -1;
  768.         else if (gKeys.down)
  769.             rowDelta = 1;
  770.         
  771.                 
  772.         
  773.         tile = gTileMap[row + rowDelta][col + colDelta];
  774.         
  775.         if (tile != kWallTile && tile != kTunnelTile1 && tile != kTunnelTile4)
  776.         {
  777.             srcSpriteP->vertMoveDelta = rowDelta * kSpriteMoveDelta;
  778.             srcSpriteP->horizMoveDelta = colDelta * kSpriteMoveDelta;
  779.         }
  780.         else
  781.         {
  782.             srcSpriteP->vertMoveDelta = 0;
  783.             srcSpriteP->horizMoveDelta = 0;
  784.         }
  785.     }
  786.     
  787.     SWOffsetSprite(srcSpriteP, srcSpriteP->horizMoveDelta, srcSpriteP->vertMoveDelta);
  788. }
  789.  
  790.  
  791. ///--------------------------------------------------------------------------------------
  792. //  MouseSpriteMoveProc
  793. ///--------------------------------------------------------------------------------------
  794.  
  795. SW_FUNC void MouseSpriteMoveProc(SpritePtr srcSpriteP)
  796. {
  797.     Point                mousePoint;
  798.     
  799.         // Get mouse coordinates local to the window
  800.     SetPort(gWindowP);
  801.     GetMouse(&mousePoint);
  802.     
  803.         // Subtract any offset from worldRect to window if a worldRect is used
  804.     mousePoint.h -= gSpriteWorldP->windRect.left;
  805.     mousePoint.v -= gSpriteWorldP->windRect.top;
  806.     
  807.     SWMoveSprite(srcSpriteP, 
  808.         mousePoint.h - 1 + gSpriteWorldP->visScrollRect.left, 
  809.         mousePoint.v - 1 + gSpriteWorldP->visScrollRect.top);
  810. }
  811.  
  812.  
  813. ///--------------------------------------------------------------------------------------
  814. //  DiamondMeterSpriteMoveProc - not installed as a MoveProc, but called directly
  815. ///--------------------------------------------------------------------------------------
  816.  
  817. SW_FUNC void DiamondMeterSpriteMoveProc(SpritePtr srcSpriteP)
  818. {
  819.         // Move sprite to top-left corner of current visScrollRect location
  820.     SWMoveSprite(srcSpriteP, 
  821.         gSpriteWorldP->visScrollRect.left + 10, 
  822.         gSpriteWorldP->visScrollRect.top + 10);
  823. }
  824.  
  825.  
  826. ///--------------------------------------------------------------------------------------
  827. //  UpdateDiamondMeter - change the meter Sprite's image and mask
  828. ///--------------------------------------------------------------------------------------
  829.  
  830. SW_FUNC void UpdateDiamondMeter( void )
  831. {
  832.     double    percent;
  833.     Rect    meterRect;
  834.     
  835.     percent = (double)gNumDiamonds / gNumDiamondsInMap;
  836.     
  837.     SetRect(&meterRect, 17, 2, (108 * percent) + 17, 14);
  838.     
  839.     
  840.         // Set port to our sprite's framePort GWorld
  841.     SetGWorld(gDiamondMeterSpriteP->curFrameP->framePort, nil);
  842.     
  843.     ForeColor(magentaColor);
  844.     PaintRect(&meterRect);
  845.     
  846.     
  847.         // Set port to our sprite's pixel mask GWorld
  848.     SetGWorld(gDiamondMeterSpriteP->curFrameP->maskPort, nil);
  849.     
  850.         // Mask image is inverted when in 8-bit or less
  851.     if (gSpriteWorldP->pixelDepth <= 8)
  852.         ForeColor(whiteColor);
  853.     else
  854.         ForeColor(blackColor);
  855.     
  856.     PaintRect(&meterRect);
  857.     
  858.     
  859.         // Set sprite to be redrawn, since we've changed its image
  860.     gDiamondMeterSpriteP->needsToBeDrawn = true;
  861. }
  862.  
  863.  
  864. ///--------------------------------------------------------------------------------------
  865. //  SmoothScrollingWorldMoveProc - our scrolling WorldMoveProc
  866. ///--------------------------------------------------------------------------------------
  867.  
  868. SW_FUNC void SmoothScrollingWorldMoveProc(
  869.     SpriteWorldPtr spriteWorldP,
  870.     SpritePtr followSpriteP)
  871. {    
  872.     short    screenMidRectTop, screenMidRectLeft;
  873.     
  874.     screenMidRectTop = gScreenMidRect.top + spriteWorldP->visScrollRect.top;
  875.     screenMidRectLeft = gScreenMidRect.left + spriteWorldP->visScrollRect.left;
  876.     
  877.     
  878.     spriteWorldP->horizScrollDelta = (kSpriteMoveDelta * 
  879.         (followSpriteP->destFrameRect.left - screenMidRectLeft) ) / kSpriteMoveDistance;
  880.     
  881.     spriteWorldP->vertScrollDelta = (kSpriteMoveDelta * 
  882.         (followSpriteP->destFrameRect.top - screenMidRectTop) ) / kSpriteMoveDistance;
  883.     
  884.     if (kInterlacedMode)
  885.         spriteWorldP->vertScrollDelta = spriteWorldP->vertScrollDelta>>1<<1;
  886. }
  887.  
  888.