00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "spriteObject.h"
00021
00027 spriteObject::spriteObject(spriteManager *newsm)
00028 : bNeedsGFXCleanup(false), attachment(NULL), isAttachment(false), staticSprite(false), sm(newsm),
00029 parentSprite(NULL), childSprite(NULL), spriteID(-1), palleteID(-1), gfxID(-1),
00030 #ifdef __WITHSOUND
00031 soundChannel(-1),
00032 #endif
00033 x(0), y(0), vx(0), vy(0), oldx(0), oldy(0), flippedh(false), flippedv(false),
00034 oldFliph(false), oldFlipv(false), layer(0), frame(0), oldFrame(0), arbitraryAnim(0),
00035 arbitrarySpeed(0), arbitraryFrameCounter(0), arbitraryTimeCounter(0), centerx(0),
00036 centery(0), collision(COL_NONE), checkCollision(false), ignoreUntilUntouched(NULL), rotSetID(-1),
00037 rotAngle(0), bRotating(false), UPDATEDlayer(false), UPDATEDflip(false), framesToLive(-1)
00038 {
00039 sm->gameSprites.push_back(this);
00040 #ifdef __MDDEBUG
00041 className = "spriteObject";
00042 char buffer[255];
00043 sprintf(buffer, "%d: constructed at gameSprites %d", sm->screen, sm->gameSprites.size()-1);
00044 macros::debugMessage(className, buffer);
00045 #endif
00046 }
00047
00051 spriteObject::~spriteObject()
00052 {
00053 #ifdef __WITHSOUND
00054 stopSound();
00055 #endif
00056 deleteSprite();
00057 }
00058
00064 spriteObject::spriteObject(const spriteObject &s)
00065 {
00066 sm = s.sm;
00067 parentSprite = s.parentSprite;
00068 childSprite = s.childSprite;
00069 attachment = s.attachment;
00070 ignoreUntilUntouched = s.ignoreUntilUntouched;
00071
00072 bNeedsGFXCleanup = s.bNeedsGFXCleanup;
00073 isAttachment = s.isAttachment;
00074 staticSprite = s.staticSprite;
00075 spriteID = s.spriteID;
00076 palleteID = s.palleteID;
00077 gfxID = s.gfxID;
00078 #ifdef __WITHSOUND
00079 soundChannel = s.soundChannel;
00080 #endif
00081 x = s.x; y = s.y; vx = s.vx; vy = s.vy; oldx = s.oldx; oldy = s.oldy;
00082 flippedh = s.flippedh; flippedv = s.flippedv; oldFliph = s.oldFliph; oldFlipv = s.oldFlipv;
00083 layer = s.layer; frame = s.frame; oldFrame = s.oldFrame;
00084 arbitraryAnim = s.arbitraryAnim; arbitrarySpeed = s.arbitrarySpeed;
00085 arbitraryFrameCounter = s.arbitraryFrameCounter; arbitraryTimeCounter = s.arbitraryTimeCounter;
00086 centerx = s.centerx; centery = s.centery; collision = s.collision;
00087 checkCollision = s.checkCollision;
00088 rotSetID = s.rotSetID; rotAngle = s.rotAngle; bRotating = s.bRotating;
00089 UPDATEDlayer = s.UPDATEDlayer; UPDATEDflip = s.UPDATEDflip;
00090 framesToLive = s.framesToLive;
00091 }
00092
00109 s8 spriteObject::giveSprite(const unsigned char *spriteData, u8 sizex, u8 sizey, u8 cx, u8 cy, u8 minIndex, s16 nx, s16 ny, u8 colorMode)
00110 {
00111 if (palleteID == -1) {
00112 #ifdef __MDDEBUG
00113 macros::debugMessage(ERRTEXT, "giveSprite() but no pal!", ERRORPOS);
00114 #endif
00115 return -1;
00116 }
00117
00118
00119
00120 #ifdef __MDDEBUG
00121 char buffer[255];
00122 sprintf(buffer, "%d: attempting to get raw sprite", sm->screen);
00123 macros::debugMessage(className, buffer);
00124 #endif
00125
00126 gfxID = sm->loadGFX(spriteData, sizex, sizey, colorMode);
00127 spriteID = sm->loadSpriteFromGFX(gfxID, sizex, sizey, palleteID, minIndex, colorMode, OFFX, OFFY);
00128 bNeedsGFXCleanup = true;
00129
00130 #ifdef __MDDEBUG
00131 memset(buffer, 0, 255);
00132 sprintf(buffer, "%d: raw sprite given (gfx #%d, sprite #%d)", sm->screen, gfxID, spriteID);
00133 macros::debugMessage(className, buffer);
00134 #endif
00135
00136
00137
00138 centerx = cx;
00139 centery = cy;
00140 setPos(nx, ny);
00141 return spriteID;
00142 }
00143
00151 s8 spriteObject::givePallete(const unsigned short *palleteData)
00152 {
00153 #ifdef __MDDEBUG
00154 char buffer[255];
00155 sprintf(buffer, "%d: attempting to get raw pallete", sm->screen);
00156 macros::debugMessage(className, buffer);
00157 #endif
00158 palleteID = sm->loadPallete((void*)palleteData);
00159 #ifdef __MDDEBUG
00160 memset(buffer, 0, 255);
00161 sprintf(buffer, "%d: raw pallete given (#%d)", sm->screen, palleteID);
00162 macros::debugMessage(className, buffer);
00163 #endif
00164 return palleteID;
00165 }
00166
00177 bool spriteObject::updatePallete(s8 newPalID, u8 sizex, u8 sizey, u8 colorMode)
00178 {
00179 #ifdef __MDDEBUG
00180 char buffer[255];
00181 sprintf(buffer, "%d: attempting pallete update (#%d -> #%d)", sm->screen, palleteID, newPalID);
00182 macros::debugMessage(className, buffer);
00183 #endif
00184 if (gfxID != -1 && spriteID != -1 && newPalID != -1)
00185 {
00186 palleteID = newPalID;
00187 sm->updateSpritePallete(spriteID, gfxID, newPalID, sizex, sizey, colorMode, x>>8, y>>8);
00188 UPDATEDflip = true;
00189 return true;
00190 }
00191 return false;
00192 }
00193
00210 s8 spriteObject::giveGFX(u16 GFXid, u8 sizex, u8 sizey, u8 cx, u8 cy, u8 minIndex, s16 nx, s16 ny, u8 colorMode)
00211 {
00212 #ifdef __MDDEBUG
00213 char buffer[255];
00214 sprintf(buffer, "%d: attempting to get preloaded GFX", sm->screen);
00215 macros::debugMessage(className, buffer);
00216 #endif
00217 gfxID = GFXid;
00218 spriteID = sm->loadSpriteFromGFX(GFXid, sizex, sizey, palleteID, minIndex, colorMode, OFFX, OFFY);
00219 #ifdef __MDDEBUG
00220 memset(buffer, 0, 255);
00221 sprintf(buffer, "%d: preloaded GFX given (gfx #%d, sprite #%d)", sm->screen, gfxID, spriteID);
00222 macros::debugMessage(className, buffer);
00223 #endif
00224 centerx = cx;
00225 centery = cy;
00226 setPos(nx, ny);
00227 return spriteID;
00228 }
00229
00241 void spriteObject::deleteSprite()
00242 {
00243 #ifdef __MDDEBUG
00244 char buffer[255];
00245 sprintf(buffer, "%d: deleting (gfx #%d, sprite #%d, pallete #%d)", sm->screen, gfxID, spriteID, palleteID);
00246 macros::debugMessage(className, buffer);
00247 #endif
00248
00249 PA_StopSpriteAnim(sm->screen, getSpriteID());
00250 PA_SetSpriteXY(sm->screen, getSpriteID(), OFFX, OFFY);
00251
00252
00253 if (!sm->isResetting())
00254 {
00255 if (bNeedsGFXCleanup)
00256 PA_DeleteGfx(sm->screen, getGFXid());
00257 if (hasGraphics())
00258 sm->removeSprite(getSpriteID());
00259
00260
00261
00262
00263 #ifdef __MDDEBUG
00264 memset(buffer, 0, 255);
00265 sprintf(buffer, "%d: clearChildren", sm->screen);
00266 macros::debugMessage(className, buffer);
00267 #endif
00268
00269 if (childSprite != NULL)
00270 childSprite->destroy();
00271 childSprite = NULL;
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 }
00292
00293 #ifdef __MDDEBUG
00294 memset(buffer, 0, 255);
00295 sprintf(buffer, "%d: deleteSprite[end]", sm->screen);
00296 macros::debugMessage(className, buffer);
00297 #endif
00298 }
00299
00305 bool spriteObject::hasGraphics() const
00306 {
00307 return (sm->isSprite(spriteID));
00308 }
00309
00316 void spriteObject::updateSprite()
00317 {
00318 if (hasGraphics())
00319 {
00320 if (isAttachment && parentSprite != NULL)
00321 setFrame(parentSprite->getFrame());
00322 else if (arbitraryAnim != 0)
00323 {
00324 if (arbitraryTimeCounter == 0)
00325 {
00326 frame = arbFrames[arbitraryFrameCounter];
00327 ++arbitraryFrameCounter;
00328 }
00329 ++arbitraryTimeCounter;
00330 arbitraryTimeCounter %= arbitrarySpeed;
00331 if (arbitraryFrameCounter == arbFrames.size())
00332 {
00333 if (arbitraryAnim != 2)
00334 arbitraryAnim = 0;
00335 else
00336 arbitraryFrameCounter = 0;
00337 }
00338 }
00339
00340 if (oldFrame != frame)
00341 {
00342 PA_SetSpriteAnim(sm->screen, spriteID, frame);
00343 oldFrame = frame;
00344 }
00345 }
00346
00347 if (staticSprite)
00348 return;
00349 x += vx;
00350 y += vy;
00351
00352 if (hasGraphics())
00353 {
00354 if (parentSprite != NULL)
00355 {
00356
00357
00358 setFlipped(parentSprite->flippedh, parentSprite->flippedv);
00359 s16 extrax = 0, extray = 0;
00360 for (spriteObject *i = this; i != NULL; i = i->parentSprite)
00361 {
00362 if (i->parentSprite == NULL)
00363 {
00364 extrax += i->getx();
00365 extray += i->gety();
00366 } else {
00367 extrax += (i->parentSprite->flippedh ? i->getx()*-1 : i->getx());
00368 extray += (i->parentSprite->flippedv ? i->gety()*-1 : i->gety());
00369 }
00370 }
00371 PA_SetSpriteXY(sm->screen, spriteID, extrax-centerx, extray-centery);
00372 }
00373 else if (x != oldx || y != oldy)
00374 {
00375 PA_SetSpriteXY(sm->screen, spriteID, (x>>8), (y>>8));
00376 oldx = x;
00377 oldy = y;
00378 }
00379
00380 if (UPDATEDflip)
00381 {
00382 PA_SetSpriteHflip(sm->screen, spriteID, flippedh);
00383 PA_SetSpriteVflip(sm->screen, spriteID, flippedv);
00384 UPDATEDflip = false;
00385 }
00386
00387 if (UPDATEDlayer)
00388 {
00389 PA_SetSpritePrio(sm->screen, spriteID, layer);
00390 UPDATEDlayer = false;
00391 }
00392
00393 if (bRotating && rotSetID != -1)
00394 PA_SetRotsetNoZoom(sm->screen, rotSetID, rotAngle);
00395 }
00396 if (framesToLive > -1)
00397 framesToLive--;
00398 }
00399
00410 void spriteObject::checkCollisions(u8 indexToCheckFrom)
00411 {
00412 if (!checkCollision)
00413 return;
00414 for (vector<spriteObject*>::iterator it = sm->gameSprites.begin()+indexToCheckFrom; it != sm->gameSprites.end(); ++it)
00415 {
00416 bool collides = isColliding(*it);
00417
00418 if (collides)
00419 collidingWith(*it);
00420 else if (!collides && ignoreUntilUntouched == *it)
00421 {
00422 ignoreUntilUntouched = NULL;
00423 }
00424 }
00425 }
00426
00435 void spriteObject::setTransparency(u8 transLevel)
00436 {
00437 transLevel %= 15;
00438 PA_SetSpriteMode(sm->screen, spriteID, 1);
00439 sm->setAlpha(transLevel);
00440 }
00441
00446 void spriteObject::turnAround()
00447 {
00448
00449 vx > 0 ? --x : ++x;
00450
00451 vx *= -1;
00452 setFlipped(!flippedh, flippedv);
00453 }
00454
00461 bool spriteObject::isFacing(const spriteObject *other) const
00462 {
00463 return ((getx() > other->getx() && flippedh) ||
00464 (getx() < other->getx() && !flippedh));
00465 }
00475 bool spriteObject::inHorizPlaneOf(const spriteObject *other) const
00476 {
00477 if (isOver(other)) return false;
00478 if (isUnder(other)) return false;
00479 return true;
00480 }
00490 bool spriteObject::inVertPlaneOf(const spriteObject *other) const
00491 {
00492 if (getRight() < other->getLeft()) return false;
00493 if (getLeft() > other->getRight()) return false;
00494 return true;
00495 }
00502 bool spriteObject::isUnder(const spriteObject *other) const
00503 {
00504 return (getTop() > other->getBottom());
00505 }
00512 bool spriteObject::isOver(const spriteObject *other) const
00513 {
00514 return (getBottom() < other->getTop());
00515 }
00525 bool spriteObject::isStandingOn(const spriteObject *other) const
00526 {
00527 if (other == this)
00528 return false;
00529
00530 if (other->isBaseable() && inVertPlaneOf(other) && getBottom() == other->getTop() && vy >= 0)
00531 return isColliding(other, true);
00532 return false;
00533 }
00534
00542 bool spriteObject::isBaseable() const
00543 {
00544 return (collision & COL_BASEABLE);
00545 }
00546
00559 bool spriteObject::isColliding(const spriteObject *other, bool checkReverse) const
00560 {
00561 if (other == this || other == ignoreUntilUntouched)
00562 return false;
00563
00564 if (collision == COL_NONE)
00565 return false;
00566
00567 if (collision <= COL_DOWNBASEABLE && other->getBottom() != getTop())
00568 return false;
00569
00570 if (collision == COL_CENTERPOINT &&
00571 (getx() < other->getRight() && getx() > other->getLeft() &&
00572 gety() < other->getBottom() && gety() > other->getTop()))
00573 return (!checkReverse || other->isColliding(this, false));
00574
00575 if (!inHorizPlaneOf(other)) return false;
00576 if (!inVertPlaneOf(other)) return false;
00577
00578 if (collision != COL_PIXELPERFECT)
00579 return (!checkReverse || other->isColliding(this, false));
00580
00587 s32 over_bottom, over_top, over_left, over_right, over_width, over_height;
00588 s32 startSearch1, startSearch2, startSearchOffset1, startSearchOffset2;
00589
00590
00591 if (getBottom() > other->getBottom())
00592 over_bottom = other->getBottom();
00593 else
00594 over_bottom = getBottom();
00595 if (getTop() < other->getTop())
00596 over_top = other->getTop();
00597 else
00598 over_top = getTop();
00599 if (getRight() > other->getRight())
00600 over_right = other->getRight();
00601 else
00602 over_right = getRight();
00603 if (getLeft() < other->getLeft())
00604 over_left = other->getLeft();
00605 else
00606 over_left = getLeft();
00607
00608 over_width = over_right - over_left;
00609 over_height = over_bottom - over_top;
00610
00611
00612 startSearchOffset1 = frame * centerx*2 * centery*2;
00613 startSearchOffset2 = other->frame * other->centerx*2 * other->centery*2;
00614
00615
00616
00617 u16* myGFX = PA_SpriteAnimP[sm->screen][getGFXid()];
00618 u16* otherGFX = PA_SpriteAnimP[other->sm->screen][other->getGFXid()];
00619
00620
00621
00622
00623 startSearch1 = startSearchOffset1 + (over_top - (y>>8) * centerx*2) + (over_left - (x>>8));
00624 startSearch2 = startSearchOffset2 + (over_top - (other->y>>8) * other->centerx*2) + (over_left - (other->x>>8));
00625
00626 for (int i=0; i < over_height; ++i)
00627 {
00628 for (int j=0; j < over_width; ++j)
00629 {
00630 if (myGFX[startSearch1] > 0 && otherGFX[startSearch2] > 0)
00631 return (!checkReverse || other->isColliding(this, false));
00632 ++startSearch1;
00633 ++startSearch2;
00634 }
00635 startSearch1 += (centerx*2 - over_width);
00636 startSearch2 += (other->centerx*2 - over_width);
00637 }
00638
00639 return false;
00640 }
00641
00648 void spriteObject::setFlipped(bool fh, bool fv)
00649 {
00650 if (bRotating && rotSetID != -1)
00651 return;
00652
00653 flippedh = fh;
00654 flippedv = fv;
00655 if (oldFliph != flippedh)
00656 {
00657 swapHBounds();
00658 oldFliph = flippedh;
00659 }
00660 if (oldFlipv != flippedv)
00661 {
00662 swapVBounds();
00663 oldFlipv = flippedv;
00664 }
00665 UPDATEDflip = true;
00666 }
00667
00668 #ifdef __WITHSOUND
00669
00678 void spriteObject::playSound(const u8 *sound, const u32 *size, bool repeat, u8 vol)
00679 {
00680 stopSound();
00681 setSoundChannel(sm->playSound(sound, size, repeat, vol));
00682 #ifdef __MDDEBUG
00683 char buffer[255];
00684 sprintf(buffer, "%d: sound playing (channel %d, raw)", sm->screen, soundChannel);
00685 macros::debugMessage(className, buffer);
00686 #endif
00687 }
00688
00697 void spriteObject::playSound(spriteManager::soundData *sound, bool repeat, u8 vol)
00698 {
00699 stopSound();
00700 setSoundChannel(sm->playSound(sound->data, sound->size, repeat, vol));
00701 #ifdef __MDDEBUG
00702 char buffer[255];
00703 sprintf(buffer, "%d: sound playing (channel %d, soundData)", sm->screen, soundChannel);
00704 macros::debugMessage(className, buffer);
00705 #endif
00706 }
00707 #endif
00708
00719 void spriteObject::setParent(spriteObject *other)
00720 {
00721 parentSprite = other;
00722 }
00723
00736 void spriteObject::addChild(spriteObject *other)
00737 {
00738 if (other != NULL)
00739 {
00740 childSprite = other;
00741
00742 other->setParent(this);
00743 }
00744 #ifdef __MDDEBUG
00745 else
00746 macros::debugMessage(ERRTEXT, "NULL childSprite added", ERRORPOS);
00747 #endif
00748 }
00749
00756 bool spriteObject::removeChild()
00757 {
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776 childSprite = NULL;
00777 return true;
00778 }