home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / SpriteWorld 2.2 / SpriteWorld Examples / Scrolling Demo / Scrolling Demo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-25  |  19.9 KB  |  735 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. // Scrolling Demo.c
  3. //
  4. // By Vern Jensen. Created in August of 1995
  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.  
  16. #define    kFullScreenWindow            true        // Try me full screen!
  17. #define kWorldRectInset                0            // Make the SpriteWorld smaller?
  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.  
  23. #define    kSpriteMoveDelta            20            // Try 5, 10, 20, or 40
  24. #define kDiamondSpace                8            // How far apart the diamonds are spaced
  25.                                                 // (try 1!)
  26.  
  27. #define kSpriteMoveDistance            80            // How far the sprite can move from
  28.                                                 // the center of the screen, in pixels.
  29.                                                 // Try making this value higher!
  30.  
  31.     // Number of ticks to wait before changing tile image; 0 = change every frame
  32. #define kDiamondFrameRate            8            // How often diamond tiles change frames
  33. #define kWallFrameRate                120            // How often wall changes frames
  34.  
  35. #define kBWPictResIDOffset            100
  36. #define kTileWidth                    40
  37. #define kTileHeight                    40
  38. #define kTileMapRows                100
  39. #define kTileMapCols                150
  40.  
  41. #define kStartRow                    5            // Starting position of sprite
  42. #define kStartCol                    5            // in tile col and row
  43.  
  44.  
  45. #define    kLeftArrowKey                0x7B
  46. #define    kRightArrowKey                0x7C
  47. #define    kDownArrowKey                0x7D
  48. #define    kUpArrowKey                    0x7E
  49.  
  50. #define    kLeftKeyPad                    0x56
  51. #define    kRightKeyPad                0x58
  52. #define    kDownKeyPad                    0x54
  53. #define    kUpKeyPad                    0x5B
  54.  
  55. #define kEscKey                        0x35
  56.  
  57.  
  58. #define kNoKey                        0
  59. #define kLeftKey                    1
  60. #define kUpKey                        2
  61. #define kRightKey                    3
  62. #define kDownKey                    4
  63.  
  64.  
  65. enum tileIDs
  66. {
  67.     kWallTile,
  68.     kLastWallTile,
  69.     kGrassTile,
  70.     kBlackTile,
  71.     kDiamondTile,
  72.     kDiamondTile2,
  73.     kLastDiamondTile,
  74.     
  75.     kTunnelTile1,
  76.     kTunnelTile2,
  77.     kTunnelTile3,
  78.     kTunnelTile4,
  79.     kTunnelTile5,
  80.     kTunnelTile6,
  81.     kWireTile1,
  82.     kWireTile2,
  83.     
  84.     kMaxNumTiles
  85. };
  86.  
  87.  
  88.  
  89. /***********/
  90. /* Globals */
  91. /***********/
  92.  
  93. SpriteWorldPtr        gSpriteWorldP;
  94. SpriteLayerPtr        gSpriteLayerP;
  95. TileMapStructPtr    gTileMapStructP;
  96. TileMapPtr            gTileMap;
  97. SpritePtr            gSimpleSpriteP, gDiamondMeterSpriteP;
  98. DrawProcPtr            gSpriteDrawProc, gScreenDrawProc;
  99. DoubleDrawProcPtr    gDoubleRectDrawProc;
  100. WindowPtr            gWindowP;
  101. Rect                gScreenMidRect;
  102.  
  103. long                gNumDiamondsInMap = 0;    // Number of diamonds in the TileMap
  104. long                gNumDiamonds = 0;        // Number of diamonds sprite has collected
  105.  
  106. struct moveKeys        // Keeps track of which keys are up and which are down
  107. {
  108.     Boolean    up;
  109.     Boolean    right;
  110.     Boolean    down;
  111.     Boolean    left;
  112. } gKeys;
  113.  
  114.  
  115. ///--------------------------------------------------------------------------------------
  116. // Main
  117. ///--------------------------------------------------------------------------------------
  118.  
  119. void    main( void )
  120. {
  121.     Initialize(kNumberOfMoreMastersCalls);
  122.  
  123.     if (SWHasSystem7())
  124.     {
  125.         AllowKeyUpEvents();    // Part of SWGameUtils.c
  126.         SetCursor(*GetCursor(watchCursor));
  127.         
  128.         CreateSpriteWorld();
  129.         SetUpTiling();
  130.         CreateBallSprite();
  131.         CreateDiamondMeterSprite();
  132.         
  133.         SetCursor(&qd.arrow);
  134.         HideCursor();
  135.         
  136.         SetUpAnimation();
  137.         RunAnimation();
  138.         ShutDown();
  139.         
  140.         RestoreEventMask();    // Call this after AllowKeyUpEvents
  141.     }
  142.     else
  143.     {
  144.         CantRunOnThisMachine();
  145.     }
  146. }
  147.  
  148.  
  149. ///--------------------------------------------------------------------------------------
  150. // CreateSpriteWorld
  151. ///--------------------------------------------------------------------------------------
  152.  
  153. void    CreateSpriteWorld( void )
  154. {
  155.     Rect        offscreenRect, worldRect, windRect;
  156.     RgnHandle    mBarUpdateRgn;
  157.     OSErr        err;
  158.     
  159.     gWindowP = GetNewCWindow(kWindowResID, NULL, (WindowPtr)-1L);
  160.     
  161.     if (gWindowP != NULL)
  162.     {
  163.         if (kFullScreenWindow == true)
  164.         {
  165.             SizeWindow(gWindowP, qd.screenBits.bounds.right, 
  166.                     qd.screenBits.bounds.bottom, false);
  167.             MoveWindow(gWindowP, 0, 0, false);
  168.         }
  169.         else
  170.         {
  171.                 // Center window in screen
  172.             windRect = gWindowP->portRect;
  173.             CenterRect(&windRect, &qd.screenBits.bounds);
  174.             
  175.                 // Make sure window is aligned to long-word boundaries (for 8-bit mode)
  176.             windRect.left = windRect.left>>2<<2;
  177.             
  178.             MoveWindow(gWindowP, windRect.left, windRect.top, false);
  179.         }
  180.         
  181.         ShowWindow(gWindowP);
  182.         SetPort(gWindowP);
  183.         mBarUpdateRgn = SWHideMenuBar(gWindowP); // Must be done *after* showing window!
  184.         EraseRgn(mBarUpdateRgn);
  185.         
  186.         if (kInterlacedMode)
  187.             PaintRect(&gWindowP->portRect);    // Blacken window for Interlaced mode
  188.     }
  189.     else
  190.         CantFindResource();
  191.     
  192.     
  193.     err = SWEnterSpriteWorld();
  194.     FatalError(err);
  195.     
  196.     
  197.     worldRect = gWindowP->portRect;
  198.     InsetRect(&worldRect, kWorldRectInset, kWorldRectInset);
  199.     
  200.     
  201.         // Set size of offscreen area
  202.     offscreenRect = worldRect;
  203.     OffsetRect(&offscreenRect, -offscreenRect.left, -offscreenRect.top);
  204.     
  205.  
  206.         // Make offscreen area evenly divisible by tile width & height
  207.     if ( (offscreenRect.right/kTileWidth)*kTileWidth != offscreenRect.right)
  208.         offscreenRect.right = (offscreenRect.right/kTileWidth)*kTileWidth + kTileWidth;
  209.     
  210.     if ( (offscreenRect.bottom/kTileHeight)*kTileHeight != offscreenRect.bottom)
  211.         offscreenRect.bottom = (offscreenRect.bottom/kTileHeight)*kTileHeight + kTileHeight;
  212.     
  213.         // Create the scrolling sprite world
  214.     err = SWCreateSpriteWorldFromWindow(&gSpriteWorldP, (CWindowPtr)gWindowP, 
  215.             &worldRect, &offscreenRect, 0);
  216.     FatalError(err);
  217.     
  218.             // Create the sprite layer
  219.     err = SWCreateSpriteLayer(&gSpriteLayerP);
  220.     FatalError(err);
  221.     
  222.         // Add it to the world
  223.     SWAddSpriteLayer(gSpriteWorldP, gSpriteLayerP);
  224.     
  225.     
  226.         // Determine what DrawProcs to use
  227.     if (gSpriteWorldP->pixelDepth == 8)        // 256 colors
  228.     {
  229.         if (kInterlacedMode)
  230.         {
  231.             gSpriteDrawProc = BP8BitInterlacedMaskDrawProc;
  232.             gScreenDrawProc = BP8BitInterlacedRectDrawProc;
  233.             gDoubleRectDrawProc = BP8BitInterlacedDoubleRectDrawProc;
  234.             SWSetPartialMaskDrawProc(gSpriteWorldP, BP8BitInterlacedPartialMaskDrawProc);
  235.         }
  236.         else
  237.         {
  238.             gSpriteDrawProc = BlitPixie8BitMaskDrawProc;
  239.             gScreenDrawProc = SWStdWorldDrawProc;
  240.             gDoubleRectDrawProc = BlitPixie8BitDoubleRectDrawProc;
  241.             SWSetPartialMaskDrawProc(gSpriteWorldP, BlitPixie8BitPartialMaskDrawProc);
  242.         }
  243.     }
  244.     else if ( !(SW_PPC && gSpriteWorldP->pixelDepth < 8) )    // Not 256 colors
  245.     {
  246.             // Use interlaced drawProcs unless in B&W, where interlacing is ugly
  247.         if (kInterlacedMode && gSpriteWorldP->pixelDepth > 2)
  248.         {
  249.             gSpriteDrawProc = BPAllBitInterlacedMaskDrawProc;
  250.             gScreenDrawProc = BPAllBitInterlacedRectDrawProc;
  251.             SWSetPartialMaskDrawProc(gSpriteWorldP, BPAllBitInterlacedPartialMaskDrawProc);
  252.             if (gSpriteWorldP->pixelDepth == 16)
  253.                 gDoubleRectDrawProc = BP16BitInterlacedDoubleRectDrawProc;
  254.         }
  255.         else
  256.         {
  257.             gSpriteDrawProc = BlitPixieAllBitMaskDrawProc;
  258.             gScreenDrawProc = BlitPixieAllBitRectDrawProc;
  259.             SWSetPartialMaskDrawProc(gSpriteWorldP, BlitPixieAllBitPartialMaskDrawProc);
  260.             if (gSpriteWorldP->pixelDepth == 16)
  261.                 gDoubleRectDrawProc = BlitPixie16BitDoubleRectDrawProc;
  262.         }
  263.     }
  264.     else
  265.     {
  266.         gSpriteDrawProc = SWStdSpriteDrawProc;
  267.         gScreenDrawProc = SWStdWorldDrawProc;
  268.         gDoubleRectDrawProc = NULL;
  269.     }
  270. }
  271.     
  272.     
  273. ///--------------------------------------------------------------------------------------
  274. // SetUpTiling
  275. ///--------------------------------------------------------------------------------------
  276.  
  277. void    SetUpTiling( void )    
  278. {
  279.     short        resIDOffset;
  280.     short        row, col;
  281.     OSErr        err;
  282.  
  283.     err = SWInitTiling(gSpriteWorldP, kTileHeight, kTileWidth, kMaxNumTiles);
  284.     FatalError(err);
  285.     
  286.     err = SWCreateTileMap(&gTileMapStructP, kTileMapRows, kTileMapCols);
  287.     FatalError(err);
  288.     
  289.     SWInstallTileMap(gSpriteWorldP, gTileMapStructP, 0);
  290.     gTileMap = gTileMapStructP->tileMap;
  291.     
  292.     SWSetSpriteLayerUnderTileLayer(gSpriteLayerP, 0);
  293.     
  294.  
  295.         // Determine whether to load B&W or color graphics
  296.     if (gSpriteWorldP->pixelDepth <= 2)
  297.         resIDOffset = kBWPictResIDOffset;
  298.     else
  299.         resIDOffset = 0;
  300.  
  301.         // Load first set of tiles
  302.     err = SWLoadTilesFromPictResource(
  303.         gSpriteWorldP, 
  304.         kWallTile,                // startTileID 
  305.         kLastDiamondTile,        // endTileID
  306.         200 + resIDOffset,        // pictResID
  307.         0,                        // maskResID
  308.         kNoMask,                // maskType
  309.         1,                        // horizBorderWidth
  310.         1);                        // vertBorderHeight
  311.     FatalError(err);
  312.     
  313.         // Load masked set of tiles
  314.     err = SWLoadTilesFromPictResource(
  315.         gSpriteWorldP, 
  316.         kTunnelTile1,            // startTileID 
  317.         kWireTile2,                // endTileID
  318.         201 + resIDOffset,        // pictResID
  319.         401,                    // maskResID
  320.         kFatMask,                // maskType
  321.         1,                        // horizBorderWidth
  322.         1);                        // vertBorderHeight
  323.     FatalError(err);
  324.  
  325.     
  326.         // Set up tileMap
  327.     for (row = 0; row < kTileMapRows; row++)
  328.     {
  329.         for (col = 0; col < kTileMapCols; col++)
  330.         {
  331.             if (row == 0 || col == 0 || row == kTileMapRows-1 || col == kTileMapCols-1)
  332.                 gTileMap[row][col] = kWallTile;
  333.             else if (row > kTileMapRows / 2)
  334.                 gTileMap[row][col] = kWireTile1;
  335.             else if ((row/kDiamondSpace)*kDiamondSpace == row && 
  336.                      (col/kDiamondSpace)*kDiamondSpace == col)
  337.             {
  338.                 gTileMap[row][col] = kDiamondTile;
  339.                 gNumDiamondsInMap++;
  340.             }
  341.             else
  342.                 gTileMap[row][col] = kGrassTile;
  343.         }
  344.     }
  345.     
  346.  
  347.         // Add tunnel to tileMap
  348.     row = kTileMapRows / 2;
  349.  
  350.     for (col = 1; col < kTileMapCols-1; col += 2)
  351.     {
  352.         gTileMap[row][col] = kTunnelTile1;
  353.         gTileMap[row][col+1] = kTunnelTile2;
  354.         gTileMap[row+1][col] = kTunnelTile4;
  355.         gTileMap[row+1][col+1] = kTunnelTile5;
  356.     }
  357. }
  358.  
  359.  
  360. ///--------------------------------------------------------------------------------------
  361. // CreateBallSprite
  362. ///--------------------------------------------------------------------------------------
  363.  
  364. void    CreateBallSprite( void )
  365. {
  366.     OSErr    err;
  367.     
  368.         // Create the ball sprite
  369.     err = SWCreateSpriteFromCicnResource(gSpriteWorldP, &gSimpleSpriteP, NULL, 
  370.             128, 1, kFatMask);    
  371.     FatalError(err);
  372.     
  373.         // Set up the ball sprite
  374.     SWAddSprite(gSpriteLayerP, gSimpleSpriteP);
  375.     SWSetSpriteMoveProc(gSimpleSpriteP, KeySpriteMoveProc);
  376.     SWSetSpriteLocation(gSimpleSpriteP, kStartCol * kTileWidth, kStartRow * kTileHeight);
  377.     SWSetSpriteMoveDelta(gSimpleSpriteP, 0, 0);
  378.     SWSetSpriteDrawProc(gSimpleSpriteP, gSpriteDrawProc);
  379. }
  380.  
  381.  
  382. ///--------------------------------------------------------------------------------------
  383. // CreateDiamondMeterSprite
  384. ///--------------------------------------------------------------------------------------
  385.  
  386. void    CreateDiamondMeterSprite( void )
  387. {
  388.     short        spriteResID;
  389.     OSErr        err;
  390.     
  391.         // Calculate resource ID for diamond meter sprite
  392.     if (gSpriteWorldP->pixelDepth <= 2)
  393.         spriteResID = 302;
  394.     else
  395.         spriteResID = 202;
  396.     
  397.         // Create the diamond meter sprite
  398.     err = SWCreateSpriteFromPictResource(gSpriteWorldP,
  399.                 &gDiamondMeterSpriteP, 
  400.                 NULL,            // pointer to memory for sprite
  401.                 spriteResID,     // picture resource id
  402.                 402,            // mask resource id
  403.                 1,                 // max frames
  404.                 kPixelMask);        // mask type
  405.     FatalError(err);
  406.     
  407.     SWAddSprite(gSpriteLayerP, gDiamondMeterSpriteP);
  408.     SWSetSpriteDrawProc(gDiamondMeterSpriteP, gSpriteDrawProc);
  409. }
  410.  
  411.  
  412. ///--------------------------------------------------------------------------------------
  413. // SetUpAnimation
  414. ///--------------------------------------------------------------------------------------
  415.  
  416. void    SetUpAnimation( void )
  417. {
  418.     Rect        moveBoundsRect;
  419.     
  420.     SWLockSpriteWorld(gSpriteWorldP);
  421.     
  422.         // Set up data used by the SmoothScrollingWorldMoveProc
  423.     gScreenMidRect = gSimpleSpriteP->curFrameP->frameRect;
  424.     CenterRect( &gScreenMidRect, &gSpriteWorldP->backRect );
  425.     
  426.     SWSetSpriteWorldMaxFPS(gSpriteWorldP, kMaxFPS);
  427.     SWSyncSpriteWorldToVBL(gSpriteWorldP, kSyncToVBL);
  428.     SWSetCleanUpSpriteWorld(gSpriteWorldP);
  429.     
  430.         // movement boundary = size of tileMap
  431.     SetRect(&moveBoundsRect, 0,0, kTileMapCols * kTileWidth, kTileMapRows * kTileHeight);
  432.     
  433.     SWSetScrollingWorldMoveBounds(gSpriteWorldP, &moveBoundsRect);
  434.     SWSetScrollingWorldMoveProc(gSpriteWorldP, SmoothScrollingWorldMoveProc, gSimpleSpriteP);
  435.     
  436.     SWSetTileChangeProc(gSpriteWorldP, TileChangeProc);
  437.     
  438.         // Move visScrollRect to starting sprite position
  439.     SWMoveVisScrollRect(gSpriteWorldP, 
  440.         gSpriteWorldP->followSpriteP->destFrameRect.left - gSpriteWorldP->backRect.right/2,
  441.         gSpriteWorldP->followSpriteP->destFrameRect.top - gSpriteWorldP->backRect.bottom/2);
  442.     
  443.         // Set starting position of diamond meter sprite
  444.     DiamondMeterSpriteMoveProc(gDiamondMeterSpriteP);
  445.  
  446.     SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, gScreenDrawProc);
  447.     SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, gScreenDrawProc);
  448.     SWSetDoubleRectDrawProc(gSpriteWorldP, gDoubleRectDrawProc);    
  449.     
  450.         // Make sure CopyBits, if used, doesn't try to colorize things
  451.     SWSetPortToWindow(gSpriteWorldP);
  452.     ForeColor(blackColor);
  453.     BackColor(whiteColor);
  454.     
  455.     SWDrawTilesInBackground(gSpriteWorldP);
  456.     SWUpdateScrollingSpriteWorld(gSpriteWorldP, true);
  457. }
  458.  
  459.  
  460. ///--------------------------------------------------------------------------------------
  461. //  RunAnimation
  462. ///--------------------------------------------------------------------------------------
  463.  
  464. void    RunAnimation( void )
  465. {
  466.     unsigned long        frames;
  467.         
  468.     frames = 0;
  469.     StartTimer();
  470.  
  471.     FatalError( SWStickyError() ); // Make sure no errors got past us during setup
  472.  
  473.     while (!Button())
  474.     {
  475.         SWProcessScrollingSpriteWorld(gSpriteWorldP);
  476.         
  477.             // We call this in case the Control Strip or something changes our window's visRgn
  478.         KeepMenuBarHidden(gWindowP);
  479.  
  480.             // Move diamond meter sprite to new visScrollRect location
  481.         DiamondMeterSpriteMoveProc(gDiamondMeterSpriteP);
  482.         
  483.             // Make sure no errors occurred during a MoveProc, etc.
  484.         FatalError( SWStickyError() );
  485.     
  486.         SWAnimateScrollingSpriteWorld(gSpriteWorldP);
  487.         
  488.         if (gSpriteWorldP->frameHasOccurred)
  489.             frames++;
  490.     }
  491.     
  492.     
  493.     ShowResults(frames);
  494.     SWShowMenuBar(gWindowP);
  495. }
  496.  
  497.  
  498. ///--------------------------------------------------------------------------------------
  499. //  ShutDown (clean up and dispose of the SpriteWorld)
  500. ///--------------------------------------------------------------------------------------
  501.  
  502. void    ShutDown( void )
  503. {
  504.     SWDisposeSpriteWorld(&gSpriteWorldP);
  505.     SWExitSpriteWorld();
  506.     
  507.     FlushEvents(everyEvent, 0);
  508.     ShowCursor();
  509. }
  510.  
  511.  
  512. ///--------------------------------------------------------------------------------------
  513. //  TileChangeProc
  514. ///--------------------------------------------------------------------------------------
  515.  
  516. SW_FUNC void TileChangeProc(
  517.     SpriteWorldPtr spriteWorldP)
  518. {
  519.     short            curImage;
  520.     static short    wallDelay = 0, diamondDelay = 0;
  521.     static short    oldTicks = 0;
  522.     short            ticksPassed, ticks;
  523.     
  524.         // Initialize oldTicks the first time this function is called
  525.     if (oldTicks == 0)
  526.         oldTicks = TickCount();
  527.     
  528.     ticks = TickCount();
  529.     ticksPassed = ticks - oldTicks;        // Number of ticks passed since last call
  530.     oldTicks = ticks;
  531.     
  532.         // kWallTile
  533.     wallDelay += ticksPassed;
  534.     if (wallDelay >= kWallFrameRate)
  535.     {
  536.         curImage = spriteWorldP->curTileImage[kWallTile];
  537.         if (curImage < kLastWallTile)
  538.             curImage++;
  539.         else
  540.             curImage = kWallTile;
  541.         
  542.         SWChangeTileImage(spriteWorldP, kWallTile, curImage);
  543.         wallDelay = 0;
  544.     }
  545.     
  546.     
  547.         // kDiamondTile
  548.     diamondDelay += ticksPassed;
  549.     if (diamondDelay >= kDiamondFrameRate)
  550.     {
  551.         curImage = spriteWorldP->curTileImage[kDiamondTile];
  552.         if (curImage < kLastDiamondTile)
  553.             curImage++;
  554.         else
  555.             curImage = kDiamondTile;
  556.         
  557.         SWChangeTileImage(spriteWorldP, kDiamondTile, curImage);
  558.         diamondDelay = 0;
  559.     }
  560. }
  561.  
  562.  
  563. ///--------------------------------------------------------------------------------------
  564. //  KeySpriteMoveProc
  565. ///--------------------------------------------------------------------------------------
  566.  
  567. SW_FUNC void KeySpriteMoveProc(SpritePtr srcSpriteP)
  568. {
  569.     short    row, col;
  570.     short    rowDelta, colDelta;
  571.     short    tile;
  572.     
  573.     UpdateKeys();    // Put the latest key values in the keys structure
  574.     
  575.     
  576.     row = srcSpriteP->destFrameRect.top / kTileHeight;
  577.     col = srcSpriteP->destFrameRect.left / kTileWidth;
  578.  
  579.     if (row * kTileHeight == srcSpriteP->destFrameRect.top &&
  580.         col * kTileWidth == srcSpriteP->destFrameRect.left)
  581.     {
  582.         tile = gTileMap[row][col];
  583.         
  584.             // Leave black trail behind sprite
  585.         if (tile == kGrassTile || tile == kDiamondTile)
  586.             SWDrawTile(gSpriteWorldP, 0, row, col, kBlackTile);
  587.         else if (tile == kTunnelTile2 || tile == kTunnelTile5 || tile == kWireTile1)
  588.             SWDrawTile(gSpriteWorldP, 0, row, col, tile+1);
  589.             
  590.         if (tile == kDiamondTile)
  591.         {
  592.             gNumDiamonds++;            // Increase number of diamonds sprite has collected
  593.             UpdateDiamondMeter();    // Update meter
  594.         }
  595.         
  596.  
  597.         rowDelta = 0;
  598.         colDelta = 0;
  599.         
  600.         if (gKeys.left)
  601.             colDelta = -1;
  602.         else if (gKeys.right)
  603.             colDelta = 1;
  604.         else if (gKeys.up)
  605.             rowDelta = -1;
  606.         else if (gKeys.down)
  607.             rowDelta = 1;
  608.         
  609.                 
  610.         
  611.         tile = gTileMap[row + rowDelta][col + colDelta];
  612.         
  613.         if (tile != kWallTile && tile != kTunnelTile1 && tile != kTunnelTile4)
  614.         {
  615.             srcSpriteP->vertMoveDelta = rowDelta * kSpriteMoveDelta;
  616.             srcSpriteP->horizMoveDelta = colDelta * kSpriteMoveDelta;
  617.         }
  618.         else
  619.         {
  620.             srcSpriteP->vertMoveDelta = 0;
  621.             srcSpriteP->horizMoveDelta = 0;
  622.         }
  623.     }
  624.     
  625.     SWOffsetSprite(srcSpriteP, srcSpriteP->horizMoveDelta, srcSpriteP->vertMoveDelta);
  626. }
  627.  
  628.  
  629. ///--------------------------------------------------------------------------------------
  630. //  DiamondMeterSpriteMoveProc - not installed as a MoveProc, but called directly
  631. ///--------------------------------------------------------------------------------------
  632.  
  633. SW_FUNC void DiamondMeterSpriteMoveProc(SpritePtr srcSpriteP)
  634. {
  635.         // Move sprite to top-left corner of current visScrollRect location
  636.     SWMoveSprite(srcSpriteP, 
  637.         gSpriteWorldP->visScrollRect.left + 10, 
  638.         gSpriteWorldP->visScrollRect.top + 10);
  639. }
  640.  
  641.  
  642. ///--------------------------------------------------------------------------------------
  643. //  UpdateDiamondMeter - change the meter Sprite's image and mask
  644. ///--------------------------------------------------------------------------------------
  645.  
  646. SW_FUNC void UpdateDiamondMeter( void )
  647. {
  648.     double    percent;
  649.     Rect    meterRect;
  650.     
  651.     percent = (double)gNumDiamonds / gNumDiamondsInMap;
  652.     
  653.         // 108 = length of meter; 17 = offset from start of meter
  654.     SetRect(&meterRect, 17, 2, (108 * percent) + 17, 14);
  655.     
  656.     
  657.         // Set port to our sprite's framePort GWorld
  658.     SetGWorld(gDiamondMeterSpriteP->curFrameP->framePort, nil);
  659.     
  660.     ForeColor(magentaColor);
  661.     PaintRect(&meterRect);
  662.     
  663.         // IMPORTANT: Set the color back when done! (In case CopyBits is used later)
  664.     ForeColor(blackColor);
  665.     
  666.     
  667.         // Set port to our sprite's pixel mask GWorld
  668.     SetGWorld(gDiamondMeterSpriteP->curFrameP->maskPort, nil);
  669.     
  670.         // Mask image is inverted when in 8-bit or less
  671.     if (gSpriteWorldP->pixelDepth <= 8)
  672.         ForeColor(whiteColor);
  673.     else
  674.         ForeColor(blackColor);
  675.     
  676.     PaintRect(&meterRect);
  677.     ForeColor(blackColor);
  678.     
  679.     
  680.         // Set sprite to be redrawn, since we've changed its image
  681.     gDiamondMeterSpriteP->needsToBeDrawn = true;
  682. }
  683.  
  684.  
  685. ///--------------------------------------------------------------------------------------
  686. //  SmoothScrollingWorldMoveProc - our scrolling WorldMoveProc
  687. ///--------------------------------------------------------------------------------------
  688.  
  689. SW_FUNC void SmoothScrollingWorldMoveProc(
  690.     SpriteWorldPtr spriteWorldP,
  691.     SpritePtr followSpriteP)
  692. {    
  693.     short    screenMidRectTop, screenMidRectLeft;
  694.     
  695.     screenMidRectTop = gScreenMidRect.top + spriteWorldP->visScrollRect.top;
  696.     screenMidRectLeft = gScreenMidRect.left + spriteWorldP->visScrollRect.left;
  697.     
  698.     
  699.     spriteWorldP->horizScrollDelta = (kSpriteMoveDelta * 
  700.         (followSpriteP->destFrameRect.left - screenMidRectLeft) ) / kSpriteMoveDistance;
  701.     
  702.     spriteWorldP->vertScrollDelta = (kSpriteMoveDelta * 
  703.         (followSpriteP->destFrameRect.top - screenMidRectTop) ) / kSpriteMoveDistance;
  704.     
  705.     if (kInterlacedMode)
  706.         spriteWorldP->vertScrollDelta = spriteWorldP->vertScrollDelta>>1<<1;
  707. }
  708.  
  709.  
  710. ///--------------------------------------------------------------------------------------
  711. //  UpdateKeys (Put the latest key values in the keys structure)
  712. ///--------------------------------------------------------------------------------------
  713.  
  714. void    UpdateKeys( void )
  715. {
  716.     EventRecord        event;
  717.     short            theKey;
  718.     Boolean            isDown;
  719.     
  720.     while ( GetOSEvent( (keyUpMask | keyDownMask), &event ) )
  721.     {
  722.         theKey = (event.message & keyCodeMask) >> 8;
  723.         isDown = (event.what != keyUp);
  724.         
  725.         if ( (theKey == kLeftArrowKey) || (theKey == kLeftKeyPad) )
  726.             gKeys.left = isDown;
  727.         else if ( (theKey == kRightArrowKey) || (theKey == kRightKeyPad) )
  728.             gKeys.right = isDown;
  729.         else if ( (theKey == kDownArrowKey) || (theKey == kDownKeyPad) )
  730.             gKeys.down = isDown;
  731.         else if ( (theKey == kUpArrowKey) || (theKey == kUpKeyPad) )
  732.             gKeys.up = isDown;
  733.     }
  734. }
  735.