-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathBarney Blaster.c
executable file
·1384 lines (1171 loc) · 41.6 KB
/
Barney Blaster.c
1
/**** Barney Blaster AD module ****//**** Version 2.0 ****//**** July, '94 ****/#include <QuickDraw.h>#include <QDOffscreen.h>#include <GestaltEqu.h>#include <Memory.h>#include <Resources.h>#include <OSUtils.h>#include <ToolUtils.h>#include <FixMath.h>#include <Picker.h>#include "GraphicsModule_Types.h"#include "Sounds.h"enum { kNewBarney, kHopSetup, kHopping, kStartingHurt, kExploding, kBurning } Level;enum { kBlowUp, kCannon, kBurn } DeathType;#define anyMultibit 0x0002#define kNumOfHopFrames 5#define kNumOfExplFrames 5#define kNumOfScraps 14#define kMinCannShots 15 /* min. no. of cannon shots */#define kShotSound 128 /* 'snd ' resource ids... */#define kReactSound 129#define kReact_2Sound 130#define kExplSound 131 #define kChucSound 140 #define kFireSound 142 #define kRectWidth 86#define kRectHeight 140#define kHoleSize 33#define kFlamePicHeight 30#define kFlamePicWidth 134#define GWldTestFlag false/* record to hold BB's variables. */typedef struct BBStorage { OSErr errorHolder; Boolean soundAvailable; /* flag that indicates existence of sound. */ SoundInfo **soundInfo; /* storage for sound. */ Handle shotSound; /* sound resource handles... */ Handle reactSound; Handle react_2Sound; Handle explSound; Handle chucStartSound; Handle chucEndSound; Handle fireSound; short whichMonitor; /* the used monitor */ Rect drawingRect; /* the on-screen Rect we draw to */ Rect sourceRect; /* the 'copied-from' rect */ GWorldPtr frameGWldArray [kNumOfHopFrames]; GWorldPtr masterScrnGWld; GWorldPtr workingPicGWld; GWorldPtr scrapsPicGWld; GWorldPtr barneyMaskGWld; GWorldPtr canBallHolePicGWld; GWorldPtr canBallHoleBufrGWld; GWorldPtr bulletHolePicGWld; GWorldPtr firePicGWld; GWorldPtr fireBufrGWld; short whichLevel; short typeOfDeath; /* blow up, cannon-ball, or burn Barney? */ short appearFrame; short setupHopFrame; short setupExplFrame; unsigned long timeForNextStage; short hopCounter; short hopNumber; Boolean firstBurnShot; short cannShotCounter; short burnLevel; unsigned long timeForFireSound; short numOfBarneys;} BBStorage, *BBStoragePtr, **BBStorageHandle;/* Error handling macros */#define FailNIL(p) if(!(p)) { CleanUp((BBStorage**)h); *storage = nil; return -1; }#define FailErr(p) if(p) { CleanUp((BBStorage**)h); *storage = nil; return -1; }#define ReportIfErr(p) if(p) { TransErrStr(__LINE__,p, params ); variableStorage->errorHolder= -1; }/* some macros to simplify synchronizing to the vertical retrace. */#define SynchFlag(m) (params->monitors->monitorList[m].synchFlag)#define SynchVBL(m) synchFlag = &SynchFlag(m); *synchFlag = false; while(!*synchFlag);/**** Functions ****/OSErr DoInitialize(Handle *storage, RgnHandle blankRgn, GMParamBlockPtr params);OSErr DoClose(Handle storage, RgnHandle blankRgn, GMParamBlockPtr params);OSErr DoBlank(Handle storage, RgnHandle blankRgn, GMParamBlockPtr params);OSErr DoDrawFrame(Handle storage, RgnHandle blankRgn, GMParamBlockPtr params);OSErr DoSetUp(RgnHandle blankRgn, short message, GMParamBlockPtr params);OSErr DoHelp(RgnHandle blankRgn, GMParamBlockPtr params);static void CleanUp(BBStorage** storage);static void BarneyAppears( BBStoragePtr variableStorage, GMParamBlockPtr params);static void SetUpForHop( BBStoragePtr variableStorage, GMParamBlockPtr params);static void DoHop( BBStoragePtr variableStorage, GMParamBlockPtr params );static void SetupForExpl( BBStoragePtr variableStorage, GMParamBlockPtr params );static void DoExplosion( BBStoragePtr variableStorage, GMParamBlockPtr params );static void DoCannonShot( BBStoragePtr variableStorage, GMParamBlockPtr params );static void DoBurnStep( BBStoragePtr variableStorage, GMParamBlockPtr params );static void DoScraps( BBStoragePtr variableStorage, GMParamBlockPtr params );static void BlankTheScreen( RgnHandle blankRgn, GMParamBlockPtr params );static short GetRandom( short min, short max );static Boolean NewLocation( BBStoragePtr variableStorage, GMParamBlockPtr params );static Boolean CheckSystem( GMParamBlockPtr params );static short GetDepth( BBStoragePtr variableStorage, GMParamBlockPtr params );static void TransErrStr( int lineNum, unsigned short error, GMParamBlockPtr params ); static void CenterRect( Rect *innerRectPtr, Rect *outerRectPtr );/* * DoInitialize is the first function called from After Darkª. * The module allocates and initializes its storage. This storage is * maintained in the parameter "storage" and the function returns "noErr" * if there are no problems. */OSErr DoInitialize(Handle *storage, RgnHandle blankRgn, GMParamBlockPtr params){ Handle h, testCals; BBStoragePtr variableStorage; GWorldPtr newGWld; PicHandle thePicture; Rect offScrRect = {0,0,kRectHeight, kRectWidth }; Rect offScrScrapsRect = {0,0,30,kNumOfScraps*30}; Rect offScrCanBallHoleRect = {0,0,kHoleSize,kHoleSize }; Rect offScrBulletHoleRect = {0,0,15,15 }; Rect offScrFireRect = {0,0, kFlamePicHeight, kFlamePicWidth }; Rect offScrFireBufrRect = {0,0, kFlamePicHeight, kRectWidth }; Rect blnkRgnRect; short monitorDepth, monitorNum; register i; short myErr; unsigned short testWord; GDHandle deepestGDH; GDHandle screenGDH; GWorldPtr screenGWld; StringPtr errorMessage = (StringPtr)"\pBarney Blaster: Sorry, there is not enough memory at the moment."; if ( !(CheckSystem( params )) ) return ModuleError; /* in case we have an error, this message will be displayed. */ BlockMove(errorMessage, params->errorMessage, 1 + errorMessage[0]); /* allocate handle to my storage */ h = NewHandleClear(sizeof( BBStorage)); FailNIL(h); /* store a reference to our storage where After Darkª can keep it. */ *storage = h; /* lock down our storage so we can refer to it by pointer. */ MoveHHi(h); HLock(h); variableStorage = (BBStoragePtr)*h; monitorDepth = GetDepth( variableStorage, params ); if ( monitorDepth < 4 ) { BlockMove( "\pBarney Blaster: Sorry, requires at least 16 colors/grays.", params->errorMessage, 255); FailErr( 1 ); } blnkRgnRect = (**blankRgn).rgnBBox; deepestGDH = GetMaxDevice( &blnkRgnRect ); GetGWorld( &screenGWld, &screenGDH ); /* Create off-screen GWorlds for pics */ myErr = NewGWorld(&newGWld, 8, &offScrRect, nil, nil, useTempMem ); if ( myErr || GWldTestFlag ) myErr = NewGWorld(&newGWld, 8, &offScrRect, nil, nil, 0 ); FailErr( myErr ); (void)LockPixels( newGWld->portPixMap ); (variableStorage->workingPicGWld) = newGWld; myErr = NewGWorld(&newGWld, monitorDepth, &offScrRect, nil, nil, useTempMem ); if ( myErr || GWldTestFlag ) myErr = NewGWorld(&newGWld, monitorDepth, &offScrRect, nil, nil, 0 ); FailErr( myErr ); (void)LockPixels( newGWld->portPixMap); (variableStorage->masterScrnGWld) = newGWld; myErr = NewGWorld(&newGWld, 8, &offScrScrapsRect, nil, nil, useTempMem ); if ( myErr || GWldTestFlag ) myErr = NewGWorld(&newGWld, 8, &offScrScrapsRect, nil, nil, 0 ); FailErr( myErr ); (void)LockPixels( newGWld->portPixMap); (variableStorage->scrapsPicGWld) = newGWld; SetGWorld( newGWld, nil ); thePicture = ( GetPicture(137) ); DrawPicture( thePicture, &offScrScrapsRect ); ReleaseResource( (Handle)thePicture ); myErr = NewGWorld(&newGWld, 1, &offScrRect, nil, nil, useTempMem ); if ( myErr || GWldTestFlag ) myErr = NewGWorld(&newGWld, 1, &offScrRect, nil, nil, 0 ); FailErr( myErr ); (void)LockPixels( newGWld->portPixMap); (variableStorage->barneyMaskGWld) = newGWld; myErr = NewGWorld(&newGWld, 8, &offScrCanBallHoleRect, nil, nil, useTempMem ); if ( myErr || GWldTestFlag ) myErr = NewGWorld(&newGWld, 8, &offScrCanBallHoleRect, nil, nil, 0 ); FailErr( myErr ); (void)LockPixels( newGWld->portPixMap); (variableStorage->canBallHolePicGWld) = newGWld; SetGWorld( newGWld, nil ); thePicture = ( GetPicture(140) ); DrawPicture( thePicture, &offScrCanBallHoleRect ); ReleaseResource( (Handle)thePicture ); myErr = NewGWorld(&newGWld, 8, &offScrCanBallHoleRect, nil, nil, useTempMem ); if ( myErr || GWldTestFlag ) myErr = NewGWorld(&newGWld, 8, &offScrCanBallHoleRect, nil, nil, 0 ); FailErr( myErr ); (void)LockPixels( newGWld->portPixMap); (variableStorage->canBallHoleBufrGWld) = newGWld; SetGWorld( newGWld, nil ); EraseRect( &offScrCanBallHoleRect ); myErr = NewGWorld(&newGWld, 8, &offScrBulletHoleRect, nil, nil, useTempMem ); if ( myErr || GWldTestFlag ) myErr = NewGWorld(&newGWld, 8, &offScrBulletHoleRect, nil, nil, 0 ); FailErr( myErr ); (void)LockPixels( newGWld->portPixMap); (variableStorage->bulletHolePicGWld) = newGWld; SetGWorld( newGWld, nil ); thePicture = ( GetPicture(138) ); DrawPicture( thePicture, &offScrBulletHoleRect ); ReleaseResource( (Handle)thePicture ); myErr = NewGWorld(&newGWld, 8, &offScrFireRect, nil, nil, useTempMem ); if ( myErr || GWldTestFlag ) myErr = NewGWorld(&newGWld, 8, &offScrFireRect, nil, nil, 0 ); FailErr( myErr ); (void)LockPixels( newGWld->portPixMap); (variableStorage->firePicGWld) = newGWld; myErr = NewGWorld(&newGWld, 8, &offScrFireBufrRect, nil, nil, useTempMem ); if ( myErr || GWldTestFlag ) myErr = NewGWorld(&newGWld, 8, &offScrFireBufrRect, nil, nil, 0 ); FailErr( myErr ); (void)LockPixels( newGWld->portPixMap); (variableStorage->fireBufrGWld) = newGWld; SetGWorld( newGWld, nil ); EraseRect( &offScrFireBufrRect ); for ( i = 0; i < kNumOfHopFrames; i++ ) { myErr = NewGWorld(&newGWld, monitorDepth, &offScrRect, nil, nil, useTempMem ); if ( myErr || GWldTestFlag ) myErr = NewGWorld(&newGWld, monitorDepth, &offScrRect, nil, nil, 0 ); if ( myErr != noErr ) break; (variableStorage->frameGWldArray[i]) = newGWld; (void)LockPixels( newGWld->portPixMap); } FailErr( myErr ); SetGWorld( screenGWld, screenGDH ); variableStorage->whichLevel = kNewBarney; variableStorage->appearFrame = 0; variableStorage->setupHopFrame = 0; variableStorage->setupExplFrame = 0; variableStorage->numOfBarneys = 0; /* Test integrity of DoHelp pic */ thePicture = ( GetPicture(500) ); if ( thePicture != nil ) { for ( i = 0, testWord = 0; i < 10000; i++ ) testWord += *(*(Handle)thePicture+i); } testCals = GetResource( 'Cals', 0 );// ReportIfErr( testWord );//#ifdef notDef if ( testWord != 50092 || (char)**testCals != 0x2F ) { BlockMove( "\pBarney Blaster: Unauthorized resource modification; can't run.", params->errorMessage, 255); FailErr( 1 ); }//#endif ReleaseResource( (Handle)thePicture ); ReleaseResource( testCals ); /* see if a sound channel is even part of the parameter block. */ variableStorage->soundAvailable = (params->systemConfig & SoundAvailable) != 0; if(variableStorage->soundAvailable) { /* load the resources for our sounds. */ variableStorage->explSound = GetResource('snd ', kExplSound); FailNIL(variableStorage->explSound); variableStorage->shotSound = GetResource('snd ', kShotSound); FailNIL(variableStorage->shotSound); variableStorage->reactSound = GetResource('snd ', kReactSound); FailNIL(variableStorage->reactSound); variableStorage->react_2Sound = GetResource('snd ', kReact_2Sound); FailNIL(variableStorage->react_2Sound); variableStorage->chucStartSound = GetResource('snd ', kChucSound); FailNIL(variableStorage->chucStartSound); variableStorage->chucEndSound = GetResource('snd ', kChucSound+1); FailNIL(variableStorage->chucEndSound); variableStorage->fireSound = GetResource('snd ', kFireSound); FailNIL(variableStorage->fireSound); /* get ready to use sound. */ /* to use the sound functions in AD 2.0u we must pass in "params" */ variableStorage->soundInfo = OpenSound(params); } myErr = variableStorage->errorHolder; /* unlock storage handle. */ HUnlock(h); return myErr;} /* we arrive here if anything has failed. */static void CleanUp(BBStorage** storage){ short i; if( storage ) { BBStorage *variableStorage; MoveHHi((Handle)storage); HLock((Handle)storage); variableStorage = *storage; if(variableStorage->soundAvailable) { if(variableStorage->explSound) ReleaseResource(variableStorage->explSound); if(variableStorage->shotSound) ReleaseResource(variableStorage->shotSound); if(variableStorage->reactSound) ReleaseResource(variableStorage->reactSound); if(variableStorage->react_2Sound) ReleaseResource(variableStorage->react_2Sound); if(variableStorage->chucStartSound) ReleaseResource(variableStorage->chucStartSound); if(variableStorage->chucEndSound) ReleaseResource(variableStorage->chucEndSound); if(variableStorage->fireSound) ReleaseResource(variableStorage->fireSound); } /* GWorlds to dispose of:frameGWldArray [kNumOfHopFrames];masterScrnGWldworkingPicGWldscrapsPicGWldbarneyMaskGWldcanBallHolePicGWldcanBallHoleBufrGWldbulletHolePicGWldfirePicGWldfireBufrGWld;*/ for ( i = 0; i < kNumOfHopFrames; i++ ) { if ( variableStorage->frameGWldArray[i] ) DisposeGWorld( variableStorage->frameGWldArray[i] ); } if ( variableStorage->masterScrnGWld ) DisposeGWorld( variableStorage->masterScrnGWld ); if ( variableStorage->workingPicGWld ) DisposeGWorld( variableStorage->workingPicGWld ); if ( variableStorage->scrapsPicGWld ) DisposeGWorld( variableStorage->scrapsPicGWld ); if ( variableStorage->barneyMaskGWld ) DisposeGWorld( variableStorage->barneyMaskGWld ); if ( variableStorage->canBallHolePicGWld ) DisposeGWorld( variableStorage->canBallHolePicGWld ); if ( variableStorage->canBallHoleBufrGWld ) DisposeGWorld( variableStorage->canBallHoleBufrGWld ); if ( variableStorage->bulletHolePicGWld ) DisposeGWorld( variableStorage->bulletHolePicGWld ); if ( variableStorage->firePicGWld ) DisposeGWorld( variableStorage->firePicGWld ); if ( variableStorage->fireBufrGWld ) DisposeGWorld( variableStorage->fireBufrGWld ); DisposHandle((Handle)storage); }}/* * DoBlank is called next. * It performs tasks that are done only once, such as making the screen * go black. */OSErr DoBlank(Handle storage, RgnHandle blankRgn, GMParamBlockPtr params){ BBStoragePtr variableStorage; short monNum; Rect monRect; OSErr myErr; MoveHHi((Handle)storage); HLock((Handle)storage); variableStorage = (BBStoragePtr)*storage; PenNormal(); for ( monNum = 0; monNum < params->monitors->monitorCount; monNum++ ) { if ( (params->monitors->monitorList[monNum].curDepth) < 4 ) FillRect( &(params->monitors->monitorList[monNum].bounds), params->qdGlobalsCopy->qdBlack ); monRect = params->monitors->monitorList[monNum].bounds; MoveTo( monRect.left, monRect.top ); LineTo( monRect.right-1, monRect.top ); LineTo( monRect.right-1, monRect.bottom-1 ); LineTo( monRect.left, monRect.bottom-1 ); LineTo( monRect.left, monRect.top ); } if ( params->controlValues[0] != 0 ) BlankTheScreen( blankRgn, params ); myErr = variableStorage->errorHolder; HUnlock((Handle)storage); return myErr;}/**** BlankTheScreen ****/static void BlankTheScreen(RgnHandle blankRgn, GMParamBlockPtr params){ FillRgn(blankRgn, params->qdGlobalsCopy->qdBlack);}/* * DoDrawFrame does almost all of the work. */OSErr DoDrawFrame( Handle storage, RgnHandle blankRgn, GMParamBlockPtr params){ register BBStoragePtr variableStorage; /* deref'ed storage handle */ OSErr myErr; /* lock our storage down so we can dereference it for faster access */ MoveHHi(storage); HLock(storage); variableStorage = (BBStoragePtr)*storage; switch ( variableStorage->whichLevel ) { case kNewBarney: BarneyAppears( variableStorage, params); break; case kHopSetup: SetUpForHop( variableStorage, params); break; case kHopping: DoHop( variableStorage, params ); break; case kStartingHurt: if ( params->controlValues[2] == 0 ) // Non-violent B. Blaster? { variableStorage->numOfBarneys ++; if ( variableStorage->numOfBarneys == 15 ) { BlankTheScreen( blankRgn, params ); variableStorage->numOfBarneys = 0; } variableStorage->whichLevel = kNewBarney; } else { switch ( variableStorage->typeOfDeath ) { case kBlowUp: SetupForExpl( variableStorage, params ); break; case kCannon: DoCannonShot( variableStorage, params ); break; case kBurn: DoBurnStep( variableStorage, params ); break; } } break; case kExploding: DoExplosion( variableStorage, params ); break; } myErr = variableStorage->errorHolder; HUnlock(storage); return myErr;} /**** BarneyAppears ****/static void BarneyAppears( BBStoragePtr variableStorage, GMParamBlockPtr params){ GDHandle screenGDH; GWorldPtr screenGWld; Rect drawRect = {0,0,kRectHeight,kRectWidth}; Rect frameRect, destRect; Rect screenRect; short curFrame, i; short transMode = transparent; register Boolean *synchFlag; unsigned long holdTicks; GetGWorld(&screenGWld, &screenGDH); screenRect = variableStorage->drawingRect; frameRect = variableStorage->sourceRect; destRect = frameRect; curFrame = variableStorage->appearFrame; if ( curFrame == 0 ) { while ( !NewLocation( variableStorage, params ) ) ; screenRect = variableStorage->drawingRect; frameRect = variableStorage->sourceRect; /* From actual screen to master screen GWorld */ SetGWorld( variableStorage->masterScrnGWld, nil ); CopyBits ( (BitMap*)*screenGWld->portPixMap, (BitMap*)(*(variableStorage->masterScrnGWld)->portPixMap), &screenRect, &frameRect, srcCopy, nil); SetGWorld( variableStorage->workingPicGWld, nil ); DrawPicture( GetPicture(128), &drawRect ); } switch ( curFrame ) { case 0: destRect.top = destRect.bottom-3; break; case 1: destRect.top = destRect.bottom-(kRectHeight/4); break; case 2: destRect.top = destRect.bottom-(kRectHeight/2); break; } /* From master of screen to current frame */ SetGWorld( variableStorage->frameGWldArray[curFrame], nil ); CopyBits ( (BitMap*)(*(variableStorage->masterScrnGWld)->portPixMap), (BitMap*)(*(variableStorage->frameGWldArray[curFrame])->portPixMap), &frameRect, &frameRect, srcCopy, nil); /* From pic to frame, over screen */ CopyBits ( (BitMap*)(*(variableStorage->workingPicGWld)->portPixMap), (BitMap*)(*(variableStorage->frameGWldArray[curFrame])->portPixMap), &frameRect, &destRect, transMode, nil); if ( curFrame == kNumOfHopFrames-1 ) { for ( i = 0; i < kNumOfHopFrames-1; i++ ) { holdTicks = TickCount(); SetGWorld( screenGWld, screenGDH ); SynchVBL(variableStorage->whichMonitor); /* wait for retrace. */ /* From frame to screen */ CopyBits ( (BitMap*)(*(variableStorage->frameGWldArray[i])->portPixMap), (BitMap*)*screenGWld->portPixMap, &frameRect, &screenRect, srcCopy, nil); while (Ticks <= holdTicks+6); } variableStorage->appearFrame = -1; variableStorage->whichLevel = kHopSetup; } (variableStorage->appearFrame)++; SetGWorld( screenGWld, screenGDH );}/**** SetUpForHop ****/static void SetUpForHop( BBStoragePtr variableStorage, GMParamBlockPtr params){ GDHandle screenGDH; GWorldPtr screenGWld; Rect drawRect = {0,0,kRectHeight,kRectWidth}; Rect frameRect; Rect screenRect; short curFrame; short picIndex; GetGWorld(&screenGWld, &screenGDH); screenRect = variableStorage->drawingRect; frameRect = variableStorage->sourceRect; curFrame = variableStorage->setupHopFrame; picIndex = curFrame; if ( picIndex == kNumOfHopFrames-1 ) picIndex = 0; /* From master of screen to current frame */ SetGWorld( variableStorage->frameGWldArray[curFrame], nil ); CopyBits ( (BitMap*)(*(variableStorage->masterScrnGWld)->portPixMap), (BitMap*)(*(variableStorage->frameGWldArray[curFrame])->portPixMap), &frameRect, &frameRect, srcCopy, nil); SetGWorld( variableStorage->workingPicGWld, nil ); DrawPicture( GetPicture(128+picIndex), &drawRect ); /* From pic to frame, over screen */ SetGWorld( variableStorage->frameGWldArray[curFrame], nil ); CopyBits ( (BitMap*)(*(variableStorage->workingPicGWld)->portPixMap), (BitMap*)(*(variableStorage->frameGWldArray[curFrame])->portPixMap), &frameRect, &frameRect, transparent, nil); if ( curFrame == kNumOfHopFrames-1 ) { variableStorage->whichLevel = kHopping; variableStorage->setupHopFrame = -1; variableStorage->hopNumber = 1; variableStorage->hopCounter = (params->controlValues[1]/10)+1; if ( variableStorage->hopCounter == 11 ) variableStorage->hopCounter = GetRandom( 1, 6 ); } (variableStorage->setupHopFrame)++; SetGWorld( screenGWld, screenGDH );}/**** DoHop ****/static void DoHop( BBStoragePtr variableStorage, GMParamBlockPtr params ){ GDHandle screenGDH; GWorldPtr screenGWld; short i; register Boolean *synchFlag; Rect frameRect; Rect screenRect; long holdTicks; GetGWorld(&screenGWld, &screenGDH); screenRect = variableStorage->drawingRect; frameRect = variableStorage->sourceRect; if ( variableStorage->hopNumber == 1 ) { if(variableStorage->soundAvailable) PlaySound(variableStorage->soundInfo, params->sndChannel, variableStorage->chucStartSound); } if ( variableStorage->hopNumber == 2 ) { if(variableStorage->soundAvailable) PlaySound(variableStorage->soundInfo, params->sndChannel, variableStorage->chucEndSound); } ReportIfErr((frameRect.right - frameRect.left) - (screenRect.right - screenRect.left)); for ( i = 0; i < kNumOfHopFrames; i++ ) { holdTicks = TickCount(); SetGWorld( screenGWld, screenGDH ); SynchVBL(variableStorage->whichMonitor); /* wait for retrace. */ CopyBits ( (BitMap*)(*(variableStorage->frameGWldArray[i])->portPixMap), (BitMap*)*screenGWld->portPixMap, &frameRect, &screenRect, srcCopy, nil); while (Ticks <= holdTicks+5); } (variableStorage->hopNumber)++; (variableStorage->hopCounter)--; if ( variableStorage->hopCounter == 0 ) { variableStorage->timeForNextStage = TickCount() + 5; variableStorage->whichLevel = kStartingHurt; variableStorage->typeOfDeath = GetRandom( kBlowUp, kBurn ); variableStorage->cannShotCounter = GetRandom( kMinCannShots,kMinCannShots+15 ); variableStorage->firstBurnShot = true; }}/**** SetupForExpl ****/static void SetupForExpl( BBStoragePtr variableStorage, GMParamBlockPtr params ){ GDHandle screenGDH; GWorldPtr screenGWld; Rect drawRect = {0,0,kRectHeight,kRectWidth}; Rect frameRect; Rect screenRect; Rect sourceBulletRect = {0,0,15,15}; Rect groinRect = {99,27,115,50 }; Boolean groinShot = false; Rect destBulletRect; short curFrame; short picIndex; long holdTicks; if ( TickCount() < variableStorage->timeForNextStage ) return; GetGWorld( &screenGWld, &screenGDH ); screenRect = variableStorage->drawingRect; frameRect = variableStorage->sourceRect; curFrame = variableStorage->setupExplFrame; picIndex = curFrame+kNumOfHopFrames-1; /* From master of screen to current frame */ SetGWorld( variableStorage->frameGWldArray[curFrame], nil ); CopyBits ( (BitMap*)(*(variableStorage->masterScrnGWld)->portPixMap), (BitMap*)(*(variableStorage->frameGWldArray[curFrame])->portPixMap), &frameRect, &frameRect, srcCopy, nil); SetGWorld( variableStorage->workingPicGWld, nil ); DrawPicture( GetPicture(128+picIndex), &drawRect ); /* From pic to frame, over screen */ SetGWorld( variableStorage->frameGWldArray[curFrame], nil ); CopyBits ( (BitMap*)(*(variableStorage->workingPicGWld)->portPixMap), (BitMap*)(*(variableStorage->frameGWldArray[curFrame])->portPixMap), &frameRect, &frameRect, transparent, nil); if ( curFrame == 0 ) { /* Bullet hole to frame */ if ( GetRandom( 0, 5 ) == 0 ) { destBulletRect.left = GetRandom( groinRect.left, groinRect.right-15 ); destBulletRect.top = groinRect.top; groinShot = true; } else { destBulletRect.left = GetRandom( 32-10, 32+10 ); destBulletRect.top = GetRandom( 81-15, 81+15 ); } destBulletRect.right = destBulletRect.left+15; destBulletRect.bottom = destBulletRect.top+15; CopyBits ( (BitMap*)(*(variableStorage->bulletHolePicGWld)->portPixMap), (BitMap*)(*(variableStorage->frameGWldArray[curFrame])->portPixMap), &sourceBulletRect, &destBulletRect, transparent, nil); /* From frame to screen (first frame, displayed while rest is being set up) */ variableStorage->timeForNextStage = TickCount() + 60; SetGWorld( screenGWld, screenGDH ); CopyBits ( (BitMap*)(*(variableStorage->frameGWldArray[0])->portPixMap), (BitMap*)*screenGWld->portPixMap, &frameRect, &screenRect, srcCopy, nil); if(variableStorage->soundAvailable) { holdTicks = TickCount(); PlaySound(variableStorage->soundInfo, params->sndChannel, variableStorage->shotSound); while (Ticks <= holdTicks+15); if ( groinShot ) PlaySound(variableStorage->soundInfo, params->sndChannel, variableStorage->react_2Sound); else PlaySound(variableStorage->soundInfo, params->sndChannel, variableStorage->reactSound); } } if ( curFrame == kNumOfExplFrames-1 ) { variableStorage->whichLevel = kExploding; variableStorage->setupExplFrame = -1; } (variableStorage->setupExplFrame)++; SetGWorld( screenGWld, screenGDH );}/**** DoExplosion ****/static void DoExplosion( BBStoragePtr variableStorage, GMParamBlockPtr params ){ GDHandle screenGDH; GWorldPtr screenGWld; short i; register Boolean *synchFlag; Rect frameRect; Rect screenRect; long holdTicks; if ( TickCount() < variableStorage->timeForNextStage ) return; GetGWorld(&screenGWld, &screenGDH); screenRect = variableStorage->drawingRect; frameRect = variableStorage->sourceRect; // play the sound. if ( variableStorage->soundAvailable ) PlaySound( variableStorage->soundInfo, params->sndChannel, variableStorage->explSound ); for ( i = 0; i < kNumOfExplFrames; i++ ) { SynchVBL(variableStorage->whichMonitor); // wait for retrace. holdTicks = TickCount(); SetGWorld( screenGWld, screenGDH ); CopyBits ( (BitMap*)(*(variableStorage->frameGWldArray[i])->portPixMap), (BitMap*)*screenGWld->portPixMap, &frameRect, &screenRect, srcCopy, nil); while (Ticks <= holdTicks+4); } if ( params->controlValues[3] > 20 ) DoScraps( variableStorage, params ); variableStorage->whichLevel = kNewBarney;}/**** DoCannonShot ****/static void DoCannonShot( BBStoragePtr variableStorage, GMParamBlockPtr params ){ GDHandle screenGDH; GWorldPtr screenGWld; Rect offScrRect = {0,0,kRectHeight, kRectWidth }; Rect sourceHoleRect = { 0, 0, kHoleSize, kHoleSize }; Rect groinRect = {99,27,115,50 }; Boolean groinShot = false; Rect resultRect; Rect maskHoleRect; Rect screenHoleRect; Rect screenRect, frameRect; short holeOffsetHoriz, holeOffsetVert; long holdTicks; if ( TickCount() < variableStorage->timeForNextStage ) return; GetGWorld(&screenGWld, &screenGDH); screenRect = variableStorage->drawingRect; frameRect = variableStorage->sourceRect; if ( variableStorage->firstBurnShot ) { SetGWorld( variableStorage->barneyMaskGWld, nil ); DrawPicture( GetPicture(139), &offScrRect ); /* From master of screen to frame 0 */ SetGWorld( variableStorage->frameGWldArray[0], nil ); CopyBits ( (BitMap*)(*(variableStorage->masterScrnGWld)->portPixMap), (BitMap*)(*(variableStorage->frameGWldArray[0])->portPixMap), &frameRect, &frameRect, srcCopy, nil); SetGWorld( variableStorage->workingPicGWld, nil ); DrawPicture( GetPicture(132), &offScrRect ); /* From pic to frame, over screen */ SetGWorld( variableStorage->frameGWldArray[0], nil ); CopyBits ( (BitMap*)(*(variableStorage->workingPicGWld)->portPixMap), (BitMap*)(*(variableStorage->frameGWldArray[0])->portPixMap), &frameRect, &frameRect, transparent, nil); /* From frame 0 to screen */ SetGWorld( screenGWld, screenGDH ); CopyBits ( (BitMap*)(*(variableStorage->frameGWldArray[0])->portPixMap), (BitMap*)*screenGWld->portPixMap, &frameRect, &screenRect, srcCopy, nil); variableStorage->timeForNextStage = TickCount() + 60; holeOffsetVert = GetRandom( 55, (kRectHeight-kHoleSize) ); holeOffsetHoriz = GetRandom( 15, (kRectWidth-kHoleSize)-15 ); } else { variableStorage->timeForNextStage = TickCount() + 8; holeOffsetVert = GetRandom( 0, (kRectHeight-kHoleSize) ); holeOffsetHoriz = GetRandom( 0, (kRectWidth-kHoleSize) ); } screenHoleRect.left = screenRect.left + holeOffsetHoriz - frameRect.left; screenHoleRect.top = screenRect.top + holeOffsetVert - frameRect.top; screenHoleRect.right = screenHoleRect.left + kHoleSize; screenHoleRect.bottom = screenHoleRect.top + kHoleSize; maskHoleRect.left = holeOffsetHoriz; maskHoleRect.top = holeOffsetVert; maskHoleRect.right = maskHoleRect.left + kHoleSize; maskHoleRect.bottom = maskHoleRect.top + kHoleSize; if( SectRect( &groinRect, &maskHoleRect, &resultRect ) && resultRect.left == groinRect.left && resultRect.top == groinRect.top ) groinShot = true; /* From pic of hole to hole buffer, via barney mask */ SetGWorld( variableStorage->canBallHoleBufrGWld, nil ); EraseRect( &sourceHoleRect ); CopyMask( (BitMap*)(*(variableStorage->canBallHolePicGWld)->portPixMap), (BitMap*)(*(variableStorage->barneyMaskGWld)->portPixMap), (BitMap*)(*(variableStorage->canBallHoleBufrGWld)->portPixMap), &sourceHoleRect, &maskHoleRect, &sourceHoleRect ); SetGWorld( variableStorage->barneyMaskGWld, nil ); EraseOval( &maskHoleRect ); SetGWorld( screenGWld, screenGDH ); PaintOval( &screenHoleRect ); /* From hole buffer to screen */ CopyBits ( (BitMap*)(*(variableStorage->canBallHoleBufrGWld)->portPixMap), (BitMap*)*screenGWld->portPixMap, &sourceHoleRect, &screenHoleRect, transparent, nil); if(variableStorage->soundAvailable) { PlaySound(variableStorage->soundInfo, params->sndChannel, variableStorage->shotSound); if(variableStorage->firstBurnShot) { holdTicks = TickCount(); while (Ticks <= holdTicks+12); if ( groinShot ) PlaySound(variableStorage->soundInfo, params->sndChannel, variableStorage->react_2Sound); else PlaySound(variableStorage->soundInfo, params->sndChannel, variableStorage->reactSound); } } variableStorage->firstBurnShot = false; variableStorage->cannShotCounter--; if ( variableStorage->cannShotCounter <= 0 ) variableStorage->whichLevel = kNewBarney;}/**** DoBurnStep ****/static void DoBurnStep( BBStoragePtr variableStorage, GMParamBlockPtr params ){ GDHandle screenGDH; GWorldPtr screenGWld; Rect offScrRect = {0,0,kRectHeight, kRectWidth }; Rect flamePicRect = {0,0, kFlamePicHeight, kFlamePicWidth }; Rect sourceFlameRect = {0,0, kFlamePicHeight, 0 }; Rect fireBufrRect = {0,0, kFlamePicHeight, kRectWidth }; Rect maskFlameRect = {0, 0, 0, kRectWidth }; Rect screenRect, frameRect, screenFlameRect, monitorRect; short holeOffsetHoriz, holeOffsetVert; short i; long holdTicks; if ( TickCount() < variableStorage->timeForNextStage ) return; GetGWorld(&screenGWld, &screenGDH); screenRect = screenFlameRect = variableStorage->drawingRect; frameRect = variableStorage->sourceRect; monitorRect = params->monitors->monitorList[variableStorage->whichMonitor].bounds; if ( variableStorage->firstBurnShot ) { SetGWorld( variableStorage->barneyMaskGWld, nil ); DrawPicture( GetPicture(139), &offScrRect ); SetGWorld( variableStorage->firePicGWld, nil ); DrawPicture( GetPicture(141), &flamePicRect ); /* From master of screen to frame 0 */ SetGWorld( variableStorage->frameGWldArray[0], nil ); CopyBits ( (BitMap*)(*(variableStorage->masterScrnGWld)->portPixMap), (BitMap*)(*(variableStorage->frameGWldArray[0])->portPixMap), &frameRect, &frameRect, srcCopy, nil); SetGWorld( variableStorage->workingPicGWld, nil ); DrawPicture( GetPicture(132), &offScrRect ); /* From pic to frame, over screen */ SetGWorld( variableStorage->frameGWldArray[0], nil ); CopyBits ( (BitMap*)(*(variableStorage->workingPicGWld)->portPixMap), (BitMap*)(*(variableStorage->frameGWldArray[0])->portPixMap), &frameRect, &frameRect, transparent, nil); /* From frame 0 to screen */ SetGWorld( screenGWld, screenGDH ); CopyBits ( (BitMap*)(*(variableStorage->frameGWldArray[0])->portPixMap), (BitMap*)*screenGWld->portPixMap, &frameRect, &screenRect, srcCopy, nil); if(variableStorage->soundAvailable) { PlaySound(variableStorage->soundInfo, params->sndChannel, variableStorage->reactSound); } variableStorage->timeForFireSound = TickCount() + 12; variableStorage->burnLevel = kRectHeight - kFlamePicHeight; } variableStorage->firstBurnShot = false; if ( screenRect.right == monitorRect.right-1 ) screenFlameRect.right = screenRect.left + kRectWidth; if ( screenRect.left == monitorRect.left+1 ) screenFlameRect.left = screenRect.right - kRectWidth; sourceFlameRect.left = GetRandom( 0, kFlamePicWidth-kRectWidth ); sourceFlameRect.right = sourceFlameRect.left + kRectWidth; for ( i = 0; i < 3; i++ ) { holdTicks = TickCount(); maskFlameRect.top = variableStorage->burnLevel; maskFlameRect.bottom = maskFlameRect.top + kFlamePicHeight; if ( screenRect.top > monitorRect.top+1 ) { screenFlameRect.top = screenRect.top + maskFlameRect.top; screenFlameRect.bottom = screenFlameRect.top + kFlamePicHeight; } else { screenFlameRect.bottom = screenRect.bottom - (kRectHeight-maskFlameRect.bottom); screenFlameRect.top = screenFlameRect.bottom - kFlamePicHeight; } screenFlameRect.bottom = screenFlameRect.top + kFlamePicHeight; if ( variableStorage->burnLevel <= 2 ) { SetGWorld( variableStorage->firePicGWld, nil ); PaintRect( &flamePicRect ); } /* From section of pic of flame to flame buffer, via barney mask */ SetGWorld( variableStorage->fireBufrGWld, nil ); EraseRect( &fireBufrRect ); CopyMask( (BitMap*)(*(variableStorage->firePicGWld)->portPixMap), (BitMap*)(*(variableStorage->barneyMaskGWld)->portPixMap), (BitMap*)(*(variableStorage->fireBufrGWld)->portPixMap), &sourceFlameRect, &maskFlameRect, &fireBufrRect ); SetGWorld( screenGWld, screenGDH ); /* From flame buffer to screen */ CopyBits ( (BitMap*)(*(variableStorage->fireBufrGWld)->portPixMap), (BitMap*)*screenGWld->portPixMap, &fireBufrRect, &screenFlameRect, transparent, nil); variableStorage->burnLevel--; while (Ticks <= holdTicks+1); } variableStorage->burnLevel--; if ( TickCount() > variableStorage->timeForFireSound ) { if(variableStorage->soundAvailable) { PlaySound(variableStorage->soundInfo, params->sndChannel, variableStorage->fireSound); } variableStorage->timeForFireSound = TickCount() + GetRandom( 40, 100 ); } variableStorage->timeForNextStage = TickCount() + 1; if ( variableStorage->burnLevel <= 1 ) { if ( variableStorage->soundAvailable ) QuietSound( variableStorage->soundInfo, params->sndChannel ); variableStorage->whichLevel = kNewBarney; variableStorage->timeForNextStage = TickCount() + 8; }} /**** DoScraps ****/static void DoScraps( BBStoragePtr variableStorage, GMParamBlockPtr params ){ GDHandle screenGDH; GWorldPtr screenGWld; short i, amountScraps; register Boolean *synchFlag; Rect scrapRect = {0, 0, 30, 30}; Rect underScrapRect = {0, 0, 30, 30}; Rect screenRect; Rect monitorRect; GetGWorld(&screenGWld, &screenGDH); monitorRect = params->monitors->monitorList[variableStorage->whichMonitor].bounds; amountScraps = (11 - ((params->controlValues[3])/10)); for ( i = 0; i < kNumOfScraps; i++ ) { if ( GetRandom( 0, 10 ) > amountScraps ) { screenRect = variableStorage->drawingRect; screenRect.bottom += ( GetRandom( -30, 50 ) ); screenRect.right += ( GetRandom( -125, 75 ) ); screenRect.top = screenRect.bottom - 30; screenRect.left = screenRect.right - 30; if ( GetRandom( 0, 2 ) == 0 ) { screenRect.top += ( GetRandom( -5, 15 ) ); screenRect.right += ( GetRandom( -5, 8 ) ); } if ( screenRect.top > monitorRect.top && screenRect.left > monitorRect.left && screenRect.bottom < monitorRect.bottom && screenRect.right < monitorRect.right ) { if ( GetRandom( 0, 1 ) ) /* 1/2 of the time, draw a random scrap */ { /* underneith the main scrap. */ underScrapRect.left = ( GetRandom( 0, kNumOfScraps-1 ) )*30; underScrapRect.right = underScrapRect.left + 30; CopyBits ( (BitMap*)(*(variableStorage->scrapsPicGWld)->portPixMap), (BitMap*)*screenGWld->portPixMap, &underScrapRect, &screenRect, transparent, nil); } CopyBits ( (BitMap*)(*(variableStorage->scrapsPicGWld)->portPixMap), (BitMap*)*screenGWld->portPixMap, &scrapRect, &screenRect, transparent, nil); } } scrapRect.left += 30; scrapRect.right += 30; }}/* * DoClose() is called when the user wakes up the screen saver. The memory * is deallocated and the function returns noErr to tell AD all is well. */OSErr DoClose( Handle storage, RgnHandle blankRgn, GMParamBlockPtr params){ BBStorage **variableStorage = (BBStorage**)storage; if ( variableStorage ) CloseSound((**variableStorage).soundInfo, params->sndChannel); /* deallocate our storage */ CleanUp(variableStorage); return noErr;}/* * DoSetUp" is called if the user clicks on a button in the Control Panel. */OSErr DoSetUp( RgnHandle blankRgn, short message, GMParamBlockPtr params){ return noErr;}/* utility functions *//**** GetRandom ****/static short GetRandom( short min, short max ){ unsigned qdRdm; // treat return value as 0-65536 long t; qdRdm = Random(); t = (qdRdm * ((long)max-min+1)) / 65536; // now 0 <= t <= range return( (short) t+min );}/**** NewLocation ****/static Boolean NewLocation( BBStoragePtr variableStorage, GMParamBlockPtr params ){ Rect destRect, monitorRect, tempRectD; Rect tempRectS = {0,0,kRectHeight,kRectWidth}; int monNum; variableStorage->whichMonitor++; if ( variableStorage->whichMonitor >= params->monitors->monitorCount ) variableStorage->whichMonitor = 0; monNum = variableStorage->whichMonitor; if ( (params->monitors->monitorList[monNum].curDepth) < 4 ) return false; destRect = monitorRect = params->monitors->monitorList[monNum].bounds; destRect.left -= 20; destRect.right -= (kRectWidth-25); destRect.top -= 55; destRect.bottom -= (kRectHeight-45); tempRectD.left = GetRandom( destRect.left, destRect.right );// tempRectD.left = destRect.left; // testing code tempRectD.right = tempRectD.left + kRectWidth; if ( tempRectD.left < monitorRect.left ) { tempRectS.left += monitorRect.left-tempRectD.left+1; tempRectD.left = monitorRect.left+1; } if ( tempRectD.right > monitorRect.right ) { tempRectS.right -= tempRectD.right-monitorRect.right+1; tempRectD.right = monitorRect.right-1; } tempRectD.top = GetRandom( destRect.top, destRect.bottom );// tempRectD.top = destRect.top; // testing code tempRectD.bottom = tempRectD.top + kRectHeight; if ( tempRectD.top < monitorRect.top ) { tempRectS.top += monitorRect.top-tempRectD.top+1; tempRectD.top = monitorRect.top+1; } if ( tempRectD.bottom > monitorRect.bottom ) { tempRectS.bottom -= tempRectD.bottom-monitorRect.bottom+1; tempRectD.bottom = monitorRect.bottom-1; } variableStorage->drawingRect = tempRectD; variableStorage->sourceRect = tempRectS; return true;}/**** CheckSystem ****/static Boolean CheckSystem( GMParamBlockPtr params ){ long feature, mask; OSErr err; if (!(ExtensionsAvailable & params->systemConfig)) { BlockMove( "\pBarney Blaster: Sorry, you need After Dark 2.0u or later.", params->errorMessage, 255); return false; } err = Gestalt( gestaltQuickdrawVersion, &feature ); if ( err != noErr ) { BlockMove( "\pBarney Blaster: Sorry, requires System 6.0.5 or later.", params->errorMessage, 255); return false; } if ( feature < gestalt32BitQD12 ) { BlockMove( "\pBarney Blaster: Sorry, requires 32 bit QuickDraw.", params->errorMessage, 255); return false; } return true;}/**** GetDepth ****/static short GetDepth( BBStoragePtr variableStorage, GMParamBlockPtr params ){ short monNum; short monDepth; short maxDepth = 0; for ( monNum = 0; monNum < params->monitors->monitorCount; monNum++ ) { monDepth = (params->monitors->monitorList[monNum].curDepth); if ( monDepth > maxDepth ) { maxDepth = monDepth; variableStorage->whichMonitor = monNum; } } return maxDepth;}/**** TransErrStr ****/static void TransErrStr( int lineNumber, unsigned short errorNumber, GMParamBlockPtr params ){ StringPtr errorMessage = (StringPtr)"\pBarney Blaster: Sorry, an error occured; line # "; Str15 numStr; Str15 errorStr = "\p, error #"; short length, i; const short moduleNameLength = 14; NumToString( (long)lineNumber, numStr ); length = i = numStr[0]; while ( i ) { errorMessage[i+33+moduleNameLength] = numStr[i]; i--; } i = errorStr[0]; while ( i ) { errorMessage[length+i+33+moduleNameLength] = errorStr[i]; i--; } NumToString( (long)errorNumber, numStr ); length = i = numStr[0]; while ( i ) { errorMessage[11+length+i+33+moduleNameLength] = numStr[i]; i--; } BlockMove(errorMessage, params->errorMessage, 1 + errorMessage[0]);} /**** DoHelp ****/OSErr DoHelp(RgnHandle blankRgn, GMParamBlockPtr params){ BBStoragePtr variableStorage; Rect pictRect, windowRect; GrafPtr helpGraf; PicHandle picture; GetPort(&helpGraf); windowRect = helpGraf->portRect; picture = GetPicture( 500 ); pictRect = (**( picture )).picFrame; FillRect( &windowRect, params->qdGlobalsCopy->qdBlack ); CenterRect( &pictRect, &windowRect ); DrawPicture( picture, &pictRect ); while (Button()) ; while ( !Button() ) ; FlushEvents( everyEvent, 0 ); ReleaseResource( (Handle)picture ); return noErr;}/**** CenterRect ****/static void CenterRect( Rect *innerRectPtr, Rect *outerRectPtr ){ Rect outerRect, innerRect; innerRect = *innerRectPtr; outerRect = *outerRectPtr; OffsetRect( &innerRect, outerRect.left - innerRect.left, outerRect.top - innerRect.top); OffsetRect( &innerRect,(outerRect.right - innerRect.right)/2, (outerRect.bottom - innerRect.bottom)/2); *innerRectPtr = innerRect;}