aboutsummaryrefslogtreecommitdiff
path: root/engines/gob/aniobject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/gob/aniobject.cpp')
-rw-r--r--engines/gob/aniobject.cpp156
1 files changed, 114 insertions, 42 deletions
diff --git a/engines/gob/aniobject.cpp b/engines/gob/aniobject.cpp
index 0ca850d1fb..7e3668a0ce 100644
--- a/engines/gob/aniobject.cpp
+++ b/engines/gob/aniobject.cpp
@@ -22,20 +22,26 @@
#include "gob/surface.h"
#include "gob/anifile.h"
+#include "gob/cmpfile.h"
#include "gob/aniobject.h"
namespace Gob {
-ANIObject::ANIObject(const ANIFile &ani) : _ani(&ani),
- _visible(false), _paused(false), _mode(kModeContinuous),
- _x(0), _y(0), _background(0), _drawn(false) {
+ANIObject::ANIObject(const ANIFile &ani) : _ani(&ani), _cmp(0),
+ _visible(false), _paused(false), _mode(kModeContinuous), _x(0), _y(0) {
+
+ setAnimation(0);
+ setPosition();
+}
+
+ANIObject::ANIObject(const CMPFile &cmp) : _ani(0), _cmp(&cmp),
+ _visible(false), _paused(false), _mode(kModeContinuous), _x(0), _y(0) {
setAnimation(0);
setPosition();
}
ANIObject::~ANIObject() {
- delete _background;
}
void ANIObject::setVisible(bool visible) {
@@ -67,7 +73,15 @@ void ANIObject::rewind() {
_frame = 0;
}
+void ANIObject::setFrame(uint16 frame) {
+ _frame = frame % _ani->getAnimationInfo(_animation).frameCount;
+}
+
void ANIObject::setPosition() {
+ // CMP "animations" have no default position
+ if (_cmp)
+ return;
+
if (_animation >= _ani->getAnimationCount())
return;
@@ -87,7 +101,13 @@ void ANIObject::getPosition(int16 &x, int16 &y) const {
y = _y;
}
-void ANIObject::getFramePosition(int16 &x, int16 &y) const {
+void ANIObject::getFramePosition(int16 &x, int16 &y, uint16 n) const {
+ // CMP "animations" have no specific frame positions
+ if (_cmp) {
+ getPosition(x, y);
+ return;
+ }
+
if (_animation >= _ani->getAnimationCount())
return;
@@ -95,11 +115,31 @@ void ANIObject::getFramePosition(int16 &x, int16 &y) const {
if (_frame >= animation.frameCount)
return;
- x = _x + animation.frameAreas[_frame].left;
- y = _y + animation.frameAreas[_frame].top;
+ // If we're paused, we don't advance any frames
+ if (_paused)
+ n = 0;
+
+ // Number of cycles run through after n frames
+ uint16 cycles = (_frame + n) / animation.frameCount;
+ // Frame position after n frames
+ uint16 frame = (_frame + n) % animation.frameCount;
+
+ // Only doing one cycle?
+ if (_mode == kModeOnce)
+ cycles = MAX<uint16>(cycles, 1);
+
+ x = _x + animation.frameAreas[frame].left + cycles * animation.deltaX;
+ y = _y + animation.frameAreas[frame].top + cycles * animation.deltaY;
}
-void ANIObject::getFrameSize(int16 &width, int16 &height) const {
+void ANIObject::getFrameSize(int16 &width, int16 &height, uint16 n) const {
+ if (_cmp) {
+ width = _cmp->getWidth (_animation);
+ height = _cmp->getHeight(_animation);
+
+ return;
+ }
+
if (_animation >= _ani->getAnimationCount())
return;
@@ -107,8 +147,15 @@ void ANIObject::getFrameSize(int16 &width, int16 &height) const {
if (_frame >= animation.frameCount)
return;
- width = animation.frameAreas[_frame].right - animation.frameAreas[_frame].left + 1;
- height = animation.frameAreas[_frame].bottom - animation.frameAreas[_frame].top + 1;
+ // If we're paused, we don't advance any frames
+ if (_paused)
+ n = 0;
+
+ // Frame position after n frames
+ uint16 frame = (_frame + n) % animation.frameCount;
+
+ width = animation.frameAreas[frame].right - animation.frameAreas[frame].left + 1;
+ height = animation.frameAreas[frame].bottom - animation.frameAreas[frame].top + 1;
}
bool ANIObject::isIn(int16 x, int16 y) const {
@@ -141,67 +188,88 @@ bool ANIObject::isIn(const ANIObject &obj) const {
obj.isIn(frameX + frameWidth - 1, frameY + frameHeight - 1);
}
-void ANIObject::draw(Surface &dest, int16 &left, int16 &top,
+bool ANIObject::draw(Surface &dest, int16 &left, int16 &top,
int16 &right, int16 &bottom) {
if (!_visible)
- return;
+ return false;
+
+ if (_cmp)
+ return drawCMP(dest, left, top, right, bottom);
+ else if (_ani)
+ return drawANI(dest, left, top, right, bottom);
+
+ return false;
+}
- if (!_background) {
+bool ANIObject::drawCMP(Surface &dest, int16 &left, int16 &top,
+ int16 &right, int16 &bottom) {
+
+ if (!hasBuffer()) {
+ uint16 width, height;
+
+ _cmp->getMaxSize(width, height);
+
+ resizeBuffer(width, height);
+ }
+
+ left = _x;
+ top = _y;
+ right = _x + _cmp->getWidth (_animation) - 1;
+ bottom = _y + _cmp->getHeight(_animation) - 1;
+
+ if (!saveScreen(dest, left, top, right, bottom))
+ return false;
+
+ _cmp->draw(dest, _animation, _x, _y, 0);
+
+ return true;
+}
+
+bool ANIObject::drawANI(Surface &dest, int16 &left, int16 &top,
+ int16 &right, int16 &bottom) {
+
+ if (!hasBuffer()) {
uint16 width, height;
_ani->getMaxSize(width, height);
- _background = new Surface(width, height, dest.getBPP());
+ resizeBuffer(width, height);
}
const ANIFile::Animation &animation = _ani->getAnimationInfo(_animation);
if (_frame >= animation.frameCount)
- return;
+ return false;
const ANIFile::FrameArea &area = animation.frameAreas[_frame];
- _backgroundLeft = CLIP<int16>(area.left + _x, 0, dest.getWidth () - 1);
- _backgroundTop = CLIP<int16>(area.top + _y, 0, dest.getHeight() - 1);
- _backgroundRight = CLIP<int16>(area.right + _x, 0, dest.getWidth () - 1);
- _backgroundBottom = CLIP<int16>(area.bottom + _y, 0, dest.getHeight() - 1);
+ left = _x + area.left;
+ top = _y + area.top;
+ right = _x + area.right;
+ bottom = _y + area.bottom;
- _background->blit(dest, _backgroundLeft , _backgroundTop,
- _backgroundRight, _backgroundBottom, 0, 0);
+ if (!saveScreen(dest, left, top, right, bottom))
+ return false;
_ani->draw(dest, _animation, _frame, _x, _y);
- _drawn = true;
-
- left = _backgroundLeft;
- top = _backgroundTop;
- right = _backgroundRight;
- bottom = _backgroundBottom;
+ return true;
}
-void ANIObject::clear(Surface &dest, int16 &left, int16 &top,
+bool ANIObject::clear(Surface &dest, int16 &left, int16 &top,
int16 &right, int16 &bottom) {
- if (!_drawn)
- return;
-
- const int16 bgRight = _backgroundRight - _backgroundLeft;
- const int16 bgBottom = _backgroundBottom - _backgroundTop;
-
- dest.blit(*_background, 0, 0, bgRight, bgBottom, _backgroundLeft, _backgroundTop);
-
- _drawn = false;
-
- left = _backgroundLeft;
- top = _backgroundTop;
- right = _backgroundRight;
- bottom = _backgroundBottom;
+ return restoreScreen(dest, left, top, right, bottom);
}
void ANIObject::advance() {
if (_paused)
return;
+ // CMP "animations" have only one frame
+ if (_cmp)
+ return;
+
if (_animation >= _ani->getAnimationCount())
return;
@@ -229,6 +297,10 @@ uint16 ANIObject::getFrame() const {
}
bool ANIObject::lastFrame() const {
+ // CMP "animations" have only one frame
+ if (_cmp)
+ return true;
+
if (_animation >= _ani->getAnimationCount())
return true;