diff options
author | Gregory Montoir | 2003-10-01 20:23:29 +0000 |
---|---|---|
committer | Gregory Montoir | 2003-10-01 20:23:29 +0000 |
commit | 9c301608daaebab809fcffe900d1e77dca6b519f (patch) | |
tree | 7e0fde04969a79cab2d2e77bd1a33ac22e4a5f2f | |
parent | e78b1aeb44ea222b0d4f32c404cc4480bad9d51c (diff) | |
download | scummvm-rg350-9c301608daaebab809fcffe900d1e77dca6b519f.tar.gz scummvm-rg350-9c301608daaebab809fcffe900d1e77dca6b519f.tar.bz2 scummvm-rg350-9c301608daaebab809fcffe900d1e77dca6b519f.zip |
added Bob functions to Graphics class
svn-id: r10528
-rw-r--r-- | queen/graphics.cpp | 419 | ||||
-rw-r--r-- | queen/graphics.h | 105 |
2 files changed, 503 insertions, 21 deletions
diff --git a/queen/graphics.cpp b/queen/graphics.cpp index cdf8b48b70..6cf9a82371 100644 --- a/queen/graphics.cpp +++ b/queen/graphics.cpp @@ -21,11 +21,14 @@ #include "queen/graphics.h" + QueenGraphics::QueenGraphics(QueenResource *resource) :_resource(resource) { memset(_frames, 0, sizeof(_frames)); - memset(_banks, 0, sizeof(_banks)); + memset(_banks, 0, sizeof(_banks)); + memset(_sortedBobs, 0, sizeof(_sortedBobs)); + } @@ -56,25 +59,27 @@ void QueenGraphics::bankLoad(const char *bankname, uint32 bankslot) { debug(5, "Loaded bank '%s' in slot %d, %d entries", bankname, bankslot, entries); } + void QueenGraphics::bankUnpack(uint32 srcframe, uint32 dstframe, uint32 bankslot) { uint8 *p = _banks[bankslot].data + _banks[bankslot].indexes[srcframe]; - ObjectFrame *pof = &_frames[dstframe]; - delete[] pof->data; + BobFrame *pbf = &_frames[dstframe]; + delete[] pbf->data; - pof->width = READ_LE_UINT16(p + 0); - pof->height = READ_LE_UINT16(p + 2); - pof->xhotspot = READ_LE_UINT16(p + 4); - pof->yhotspot = READ_LE_UINT16(p + 6); + pbf->width = READ_LE_UINT16(p + 0); + pbf->height = READ_LE_UINT16(p + 2); + pbf->xhotspot = READ_LE_UINT16(p + 4); + pbf->yhotspot = READ_LE_UINT16(p + 6); - uint32 size = pof->width * pof->height; - pof->data = new uint8[ size ]; - memcpy(pof->data, p, size); + uint32 size = pbf->width * pbf->height; + pbf->data = new uint8[ size ]; + memcpy(pbf->data, p, size); debug(5, "Unpacked frame %d from bank slot %d to frame slot %d", srcframe, bankslot, dstframe); } + void QueenGraphics::bankOverpack(uint32 srcframe, uint32 dstframe, uint32 bankslot) { uint8 *p = _banks[bankslot].data + _banks[bankslot].indexes[srcframe]; @@ -93,6 +98,7 @@ void QueenGraphics::bankOverpack(uint32 srcframe, uint32 dstframe, uint32 banksl debug(5, "Overpacked frame %d from bank slot %d to frame slot %d", srcframe, bankslot, dstframe); } + void QueenGraphics::bankErase(uint32 bankslot) { delete[] _banks[bankslot].data; @@ -101,3 +107,396 @@ void QueenGraphics::bankErase(uint32 bankslot) { debug(5, "Erased bank in slot %d", bankslot); } + +void QueenGraphics::bobAnimString(uint32 bobnum, uint8* animBuf) { + + BobSlot *pbs = &_bobs[bobnum]; + pbs->active = true; + pbs->animating = true; + pbs->anim.string.buffer = animBuf; + pbs->anim.string.curPos = animBuf; + pbs->frameNum = READ_LE_UINT16(animBuf); + pbs->anim.speed = READ_LE_UINT16(animBuf + 2) / 4; +} + + +void QueenGraphics::bobAnimNormal(uint32 bobnum, uint16 firstFrame, uint16 lastFrame, uint16 speed, bool rebound, bool xflip) { + + BobSlot *pbs = &_bobs[bobnum]; + pbs->active = true; + pbs->animating = true; + pbs->frameNum = firstFrame; + pbs->anim.speed = speed; + pbs->anim.speedBak = speed; + pbs->anim.string.buffer = NULL; + pbs->anim.normal.firstFrame = firstFrame; + pbs->anim.normal.lastFrame = lastFrame; + pbs->anim.normal.rebound = rebound; + pbs->frameDir = 1; + pbs->xflip = xflip; +} + + +void QueenGraphics::bobMove(uint32 bobnum, uint16 endx, uint16 endy, int16 speed) { + + BobSlot *pbs = &_bobs[bobnum]; + + pbs->active = true; + pbs->moving = true; + + pbs->endx = endx; + pbs->endy = endy; + + // FIXME: can speed be negative or =0 ? the original sources does the check + pbs->speed = (speed < 1) ? 1 : speed; + + int16 dx = endx - pbs->x; + if (dx < 0) { + pbs->dx = -dx; + pbs->xdir = -1; + } + else { + pbs->dx = dx; + pbs->xdir = 1; + } + int16 dy = endy - pbs->y; + if (dy < 0) { + pbs->dy = -dy; + pbs->ydir = -1; + } + else { + pbs->dy = dy; + pbs->ydir = 1; + } + + if (pbs->dx > pbs->dy) { + pbs->total = pbs->dy / 2; + pbs->xmajor = true; + } + else { + pbs->total = pbs->dx / 2; + pbs->xmajor = false; + } + + // move one step along line to avoid glitching + pbs->moveOneStep(); +} + + +void BobSlot::moveOneStep() { + + if(xmajor) { + if(x == endx) { + y = endy; + moving = false; + } + else { + x += xdir; + total += dy; + if(total > dx) { + y += ydir; + total -= dx; + } + } + } + else { + if(y == endy) { + x = endx; + moving = false; + } + else { + y += ydir; + total += dx; + if(total > dy) { + x += xdir; + total -= dy; + } + } + } +} + + +void BobSlot::animOneStep() { + + if (anim.string.buffer != NULL) { + --anim.speed; + if(anim.speed == 0) { + anim.string.curPos += 4; + uint16 nextFrame = READ_LE_UINT16(anim.string.curPos); + if (nextFrame == 0) { + anim.string.curPos = anim.string.buffer; + frameNum = READ_LE_UINT16(anim.string.curPos); + } + else { + frameNum = nextFrame; + } + anim.speed = READ_LE_UINT16(anim.string.curPos + 2) / 4; + + // FIXME: handle that when QueenSound class is ready + // play memory sfx and move on to next frame + if(frameNum > 500) { + frameNum -= 500; + // _sound->sfxplay(NULLstr); + } + } + } + else { + // normal looping animation + --anim.speed; + if(anim.speed == 0) { + anim.speed = anim.speedBak; + + uint16 nextFrame = frameNum + frameDir; + if (nextFrame > anim.normal.lastFrame || nextFrame < anim.normal.firstFrame) { + if (anim.normal.rebound) { + frameDir *= -1; + } + else { + frameNum = anim.normal.lastFrame - 1; + } + frameNum += frameDir; + } + } + } +} + + +void QueenGraphics::bobDraw(uint32 bobnum, uint16 x, uint16 y, uint16 scale, bool xflip, const Box& box) { + + uint16 w, h; + uint8 *src; + + BobFrame *pbf = &_frames[bobnum]; + if(scale >= 0 && scale < 100) { + bobShrink(pbf, scale); + src = _shrinkBuffer.data; + w = _shrinkBuffer.width; + h = _shrinkBuffer.height; + } + else { + src = pbf->data; + w = pbf->width; + h = pbf->height; + } + + if(w != 0 && h != 0 && box.intersects(x, y, w, h)) { + + uint16 x_skip = 0; + uint16 y_skip = 0; + uint16 w_new = w; + uint16 h_new = h; + + // compute bounding box intersection with frame + if (x < box.x1) { + x_skip = box.x1 - x; + w_new -= x_skip; + x = box.x1; + } + + if (y < box.y1) { + y_skip = box.y1 - y; + h_new -= y_skip; + y = box.y1; + } + + if (x + w_new > box.x2 + 1) { + w_new = box.x2 - x + 1; + } + + if (y + h_new > box.y2 + 1) { + h_new = box.y2 - y + 1; + } + + uint16 j; + for (j = 0; j < h_new; ++j) { + memset(_ulines[y + j], 2, w_new / 16); + } + + src += w * y_skip; + if (!xflip) { + src += x_skip; +// _display->blit(hidden, x, y, 320, src, w_new, h_new, w, xflip, true); + } + else { + src += w - w_new - x_skip; + x += w_new - 1; +// _display->blit(hidden, x, y, 320, src, x_new, h_new, w, xflip, true); + } + } + +} + + +void QueenGraphics::bobDrawInventoryItem(uint32 bobnum, uint16 x, uint16 y) { + if (bobnum == 0) { + // clear panel area + uint8 *p = _panel + y * 320 + x; + for(uint32 j = 0; j < 32; ++j) { + for(uint32 i = 0; i < 32; ++i) { + *p++ = INK_BG_PANEL; + } + p += 320 - 32; + } + } + else { + BobFrame *pbf = &_frames[bobnum]; +// _display->blit(panel, x, y, 320, pbf->data, pbf->width, pbf->height, false, false); + } +} + + +void QueenGraphics::bobPaste(uint32 bobnum, uint16 x, uint16 y) { + + BobFrame *pbf = &_frames[bobnum]; +// _display->blit(backdrop, x, y, 640, pbf->data, pbf->width, pbf->height, pbf->width, false, true); + frameErase(bobnum); +} + + +void QueenGraphics::bobShrink(const BobFrame* pbf, uint16 percentage) { + + // computing new size, rounding to upper value + uint16 new_w = (pbf->width * percentage + 50) / 100; + uint16 new_h = (pbf->height * percentage + 50) / 100; + + if (new_w != 0 && new_h != 0) { + + _shrinkBuffer.width = new_w; + _shrinkBuffer.height = new_h; + + uint32 shrinker = (100 << 0x10) / percentage; + uint16 x_scale = shrinker >> 0x10; + uint16 y_scale = x_scale * pbf->width; + shrinker &= 0xFFFF; + + uint8* src = pbf->data; + uint8* dst = _shrinkBuffer.data; + + for (uint32 y_count = 0; new_h != 0; --new_h) { + + uint8 *p = src; + for (uint32 x_count = 0; new_w != 0; --new_w) { + *dst++ = *p; + p += x_scale; + x_count += shrinker; + if (x_count > 0xFFFF) { + ++p; + x_count &= 0xFFFF; + } + } + + src += y_scale; + y_count += shrinker; + if (y_count > 0xFFFF) { + src += pbf->width; + y_count &= 0xFFFF; + } + } + } +} + + +void QueenGraphics::bobClear(uint32 bobnum) { + + BobSlot *pbs = &_bobs[bobnum]; + + pbs->active = 0; + pbs->xflip = false; + pbs->anim.string.buffer = NULL; + pbs->moving = false; + pbs->scale = 100; + pbs->box.x1 = 0; + pbs->box.y1 = 0; + pbs->box.y1 = 319; + pbs->box.y2 = (bobnum == 16) ? 199 : 149; // FIXME: does bob number 16 really used ? +} + + +void QueenGraphics::bobSortAll() { + + int32 _sorted = 0; + + // animate/move the bobs + for (int32 i = 0; i < ARRAYSIZE(_bobs); ++i) { + + BobSlot *pbs = &_bobs[i]; + if (pbs->active) { + _sortedBobs[_sorted] = pbs; + ++_sorted; + + if (pbs->animating) { + pbs->animOneStep(); + } + if (pbs->moving) { + for (uint32 j = 0; pbs->moving && j < pbs->speed; ++j) { + pbs->moveOneStep(); + } + } + } + } + + _sortedBobs[_sorted] = 0; + + // bubble sort the bobs + for (int32 index = 0; index < _sorted - 1; ++index) { + int32 smallest = index; + for (int32 compare = index + 1; compare <= _sorted - 1; ++compare) { + if (_sortedBobs[compare]->y < _sortedBobs[compare]->y) { + smallest = compare; + } + } + if (index != smallest) { + SWAP(_sortedBobs[index], _sortedBobs[smallest]); + } + } + +} + + +void QueenGraphics::bobDrawAll() { + + for (BobSlot *pbs = _sortedBobs[0]; pbs; ++pbs) { + if (pbs->active) { + + BobFrame *pbf = &_frames[ pbs->frameNum ]; + uint16 xh, yh, x, y; + + xh = pbf->xhotspot; + yh = pbf->yhotspot; + + if (pbs->xflip) { + xh = pbf->width - xh; + } + + // adjusts hot spots when object is scaled + if (pbs->scale != 100) { + xh = (xh * pbs->scale) / 100; + yh = (yh * pbs->scale) / 100; + } + + // adjusts position to hot-spot and screen scroll + x = pbs->x - xh; // - _display->scrollx; + y = pbs->y - yh; + + bobDraw(pbs->frameNum, x, y, pbs->scale, pbs->xflip, pbs->box); + } + } +} + + +void QueenGraphics::bobClearAll() { + + for(int32 i = 0; i < ARRAYSIZE(_bobs); ++i) { + bobClear(i); + } +} + + +void QueenGraphics::frameErase(uint32 fslot) { + + BobFrame *pbf = &_frames[fslot]; + pbf->width = 0; + pbf->height = 0; + delete[] pbf->data; + +} diff --git a/queen/graphics.h b/queen/graphics.h index 0cd8ea95fb..7091224878 100644 --- a/queen/graphics.h +++ b/queen/graphics.h @@ -28,12 +28,69 @@ #define MAX_BANK_SIZE 110 #define MAX_FRAMES_NUMBER 256 #define MAX_BANKS_NUMBER 18 +#define MAX_BOBS_NUMBER 64 -struct ObjectFrame { - uint16 width, height; - uint16 xhotspot, yhotspot; - uint8 *data; +struct BobFrame { + uint16 width, height; + uint16 xhotspot, yhotspot; + uint8 *data; +}; + +// FIXME: share that with logic.h (ObjectData) ? +struct Box { + uint16 x1, y1, x2, y2; + + bool intersects(uint16 x, uint16 y, uint16 w, uint16 h) const { + return (x + w > x1) && (y + h > y1) && (x <= x2) && (y <= y2); + } +}; + + +struct BobSlot { + bool active; + uint16 x, y; //! current position + Box box; //! bounding box + bool xflip; + uint16 scale; //! shrinking percentage + uint16 frameNum; //! associated BobFrame + uint8 frameDir; //! 'direction' for the next frame (-1, 1) + + //! animation stuff + bool animating; + struct { + uint16 speed, speedBak; + + //! string based animation + struct { + uint8* buffer; + uint8* curPos; + } string; + + //! normal moving animation + struct { + bool rebound; + uint16 firstFrame, lastFrame; + } normal; + + } anim; + + bool moving; + uint16 speed; //! moving speed + bool xmajor; //! move along x axis instead of y + int8 xdir, ydir; //! moving direction + uint16 endx, endy; //! destination point + uint16 dx, dy; + uint16 total; + + void moveOneStep(); + void animOneStep(); +}; + + +//! Inks indexes +enum { + INK_BG_PANEL = 0xE2 }; @@ -42,11 +99,26 @@ public: QueenGraphics(QueenResource *resource); - void bankLoad(const char *bankname, uint32 bankslot); - void bankUnpack(uint32 srcframe, uint32 dstframe, uint32 bankslot); - void bankOverpack(uint32 srcframe, uint32 dstframe, uint32 bankslot); - void bankErase(uint32 bankslot); - + void bankLoad(const char *bankname, uint32 bankslot); // loadbank() + void bankUnpack(uint32 srcframe, uint32 dstframe, uint32 bankslot); // unpackbank() + void bankOverpack(uint32 srcframe, uint32 dstframe, uint32 bankslot); // overpackbank() + void bankErase(uint32 bankslot); // erase() + + void bobAnimString(uint32 bobnum, uint8* animBuf); // stringanim() + void bobAnimNormal(uint32 bobnum, uint16 firstFrame, uint16 lastFrame, uint16 speed, bool rebound, bool xflip); // makeanim() + void bobMove(uint32 bobnum, uint16 endx, uint16 endy, int16 speed); // movebob() + void bobDraw(uint32 bobnum, uint16 x, uint16 y, uint16 scale, bool xflip, const Box& box); // bob() + void bobDrawInventoryItem(uint32 bobnum, uint16 x, uint16 y); // invbob() + void bobPaste(uint32 bobnum, uint16 x, uint16 y); // bobpaste() + void bobShrink(const BobFrame* pbf, uint16 percentage); // shrinkbob() + void bobClear(uint32 bobnum); // clearbob() + void bobSortAll(); // sortbobs() + void bobDrawAll(); // drawbobs() + void bobClearAll(); // clearallbobs() + + void frameErase(uint32 fslot); + + private: struct PackedBank { @@ -54,8 +126,19 @@ private: uint8 *data; }; - ObjectFrame _frames[MAX_FRAMES_NUMBER]; - PackedBank _banks[MAX_BANKS_NUMBER]; + struct ShrunkBobFrame { + uint16 width; + uint16 height; + uint8 data[60000]; // FIXME: original buffer size, maybe it can be smaller + }; + + BobFrame _frames[MAX_FRAMES_NUMBER]; //! unbanked bob frames + PackedBank _banks[MAX_BANKS_NUMBER]; //! banked bob frames + BobSlot _bobs[MAX_BOBS_NUMBER]; + BobSlot* _sortedBobs[MAX_BOBS_NUMBER + 1]; //! bobs displayed + ShrunkBobFrame _shrinkBuffer; + uint8 _ulines[201][20]; + uint8 _panel[320 * 50]; // FIXME: rather in QueenDisplay ? QueenResource *_resource; |