/* Sprites.c */ #include "Sprites.h" /************************** Create/Destroy **************************/ void DeleteSprite(SpriteHandle theSprite){ short loop; BitMapHandle bh,mh,buffh; Boolean isMasked,isBuffered; bh = (**theSprite).frames; isMasked = IsSpriteMasked(theSprite); if(isMasked){ mh = (**theSprite).masks; } for(loop = 0; loop < (**theSprite).numberFrames; loop++){ MyDisposePtr( (*bh)[loop].baseAddr); if(isMasked){ MyDisposePtr((*mh)[loop].baseAddr); } } MyDisposeHandle((Handle) (**theSprite).frames); if(isMasked){ MyDisposeHandle((Handle) (**theSprite).masks); } isBuffered=IsSpriteCleaning(theSprite); if(isBuffered) { buffh= (**theSprite).buffer; MyDisposePtr( (**buffh).baseAddr); MyDisposeHandle((Handle)buffh); } MyDisposeHandle((Handle) theSprite); } SpriteHandle CreateSprite(int frameAmount, Boolean wantMasks, Boolean wantBuffer){ SpriteHandle theSprite = NULL; BitMapHandle bh = NULL, mh = NULL, buffh = NULL; Rect emptyRect = {0,0,0,0}; if(NULL != (theSprite = (SpriteHandle) NewHandleClear(sizeof(Sprite))) && NULL != (bh = (BitMapHandle) NewHandleClear(sizeof(BitMap)*frameAmount)) && NULL != (mh = (BitMapHandle) NewHandleClear(sizeof(BitMap)*frameAmount)) && NULL != (buffh = (BitMapHandle) NewHandleClear(sizeof(BitMap))) ){ // all the allocations succeeded (**theSprite).frames = bh; (**theSprite).numberFrames = frameAmount; (**theSprite).theRect = emptyRect; (**theSprite).bufferRect = emptyRect; if(wantMasks==false) MyDisposeHandle((Handle)mh); else (**theSprite).masks = mh; if(wantBuffer==false) MyDisposeHandle((Handle)buffh); else (**theSprite).buffer = buffh; return theSprite; } // something failed. clean up MyDisposeHandle((Handle) bh); MyDisposeHandle((Handle) mh); MyDisposeHandle((Handle) buffh); MyDisposeHandle((Handle) theSprite); return NULL; } void MyDisposeHandle(Handle h){ if(NULL != h){ DisposeHandle(h); } } void MyDisposePtr(Ptr p){ if(NULL != p){ DisposePtr(p); } } void MyDisposeBitMap(BitMap *bmp){ if(NULL != bmp){ MyDisposePtr(bmp->baseAddr); } } /************************* Tests/Read ****************************/ Boolean IsSpriteMasked(SpriteHandle sh){ return NULL != (**sh).masks; } Boolean IsSpriteCleaning(SpriteHandle sh){ return NULL != (**sh).buffer; } int GetSpriteX(SpriteHandle theSprite) { return (**theSprite).theRect.left; } int GetSpriteY(SpriteHandle theSprite) { return (**theSprite).theRect.top; } Point GetSpritePos(SpriteHandle theSprite) { Point temp; temp.h=GetSpriteX(theSprite); temp.v=GetSpriteY(theSprite); return temp; } /**************************** Assigns ****************************/ void SetSpritePos(SpriteHandle theSprite, Point where){ Rect *rp = &(**theSprite).theRect; OffsetRect(&(**theSprite).theRect, where.h - rp->left, where.v - rp->top); } void SetSpriteX(SpriteHandle theSprite,int newX) { int tempX=(**theSprite).theRect.left; OffsetRect(&((**theSprite).theRect),newX-tempX,0); } void SetSpriteY(SpriteHandle theSprite,int newY) { int tempY=(**theSprite).theRect.top; OffsetRect(&((**theSprite).theRect),0,newY-tempY); } /* LoadBMIntoSpriteF Assumes you have a SpriteHandle created by CreateSprite Assumes you have a BitMap source from which to copy the data Assumes you know which frame you want this loaded into (could be part of a loop to load multiple frames) The resource PICT will controle how big the Rect associated with the first frame will be, and be used for all frames */ void LoadBMIntoSpriteF(SpriteHandle theSprite,short theFrame, BitMap *loadBM) { BitMap maskBM; BitMapHandle bh = NULL, mh = NULL; Boolean isRectEmpty; maskBM.baseAddr = NULL; HLock((Handle)theSprite); isRectEmpty = EmptyRect(&((**theSprite).theRect)); HUnlock((Handle)theSprite); if(isRectEmpty) (**theSprite).theRect = loadBM->bounds; bh = (**theSprite).frames; (*bh)[theFrame] = *loadBM; if(IsSpriteMasked(theSprite)) { mh = (**theSprite).masks; maskBM.bounds = loadBM->bounds; if(maskBM.baseAddr == NULL) InitBitMap(&maskBM); MyCalcMask(&(*bh)[theFrame],&maskBM); (*mh)[theFrame] = maskBM; } } /* LoadPictIntoSpriteFrame Assumes you have a SpriteHandle created by CreateSprite Assumes you have a PICT resource ID ready to be loaded Assumes you know which frame you want this loaded into (could be part of a loop to load multiple frames) The resource PICT will controle how big the Rect associated with the first frame will be, and be used for all frames */ void LoadPictIntoSpriteFrame(SpriteHandle theSprite,short theFrame, int resID) { BitMap loadBM, maskBM; BitMapHandle bh = NULL, mh = NULL; Boolean isRectEmpty; loadBM.baseAddr = NULL; maskBM.baseAddr = NULL; HLock((Handle)theSprite); isRectEmpty = EmptyRect(&((**theSprite).theRect)); HUnlock((Handle)theSprite); if(LoadPicResIntoBitMap(&loadBM, resID)){ if(isRectEmpty) (**theSprite).theRect = loadBM.bounds; /* only sets it once--the first time a frame is loaded. I'll have to assume all other frames will have the exact same bounds.*/ bh = (**theSprite).frames; (*bh)[theFrame] = loadBM; if(IsSpriteMasked(theSprite)) { mh = (**theSprite).masks; maskBM.bounds = loadBM.bounds; if(maskBM.baseAddr == NULL) InitBitMap(&maskBM); MyCalcMask(&(*bh)[theFrame],&maskBM); (*mh)[theFrame] = maskBM; } } } SpriteHandle LoadDataIntoSprite(short fRefNum, Boolean wantMasks, Boolean wantBuffer) { int loop; int numberFrames; Rect theRect; Boolean isMasked, isCleaning; short rowBytes; long calculatedSize; BitMapHandle bh,mh; BitMap maskBM; long count; SpriteHandle theSprite; maskBM.baseAddr = NULL; count = sizeof(int); FSRead(fRefNum,&count,&numberFrames); count = sizeof(Rect); FSRead(fRefNum,&count,&theRect); theSprite = CreateSprite(numberFrames,wantMasks,wantBuffer); HLock((Handle)theSprite); (**theSprite).theRect = theRect; bh=(**theSprite).frames; HLock((Handle)bh); mh = (**theSprite).masks; HLock((Handle)mh); for(loop=0;loopbounds.bottom-srcBM->bounds.top; wrdsWide=(srcBM->rowBytes)/2; CalcMask(srcBM->baseAddr,dstBM->baseAddr,srcBM->rowBytes,dstBM->rowBytes,height,wrdsWide); GetPort(&oldPort); tmpR=dstBM->bounds; CreateOffscreenGrafPort(&tmpOS, &(tmpR)); SetPort(tmpOS); FillRect(&tmpR,white); tmpR=dstBM->bounds; OffsetRect(&tmpR,-1,0); CopyBits(dstBM,&(qd.thePort->portBits), &(dstBM->bounds),&tmpR, srcOr, NULL); tmpR=dstBM->bounds; OffsetRect(&tmpR,1,0); CopyBits(dstBM,&(qd.thePort->portBits), &(dstBM->bounds),&tmpR, srcOr, NULL); tmpR=dstBM->bounds; OffsetRect(&tmpR,0,1); CopyBits(dstBM,&(qd.thePort->portBits), &(dstBM->bounds),&tmpR, srcOr, NULL); tmpR=dstBM->bounds; OffsetRect(&tmpR,0,-1); CopyBits(dstBM,&(qd.thePort->portBits), &(dstBM->bounds),&tmpR, srcOr, NULL); OffsetRect(&tmpR,1,1); CopyBits(dstBM,&(qd.thePort->portBits), &(dstBM->bounds),&tmpR, srcOr, NULL); OffsetRect(&tmpR,-1,1); CopyBits(dstBM,&(qd.thePort->portBits), &(dstBM->bounds),&tmpR, srcOr, NULL); OffsetRect(&tmpR,1,-1); CopyBits(dstBM,&(qd.thePort->portBits), &(dstBM->bounds),&tmpR, srcOr, NULL); OffsetRect(&tmpR,-1,-1); CopyBits(dstBM,&(qd.thePort->portBits), &(dstBM->bounds),&tmpR, srcOr, NULL); tmpR=dstBM->bounds; CopyBits(&(qd.thePort->portBits),dstBM,&(tmpR), &(dstBM->bounds), srcCopy, NULL); SetPort(oldPort); DestroyOffscreenGrafPort(tmpOS); } void GetSpriteBuffer(SpriteHandle theSprite) { BitMapHandle buffh; Rect srcR; buffh=(**theSprite).buffer; if(buffh != NULL) { srcR = (**theSprite).theRect; HLock((Handle) buffh); CopyBits(&qd.thePort->portBits,&(**buffh),&srcR,&(**buffh).bounds, srcCopy, NULL); HUnlock((Handle) buffh); } } /**************************** Display ****************************/ void BlitSprite(SpriteHandle theSprite, short frameIndex){ BitMap buffBM; BitMapHandle buffh = NULL; buffBM.baseAddr = NULL; if(IsSpriteCleaning(theSprite)) { buffh = (**theSprite).buffer; if(NULL == (**buffh).baseAddr) { buffBM.bounds = (*((**theSprite).frames))[frameIndex].bounds; InitBitMap(&buffBM); (**buffh) = buffBM; (**theSprite).bufferRect = (**theSprite).theRect; GetSpriteBuffer(theSprite); } HLock((Handle)buffh); HLock((Handle)theSprite); CopyBits(&(**buffh),&qd.thePort->portBits,&(**buffh).bounds, &(**theSprite).bufferRect,srcCopy, NULL); HUnlock((Handle)theSprite); HUnlock((Handle)buffh); (**theSprite).bufferRect = (**theSprite).theRect; GetSpriteBuffer(theSprite); } if(IsSpriteMasked(theSprite)) { DrawMask(theSprite,frameIndex,srcBic); DrawSprite(theSprite,frameIndex,srcOr); } else DrawSprite(theSprite,frameIndex,srcCopy); } void DrawSprite(SpriteHandle theSprite, short frameIndex, short transfer) { BitMapHandle bh = (**theSprite).frames; Rect destR = (**theSprite).theRect; HLock((Handle) bh); CopyBits(&(*bh)[frameIndex], &qd.thePort->portBits, &(*bh)[frameIndex].bounds, &destR, transfer, NULL); HUnlock((Handle) bh); } void DrawSpriteTo(SpriteHandle theSprite, short frameIndex, short transfer, BitMap *destBM) { BitMapHandle bh = (**theSprite).frames; Rect destR = (**theSprite).theRect; HLock((Handle) bh); CopyBits(&(*bh)[frameIndex], destBM, &(*bh)[frameIndex].bounds, &destR, transfer, NULL); HUnlock((Handle) bh); } void SpriteToOffscreen(SpriteHandle theSprite, short frameIndex, GrafPtr offscreenBM) { BitMapHandle bh = (**theSprite).frames; GrafPtr oldG; GetPort(&oldG); SetPort(offscreenBM); DrawSprite(theSprite,frameIndex,srcCopy); SetPort(oldG); } void DrawMask(SpriteHandle theSprite, short frameIndex, short transfer){ BitMapHandle mh = (**theSprite).masks; Rect destR = (**theSprite).theRect; HLock((Handle) mh); CopyBits(&(*mh)[frameIndex], &qd.thePort->portBits, &(*mh)[frameIndex].bounds, &destR, transfer, NULL); HUnlock((Handle) mh); }