home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-03-06 | 16.1 KB | 555 lines | [TEXT/BROW] |
- //
- // File: demo.c
- //
- // This file contains the routines that control the demo.
- //
- // 2/19/95 -- Created by Mick
- //
-
- // include files
-
- #include "global.h"
-
- #include <Palettes.h>
- #include <QDOffscreen.h>
-
- #include "demo.h"
-
- #include "main.h"
- #include "sprite.h"
- #include "update.h"
-
- // defines for this file
-
- #define kMaxObjects 10 // the maximum number of objects in the demo
- #define kClipRectInset 100 // the amount to inset the clip rect
-
- // typedefs for this file
-
- typedef struct
- {
- tSpriteInfo *fSpriteInfo; // the information on the sprite for this object
- unsigned char fIsVisible; // should we draw this object
- unsigned char fWasVisible; // was this object visible last time?
- signed long fXPos; // the x position of this object ( 16:16 fixed )
- signed long fYPos; // the y position of this object ( 16:16 fixed )
- signed long fDeltaX; // the x coord of the velocity of this object ( 16:16 fixed )
- signed long fDeltaY; // the y coord of the velocity of this object ( 16:16 fixed )
- signed short fIntXPos; // the x position as an integer
- signed short fIntYPos; // the y position as an integer
- } tObjectInfo;
-
- // global function declarations
-
- void startupDemo( void );
- void shutdownDemo( void );
- void demoKey( unsigned char inKey );
- void doDemoFrame( void );
-
- // global data owned by this file
-
- GWorldPtr gOffscreenBuffer; // the port and gdevice of the offscreen buffer
- PixMapHandle gOffscreenPixels; // the actual pixmap of the offscreen buffer
- Rect gOffscreenRect; // the size of the offscreen buffer
-
- // local function declarations
-
- static void moveObjects( void ); // move all the objects
- static void blitToScreen( Rect *inCopyRect ); // copy data from offscreen to onscreen
- static void restoreBackground( void ); // redraw the background
-
- // static data
-
- static tObjectInfo sObjects[ kMaxObjects ]; // the data for all the objects
- static unsigned char sShowUpdateAreaFlag; // should we show the update area?
- static unsigned char sStepMode; // are we running step by step
-
- // functions
-
- //
- // startupDemo -
- //
- // Create and load all the buffers and data needed for the demo.
- //
-
- void startupDemo( void )
- {
- unsigned short indexCounter; // a counter to scan the object array
-
- // create the offscreen gworld
- NewGWorld( &gOffscreenBuffer, 8, &( gMainWindow->portRect ), gAppColorTable, ( GDHandle )kNil, keepLocal );
-
- // get the pixel map and rect
- gOffscreenPixels = GetGWorldPixMap( gOffscreenBuffer );
- gOffscreenRect = gMainWindow->portRect;
-
- // load the sprite
- for( indexCounter = 0; indexCounter < kMaxObjects; indexCounter++ )
- {
- // load the sprites
- sObjects[ indexCounter ].fSpriteInfo = loadSprite( kNumberOne + indexCounter );
-
- // give it a random location and velocity
- sObjects[ indexCounter ].fIntXPos = Random() & 0x00FF;
- sObjects[ indexCounter ].fIntYPos = Random() & 0x00FF;
- sObjects[ indexCounter ].fXPos = ( sObjects[ indexCounter ].fIntXPos ) << 16;
- sObjects[ indexCounter ].fYPos = ( sObjects[ indexCounter ].fIntYPos ) << 16;
- sObjects[ indexCounter ].fDeltaX = Random() << 4;
- sObjects[ indexCounter ].fDeltaY = Random() << 4;
-
- // initially, it is visible (but it was not last frame)
- sObjects[ indexCounter ].fIsVisible = kTrue;
- sObjects[ indexCounter ].fWasVisible = kFalse;
- }
-
- // set the initial flags
- sStepMode = kFalse;
- sShowUpdateAreaFlag = kFalse;
- }
-
-
- //
- // shutdownDemo -
- //
- // Release all the memory used by the demo.
- //
-
- void shutdownDemo( void )
- {
- unsigned short indexCounter; // a counter to scan the object array
-
- // dump the sprites
- for( indexCounter = 0; indexCounter < kMaxObjects; indexCounter++ )
- {
- disposeSprite( sObjects[ indexCounter ].fSpriteInfo );
- }
-
- // dump the offscreen gworld
- DisposeGWorld( gOffscreenBuffer );
- }
-
-
- //
- // demoKey -
- //
- // Handle a key stroke -- allows the user to set options while the demo runs.
- //
-
- void demoKey( unsigned char inKey )
- {
- // depending on the key pressed
- switch( inKey )
- {
- case 'u': // turn show update on/off
- sShowUpdateAreaFlag = !sShowUpdateAreaFlag;
- break;
- case 's': // turn step mode on and off
- sStepMode = !sStepMode;
- break;
- case ' ': // step one frame (if we are in step mode)
- if ( sStepMode )
- {
- // allow one frame, by temporarily turning off step mode
- sStepMode = kFalse;
- doDemoFrame();
- sStepMode = kTrue;
- }
- break;
- case '+': // add more rects to the update
- increaseUpdateRects();
- break;
- case '-': // reduce the number of rects to update with
- decreaseUpdateRects();
- break;
-
- case '1': // turn this number on and off
- sObjects[ 0 ].fIsVisible = !sObjects[ 0 ].fIsVisible;
- break;
- case '2': // turn this number on and off
- sObjects[ 1 ].fIsVisible = !sObjects[ 1 ].fIsVisible;
- break;
- case '3': // turn this number on and off
- sObjects[ 2 ].fIsVisible = !sObjects[ 2 ].fIsVisible;
- break;
- case '4': // turn this number on and off
- sObjects[ 3 ].fIsVisible = !sObjects[ 3 ].fIsVisible;
- break;
- case '5': // turn this number on and off
- sObjects[ 4 ].fIsVisible = !sObjects[ 4 ].fIsVisible;
- break;
- case '6': // turn this number on and off
- sObjects[ 5 ].fIsVisible = !sObjects[ 5 ].fIsVisible;
- break;
- case '7': // turn this number on and off
- sObjects[ 6 ].fIsVisible = !sObjects[ 6 ].fIsVisible;
- break;
- case '8': // turn this number on and off
- sObjects[ 7 ].fIsVisible = !sObjects[ 7 ].fIsVisible;
- break;
- case '9': // turn this number on and off
- sObjects[ 8 ].fIsVisible = !sObjects[ 8 ].fIsVisible;
- break;
- case '0': // turn this number on and off
- sObjects[ 9 ].fIsVisible = !sObjects[ 9 ].fIsVisible;
- break;
-
- case '!': // freeze/unfreeze this number
- if ( sObjects[ 0 ].fDeltaX == 0 && sObjects[ 0 ].fDeltaY == 0 )
- {
- sObjects[ 0 ].fDeltaX = Random() << 4;
- sObjects[ 0 ].fDeltaY = Random() << 4;
- }
- else
- {
- sObjects[ 0 ].fDeltaX = 0;
- sObjects[ 0 ].fDeltaY = 0;
- }
- break;
- case '@': // freeze/unfreeze this number
- if ( sObjects[ 1 ].fDeltaX == 0 && sObjects[ 1 ].fDeltaY == 0 )
- {
- sObjects[ 1 ].fDeltaX = Random() << 4;
- sObjects[ 1 ].fDeltaY = Random() << 4;
- }
- else
- {
- sObjects[ 1 ].fDeltaX = 0;
- sObjects[ 1 ].fDeltaY = 0;
- }
- break;
- case '#': // freeze/unfreeze this number
- if ( sObjects[ 2 ].fDeltaX == 0 && sObjects[ 2 ].fDeltaY == 0 )
- {
- sObjects[ 2 ].fDeltaX = Random() << 4;
- sObjects[ 2 ].fDeltaY = Random() << 4;
- }
- else
- {
- sObjects[ 2 ].fDeltaX = 0;
- sObjects[ 2 ].fDeltaY = 0;
- }
- break;
- case '$': // freeze/unfreeze this number
- if ( sObjects[ 3 ].fDeltaX == 0 && sObjects[ 3 ].fDeltaY == 0 )
- {
- sObjects[ 3 ].fDeltaX = Random() << 4;
- sObjects[ 3 ].fDeltaY = Random() << 4;
- }
- else
- {
- sObjects[ 3 ].fDeltaX = 0;
- sObjects[ 3 ].fDeltaY = 0;
- }
- break;
- case '%': // freeze/unfreeze this number
- if ( sObjects[ 4 ].fDeltaX == 0 && sObjects[ 4 ].fDeltaY == 0 )
- {
- sObjects[ 4 ].fDeltaX = Random() << 4;
- sObjects[ 4 ].fDeltaY = Random() << 4;
- }
- else
- {
- sObjects[ 4 ].fDeltaX = 0;
- sObjects[ 4 ].fDeltaY = 0;
- }
- break;
- case '^': // freeze/unfreeze this number
- if ( sObjects[ 5 ].fDeltaX == 0 && sObjects[ 5 ].fDeltaY == 0 )
- {
- sObjects[ 5 ].fDeltaX = Random() << 4;
- sObjects[ 5 ].fDeltaY = Random() << 4;
- }
- else
- {
- sObjects[ 5 ].fDeltaX = 0;
- sObjects[ 5 ].fDeltaY = 0;
- }
- break;
- case '&': // freeze/unfreeze this number
- if ( sObjects[ 6 ].fDeltaX == 0 && sObjects[ 6 ].fDeltaY == 0 )
- {
- sObjects[ 6 ].fDeltaX = Random() << 4;
- sObjects[ 6 ].fDeltaY = Random() << 4;
- }
- else
- {
- sObjects[ 6 ].fDeltaX = 0;
- sObjects[ 6 ].fDeltaY = 0;
- }
- break;
- case '*': // freeze/unfreeze this number
- if ( sObjects[ 7 ].fDeltaX == 0 && sObjects[ 7 ].fDeltaY == 0 )
- {
- sObjects[ 7 ].fDeltaX = Random() << 4;
- sObjects[ 7 ].fDeltaY = Random() << 4;
- }
- else
- {
- sObjects[ 7 ].fDeltaX = 0;
- sObjects[ 7 ].fDeltaY = 0;
- }
- break;
- case '(': // freeze/unfreeze this number
- if ( sObjects[ 8 ].fDeltaX == 0 && sObjects[ 8 ].fDeltaY == 0 )
- {
- sObjects[ 8 ].fDeltaX = Random() << 4;
- sObjects[ 8 ].fDeltaY = Random() << 4;
- }
- else
- {
- sObjects[ 8 ].fDeltaX = 0;
- sObjects[ 8 ].fDeltaY = 0;
- }
- break;
- case ')': // freeze/unfreeze this number
- if ( sObjects[ 9 ].fDeltaX == 0 && sObjects[ 9 ].fDeltaY == 0 )
- {
- sObjects[ 9 ].fDeltaX = Random() << 4;
- sObjects[ 9 ].fDeltaY = Random() << 4;
- }
- else
- {
- sObjects[ 9 ].fDeltaX = 0;
- sObjects[ 9 ].fDeltaY = 0;
- }
- break;
-
- default: // unknown key
- SysBeep( 0 );
- break;
- }
- }
-
-
- //
- // doDemoFrame -
- //
- // Move the demo ahead one frame -- move the sprites and draw.
- //
-
- void doDemoFrame( void )
- {
- CGrafPtr oldPort; // the graf port that is in place when we are called
- GDHandle oldDevice; // the gdevice that is in place when we are called
- signed long indexCounter; // a counter to scan all the objects
- signed long rectCounter; // a counter to scan all the rects
- Rect updateRect; // the rect that needs to be updated
- Point drawPoint; // where to draw the sprite
-
- // if we are in step mode, return
- if ( sStepMode )
- {
- return;
- }
-
- // save the current port and gdevice
- GetGWorld( &oldPort, &oldDevice );
-
- // set the offscreen buffer as current ( and lock the pixel map )
- SetGWorld( gOffscreenBuffer, ( GDHandle )kNil );
- LockPixels( gOffscreenPixels );
-
- // restore the background
- restoreBackground();
-
- // move the objects
- moveObjects();
-
- // draw the sprites in each of the update rects
- for( rectCounter = 0; rectCounter < getUpdateRectCount(); rectCounter++ )
- {
- // get one of the update rects
- getUpdateRect( rectCounter, &updateRect );
-
- // if the user wants it, draw the update rect
- if ( sShowUpdateAreaFlag )
- {
- FrameRect( &updateRect );
- }
-
- // setup to draw the sprites
- startSpriteDraw( &updateRect, gOffscreenPixels );
-
- // draw the sprites from back to front
- for( indexCounter = kMaxObjects - 1; indexCounter >= 0; indexCounter-- )
- {
- if ( sObjects[ indexCounter ].fIsVisible )
- {
- drawPoint.h = ( sObjects[ indexCounter ].fIntXPos ) ;
- drawPoint.v = ( sObjects[ indexCounter ].fIntYPos );
- drawSprite( sObjects[ indexCounter ].fSpriteInfo, drawPoint );
- }
- }
-
- // shutdown the shape draw
- endSpriteDraw();
- }
-
- if ( sShowUpdateAreaFlag )
- {
- // copy the buffer to the screen
- blitToScreen( &gOffscreenRect );
- }
- else
- {
- // copy each of the update rects to the screen
- for( rectCounter = 0; rectCounter < getUpdateRectCount(); rectCounter++ )
- {
- // get one of the update rects
- getUpdateRect( rectCounter, &updateRect );
-
- // copy the buffer to the screen
- blitToScreen( &updateRect );
- }
- }
-
- // restore the current port and gdevice
- UnlockPixels( gOffscreenPixels );
- SetGWorld( oldPort, oldDevice );
- }
-
-
- //
- // moveObjects -
- //
- // Move all the objects.
- //
-
- void moveObjects( void )
- {
- unsigned short indexCounter; // a counter to scan all the objects
- Rect objectRect; // the rectangle that bounds the object
-
- // clear the update area
- clearUpdate();
-
- // concider each object
- for( indexCounter = 0; indexCounter < kMaxObjects; indexCounter++ )
- {
- // if this object has no velocity and we are not displaying the update rects, we can ignore it
- if ( sObjects[ indexCounter ].fDeltaX == 0 && sObjects[ indexCounter ].fDeltaY == 0 )
- {
- continue;
- }
-
- // if the object was visible last time
- if ( sObjects[ indexCounter ].fWasVisible )
- {
- // determine the object's rect
- objectRect = ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect;
- objectRect.left += sObjects[ indexCounter ].fIntXPos;
- objectRect.top += sObjects[ indexCounter ].fIntYPos;
- objectRect.right += sObjects[ indexCounter ].fIntXPos;
- objectRect.bottom += sObjects[ indexCounter ].fIntYPos;
-
- // add the old rect to the update (so it will be erased)
- addRectToUpdate( &objectRect );
- }
-
- // apply the velocity
- sObjects[ indexCounter ].fXPos += sObjects[ indexCounter ].fDeltaX;
- sObjects[ indexCounter ].fYPos += sObjects[ indexCounter ].fDeltaY;
-
- // if the object has hit an edge, bounce it
- if( sObjects[ indexCounter ].fXPos < ( gOffscreenRect.left << 16 ) )
- {
- sObjects[ indexCounter ].fDeltaX *= -1;
- sObjects[ indexCounter ].fXPos += ( gOffscreenRect.left << 16 ) - sObjects[ indexCounter ].fXPos;
- }
- if( sObjects[ indexCounter ].fYPos < ( gOffscreenRect.top << 16 ) )
- {
- sObjects[ indexCounter ].fDeltaY *= -1;
- sObjects[ indexCounter ].fYPos += ( gOffscreenRect.top << 16 ) - sObjects[ indexCounter ].fYPos;
- }
- if( sObjects[ indexCounter ].fXPos +
- ( ( ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.right -
- ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.left ) << 16 ) >
- ( gOffscreenRect.right << 16 ) )
- {
- sObjects[ indexCounter ].fDeltaX *= -1;
- sObjects[ indexCounter ].fXPos += ( ( gOffscreenRect.right -
- ( ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.right -
- ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.left ) ) << 16 ) -
- sObjects[ indexCounter ].fXPos;
- }
- if( sObjects[ indexCounter ].fYPos +
- ( ( ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.bottom -
- ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.top ) << 16 ) >
- ( gOffscreenRect.bottom << 16 ) )
- {
- sObjects[ indexCounter ].fDeltaY *= -1;
- sObjects[ indexCounter ].fYPos += ( ( gOffscreenRect.bottom -
- ( ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.bottom -
- ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.top ) ) << 16 ) -
- sObjects[ indexCounter ].fYPos;
- }
-
- // if the object is visible
- if( sObjects[ indexCounter ].fIsVisible )
- {
- // evaluate the fixed numbers to new integer positions
- sObjects[ indexCounter ].fIntXPos = ( sObjects[ indexCounter ].fXPos ) >> 16;
- sObjects[ indexCounter ].fIntYPos = ( sObjects[ indexCounter ].fYPos ) >> 16;
-
- // determine the object's rect
- objectRect = ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect;
- objectRect.left += sObjects[ indexCounter ].fIntXPos;
- objectRect.top += sObjects[ indexCounter ].fIntYPos;
- objectRect.right += sObjects[ indexCounter ].fIntXPos;
- objectRect.bottom += sObjects[ indexCounter ].fIntYPos;
-
- // add the new rect to the update (so it will be drawn)
- addRectToUpdate( &objectRect );
- }
-
- // record the this frame's visibility
- sObjects[ indexCounter ].fWasVisible = sObjects[ indexCounter ].fIsVisible;
- }
- }
-
-
- //
- // blitToScreen -
- //
- // This routine updates the screen from the offscreen buffer.
- //
-
- void blitToScreen( Rect *inCopyRect )
- {
- CGrafPtr oldPort; // the graf port that is in place when we are called
- GDHandle oldDevice; // the gdevice that is in place when we are called
-
- // save the current port and gdevice
- GetGWorld( &oldPort, &oldDevice );
-
- // set the drawing environment to the screen
- SetGWorld( ( CWindowPtr )gMainWindow, GetMainDevice() );
-
- // make sure that the fore and back colors are correct to prevent colorize mode
- ForeColor( blackColor );
- BackColor( whiteColor );
-
- // Copy the screen's color table seed into the source pixmap.
- // This will minimize CopyBits' setup time.
- ( *( ( *gOffscreenPixels )->pmTable ) )->ctSeed = ( *( ( *( ( *( GetGDevice() ) )->gdPMap ) )->pmTable ) )->ctSeed;
-
- // copy the buffer to the screen
- CopyBits( ( BitMap * )( *gOffscreenPixels ), &( gMainWindow->portBits ),
- inCopyRect, inCopyRect, srcCopy, ( RgnHandle )kNil );
-
- // restore the current port and gdevice
- SetGWorld( oldPort, oldDevice );
- }
-
-
- //
- // restoreBackground -
- //
- // This routine redraws the background over changed areas.
- //
-
- void restoreBackground( void )
- {
- // erase the entire offscreen
- EraseRect( &gOffscreenRect );
- }