Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
GameSource/ExplosionSprites.c
/* |
Explosion Sprites |
this is the code for handling the animated explosions in ZAM. |
*/ |
#include "ZAM.h" |
#include "SpriteFrameRates.h" |
#include "GameSounds.h" |
#include "ZAMProtos.h" |
#define kFirstExpFrameNum 0 |
#define kLastExpFrameNum 5 |
spritePtr GetExplosionSprite(gamePtr game); |
/* these are the globals used by this file. They are private to this file */ |
/* other parts of the game deal with explosions by calling the routines in this file */ |
static spriteLayerPtr gExplosionLayer; |
static spritePtr gExplosionSprite[kMaxExp]; |
void StartExplosionHere(gamePtr game, Fixed h, Fixed v) |
/* |
This is the main explosion generation routine. When you want one, |
just call this and pass the fixed point coordinates, and an explosion will |
start. The game parameter is not really used any more, but the explosion list |
used to be kept in it. |
*/ |
{ |
spritePtr thisExp; |
thisExp = GetExplosionSprite(game); |
if(thisExp != nil) { |
thisExp->visible = false; |
SetSpriteCurrentFrame(thisExp,0); |
SetSpriteLoc(thisExp, h, v); |
thisExp->visible = true; |
(void)PlaySndAsynchChannel( kExplode, kExplosionChan, kStdPriority); |
StartSpriteAction(thisExp); |
} |
} |
spritePtr GetExplosionSprite(gamePtr game) |
/* |
this function returns a spritePtr that is to be used for a new |
explosion. At one time I had an elaborate queueing scheme the prevented searching a list, |
but then I simplified it in order to reduce complexity and track down bugs in other parts of |
the code. |
*/ |
{ |
short i; |
for(i = 0; i < kMaxExp; i++) { |
if(!gExplosionSprite[i]->inUse) { |
gExplosionSprite[i]->inUse = true; |
return gExplosionSprite[i]; |
} |
} |
return nil; |
} |
Boolean ExplosionLastFrameProc(spritePtr expSprite, frameCellPtr frame) |
/* |
On the last frame of animation we want to hide the explosion |
so it erases properly, so explosion sprites are created with a frame callback |
on the last frame of animation. |
*/ |
{ |
expSprite->visible = false; // hide it |
expSprite->inUse = false; // free it up |
StopSpriteAction(expSprite); // stop its clock |
expSprite->spriteFlags |= kNeedsToBeErased; // flag it for updating |
expSprite->ownerLayer->layerFlags |= kLayerDirty; // be sure the layer is flagged too |
return false; // don't want to be re-inserted in timer |
} |
Boolean FirstFrameProc(spritePtr explosionSprite, frameCellPtr frame) |
/* |
Make sure the sprite is visible on the first frame of animation. |
I forget why I do this, I think it was because of problems when one explosion was |
cancelled to start a new one. |
*/ |
{ |
explosionSprite->visible = true; // just make sure we are visible |
return true; |
} |
void StartExplosionMoving(gamePtr game, Fixed h, Fixed v, fixPt *vel) |
/* |
This routine was used when I wanted the explosions to drift around |
but I don't use it anymore. The explosions will move though if you |
replace StartExplosionHere with this. Pretty handy. |
*/ |
{ |
spritePtr thisExp; |
thisExp = GetExplosionSprite(game); |
if(thisExp == nil) { /* no more free explosions */ |
ErrMsg("\pNo More Explosions are available"); |
} else { |
thisExp->visible = false; |
/* prevent any drawing */ |
StopSpriteAction(thisExp); |
SetSpriteCurrentFrame(thisExp,0); |
SetSpriteLoc(thisExp, h, v); |
SetSpriteVelocity(thisExp, vel->h >> 1, vel->v >> 1); |
thisExp->moveTimeInterval = 100; |
thisExp->visible = true; |
StartSpriteAction(thisExp); |
} |
} |
void LoadExplosionSprites(gamePtr game) |
/* |
This function loads all the graphics for the explosion sprites |
and also creates all of them. The game is limited to a fixed |
number of explosions happening at any one time. |
*/ |
{ |
OSErr err; |
short ref; |
frameSetPtr expFrameSet; |
short i; |
short y; |
ref = OpenResFile("\pExplosionFrames.rsrc"); |
err = CreateColorIconFrameSet(&expFrameSet, kBaseID, kMaxExpFrames); |
if(err != noErr) { |
ErrMsgCode("\pCreateColorIconFrameSet failed.",err); |
} |
if(err == noErr) |
SetFrameSetCTSeed(expFrameSet,game->gameCTSeed); |
err = CreateSpriteLayer(&gExplosionLayer,game->tween,game->backdrop,game->gameWind); |
if(err != noErr) { |
ErrMsgCode("\pCreateSpriteLayer failed.",err); |
} |
if(err == noErr) { |
err = CreateEmptySprite(gExplosionLayer, |
&gExplosionSprite[0], /* returned sprite here */ |
kDefaultFrameAdvance, |
0, /* time between movement */ |
kExplosionFrameTime, /* time between frame change */ |
(long)game); /* refcon, ptr to game */ |
if(err != noErr) { |
ErrMsgCode("\pCreateEmptySprite failed.",err); |
} else { |
/* install the missile frame set */ |
gExplosionSprite[0]->frameList = expFrameSet; |
} |
} |
for(i = 1; i < kMaxExp; i++) { |
if(err == noErr) { |
err = CreateEmptySprite(gExplosionLayer, |
&gExplosionSprite[i], /* returned sprite here */ |
kDefaultFrameAdvance, |
0, /* time between movement */ |
kExplosionFrameTime, /* time between frame change */ |
(long)game); |
if(err != noErr) { |
ErrMsgCode("\pCreateEmptySprite failed.",err); |
} |
} |
if(err == noErr) { |
/* dup the frame set */ |
err = CopyFrameSet(expFrameSet, &gExplosionSprite[i]->frameList); |
if(err != noErr) { |
ErrMsgCode("\pCopyFrameSet failed!",err); |
} |
} |
} |
for(i = 0; i < kMaxExp; i++) { |
SetSpriteFrameCallback(gExplosionSprite[i],kFirstExpFrameNum,FirstFrameProc); |
SetSpriteFrameCallback(gExplosionSprite[i],kLastExpFrameNum,ExplosionLastFrameProc); |
SetSpriteFrameRef(gExplosionSprite[i],kLastExpFrameNum, i); |
gExplosionSprite[i]->inUse = false; |
} |
CloseResFile(ref); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14