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/SpriteFrameSet.c
#include "ZAMProtos.h" |
void InitFrameSetInfo(frameSetPtr fsp, short frameCount) |
/* initialize the frame set header */ |
/* this is the stuff that is block moved around when a sprite frame set is shared */ |
/* not a good way to do it. */ |
{ |
fsp->finfo.frameCount = frameCount; |
fsp->finfo.frameIndex = 0; |
fsp->finfo.curImage = &fsp->flist[0]; |
fsp->finfo.prevImage = fsp->finfo.curImage; |
fsp->finfo.dimension.h = RECT_WD(fsp->flist[0].image->portRect); |
fsp->finfo.dimension.v = RECT_HT(fsp->flist[0].image->portRect); |
fsp->finfo.center.h = fsp->finfo.dimension.h / 2; |
fsp->finfo.center.v = fsp->finfo.dimension.v / 2; |
} |
void SetSpriteCurrentFrame(spritePtr theSprite, short frameNum) |
/* |
Force the sprite to change frame. This also remembers the current frame |
so that erasing happens correctly later. |
*/ |
{ |
theSprite->frameList->finfo.frameIndex = frameNum; |
theSprite->frameList->finfo.prevImage = theSprite->frameList->finfo.curImage; |
theSprite->frameList->finfo.curImage = &theSprite->frameList->flist[frameNum]; |
} |
OSErr CopyFrameSet(frameSetPtr srcFrameSet, frameSetPtr *destFrameSet) |
/* |
This should be called duplicate or clone because it allocates |
the destination frame set for you and copies the source to it. |
*/ |
{ |
frameSetPtr fsp; |
long fsSize; |
OSErr err = noErr; |
fsSize = sizeof(frameInfo) + (sizeof(frameCell) * srcFrameSet->finfo.frameCount); |
/* create a new frame set block -- this is the destination frame set */ |
fsp = (frameSetPtr)NewPtrClear(fsSize); |
if(fsp == nil) { |
err = MemError(); |
ErrMsgCode("\pError allocating SpriteFrameSet",err); |
} |
if(err == noErr) { |
BlockMove(srcFrameSet, fsp, fsSize); |
} |
*destFrameSet = fsp; |
return err; |
} |
OSErr CreateEmptyFrameSet(frameSetPtr *dstFrameSet, short numFrames) |
/* |
This creates a frame set with no actual content. |
Content can be copied later with SetSpriteFrameSet, which is the nasty block move |
culprit. |
*/ |
{ |
frameSetPtr fsp; |
long fsSize; |
OSErr err = noErr; |
fsSize = sizeof(frameInfo) + (sizeof(frameCell) * numFrames); |
/* create a new frame set block -- this is the destination frame set */ |
fsp = (frameSetPtr)NewPtrClear(fsSize); |
if(fsp == nil) { |
err = MemError(); |
ErrMsgCode("\pError allocating SpriteFrameSet",err); |
} |
if(err == noErr) { |
fsp->finfo.frameCount = numFrames; |
fsp->finfo.frameIndex = 0; |
fsp->finfo.curImage = nil; |
fsp->finfo.prevImage = nil; |
} |
*dstFrameSet = fsp; |
return err; |
} |
void SetSpriteFrameSet( spritePtr theSprite, frameSetPtr srcFrameSet) |
/* |
Change the frame set of a sprite from whatever it was to the new one. |
Note that this has one severe limiation, in that you can only go to another |
frame set that has the same number of frames. This function could be changed |
to check for a difference in size and deal with it, but it is actually pretty |
weak as it is already, and a completely different scheme would work better. |
A frame set reference perhaps or something like that. |
*/ |
{ |
long fsSize; |
frameCellPtr prevFrameSet; |
fsSize = GetPtrSize(srcFrameSet); |
/* save the previous frame set for erasing the old image */ |
prevFrameSet = theSprite->frameList->finfo.curImage; |
/* copy the new frame set over the first one, and set it to the start */ |
BlockMove(srcFrameSet, theSprite->frameList, fsSize); |
InitFrameSetInfo(theSprite->frameList, srcFrameSet->finfo.frameCount); |
/* if there was a previous frame set, then restore it */ |
if(prevFrameSet != nil) |
theSprite->frameList->finfo.prevImage = prevFrameSet; |
} |
OSErr CreateColorIconFrameSet(frameSetPtr *newFrameSet, short startID, short numFrames) |
/* |
Create a frame set from color icons starting with CICN resource id startID for the numFrames. |
*/ |
{ |
short index; |
frameSetPtr fsp; |
frameCellPtr fcp; |
short err = noErr; |
CIconHandle cicn; |
/* create a new frame set block */ |
fsp = (frameSetPtr)NewPtrClear(sizeof(frameInfo) + (sizeof(frameCell) * numFrames)); |
if(fsp == nil) { |
err = MemError(); |
ErrMsgCode("\pError allocating SpriteFrameSet",err); |
} |
if(err == noErr) { |
/* load the frames into the GWorld list */ |
for(index = 0; (index < numFrames) && (err == noErr); index ++) { |
fcp = &fsp->flist[index]; |
cicn = GetCIcon(startID + index); |
if(cicn == nil) { |
err = ResError(); |
ErrMsgCode("\pcicn resource not loaded in CreateColorIconFrameSet",err); |
} else { |
err = CreateGWorldFromCIcon(&fcp->image, cicn); |
if(err != noErr) { |
ErrMsgCode("\pCreateColorIconFrameSet: CreateGWorldFromCIcon failed.",err); |
} |
if(err == noErr) { |
err = CreateRegionFromCIconMask(&fcp->mask, cicn); |
if(err != noErr) { |
ErrMsgCode("\pCreateRegionFromCIconMask failed.",err); |
} else { |
/* save off the topleft of the region so we can move */ |
/* it with the sprite */ |
fcp->maskLoc.v = (**fcp->mask).rgnBBox.top; |
fcp->maskLoc.h = (**fcp->mask).rgnBBox.left; |
} |
} |
DisposeCIcon(cicn); |
} |
} |
/* have all the frames, so set up the frame header information */ |
InitFrameSetInfo(fsp, numFrames); |
} |
*newFrameSet = fsp; |
if(err != noErr) { |
/* crappy for now but hey */ |
ErrMsgCode("\pIt would be unwise to proceed.!!!",err); |
ExitToShell(); |
} |
return err; |
} |
OSErr CreatePICTIconFrameSet(frameSetPtr *newFrameSet, short startID, short numFrames) |
/* |
Does the same thing, only the image is loaded from a picture while |
the mask is loaded from a cicn. The reason for this is that I originally was only using |
cicns, but, then I discovered a lovely program called DeBabelizer |
( by Equilibrium Technologies, in Sausalito, CA), which will take a whole bunch of art work |
from just about anywhere and create a common palette for it, and even re-map the pictures to the |
new palette. So I did that with all the artwork in ZAM, but did not want to take it from the PICTs |
back to CICN. Too bad Debabelizer cannot process CICNS directly. |
So this is a hacky way around it, and I'm sorry to say it takes up more room on disk. |
*/ |
{ |
short index; |
frameSetPtr fsp; |
frameCellPtr fcp; |
short err = noErr; |
CIconHandle cicn; |
PicHandle pict; |
/* create a new frame set block */ |
fsp = (frameSetPtr)NewPtrClear(sizeof(frameInfo) + (sizeof(frameCell) * numFrames)); |
if(fsp == nil) { |
err = MemError(); |
ErrMsgCode("\pError allocating SpriteFrameSet",err); |
} |
if(err == noErr) { |
/* load the frames into the GWorld list */ |
for(index = 0; (index < numFrames) && (err == noErr); index ++) { |
fcp = &fsp->flist[index]; |
cicn = GetCIcon(startID + index); |
if(cicn == nil) { |
err = ResError(); |
ErrMsgCode("\pcicn resource not loaded in CreateColorIconFrameSet",err); |
} else { |
pict = GetPicture(startID + index); |
if(pict == nil) { |
err = ResError(); |
ErrMsgCode("\pPICT resource not loaded in CreateColorIconFrameSet",err); |
} else { |
err = CreateGWorldFromPict(&fcp->image, pict); |
if(err != noErr) { |
ErrMsgCode("\pCreateColorIconFrameSet: CreateGWorldFromPict failed.",err); |
} |
if(err == noErr) { |
err = CreateRegionFromCIconMask(&fcp->mask, cicn); |
if(err != noErr) { |
ErrMsgCode("\pCreateRegionFromCIconMask failed.",err); |
} else { |
/* save off the topleft of the region so we can move */ |
/* it with the sprite */ |
fcp->maskLoc.v = (**fcp->mask).rgnBBox.top; |
fcp->maskLoc.h = (**fcp->mask).rgnBBox.left; |
} |
} |
ReleaseResource(pict); |
} |
DisposeCIcon(cicn); |
} |
} |
/* have all the frames, so set up the frame header information */ |
InitFrameSetInfo(fsp, numFrames); |
} |
*newFrameSet = fsp; |
if(err != noErr) { |
/* crappy for now but hey */ |
ErrMsgCode("\pIt would be unwise to proceed.!!!",err); |
ExitToShell(); |
} |
return err; |
} |
short GetNextSpriteFrameIndex(spritePtr spr) |
{ |
short frameNum; |
frameNum = spr->frameList->finfo.frameIndex + 1; |
if(frameNum >= spr->frameList->finfo.frameCount) { |
frameNum = 0; |
} |
return frameNum; |
} |
void AttachCTableToFrameSet(frameSetPtr frameSet, CTabHandle srcCtable, short ctSeed) |
/* |
Change the color table of a frame set, and set the seed. I had mixed results using this. |
*/ |
{ |
CTabHandle ctab; |
frameCellPtr prevFrameSet; |
short i; |
PixMapHandle pmH; |
ctab = srcCtable; |
for(i = 0; i < frameSet->finfo.frameCount; i++) { |
pmH = GetGWorldPixMap(frameSet->flist[i].image); // get pixmap |
DisposeHandle((**pmH).pmTable); |
HandToHand(&ctab); // duplicate it |
(**pmH).pmTable = ctab; // stuff it in |
(**(**pmH).pmTable).ctSeed = ctSeed; // change the seed |
} |
} |
void SetFrameSetCTSeed(frameSetPtr frameSet, short newSeed) |
{ |
short i; |
PixMapHandle pmH; |
for(i = 0; i < frameSet->finfo.frameCount; i++) { |
pmH = GetGWorldPixMap(frameSet->flist[i].image); // get pixmap |
(**(**pmH).pmTable).ctSeed = newSeed; // change the seed |
} |
} |
void SetSpriteXXFrameSet( spritePtr theSprite, frameSetPtr srcFrameSet) |
/* |
Guess this is old dead code no longer used. |
*/ |
{ |
long fsSize; |
frameCellPtr prevFrameSet; |
fsSize = GetPtrSize(srcFrameSet); |
/* save the previous frame set for erasing the old image */ |
prevFrameSet = theSprite->frameList->finfo.curImage; |
/* copy the new frame set over the first one, and set it to the start */ |
BlockMove(srcFrameSet, theSprite->frameList, fsSize); |
InitFrameSetInfo(theSprite->frameList, srcFrameSet->finfo.frameCount); |
/* if there was a previous frame set, then restore it */ |
theSprite->frameList->finfo.prevImage = prevFrameSet; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14