aboutsummaryrefslogtreecommitdiff
path: root/engines/draci/animation.cpp
diff options
context:
space:
mode:
authorRobert Špalek2009-11-07 01:28:27 +0000
committerRobert Špalek2009-11-07 01:28:27 +0000
commit357d9989d4c6ae73e02a044b388f36069e093ce0 (patch)
tree06d8453b5babaa0c5a844ff0f31e56652276c665 /engines/draci/animation.cpp
parentfdad4e7b543af2debcc35492e46c979ab1dd8fec (diff)
downloadscummvm-rg350-357d9989d4c6ae73e02a044b388f36069e093ce0.tar.gz
scummvm-rg350-357d9989d4c6ae73e02a044b388f36069e093ce0.tar.bz2
scummvm-rg350-357d9989d4c6ae73e02a044b388f36069e093ce0.zip
Implemented relative animations.
In these animations, each sprite can specify a relative shift with respect to the previous sprite. Moving animations (such as walking of the dragon) are easily described in this framework. I have sort of hacked their support and it seems to work. The current walking code does not interact with the new code yet, but it will be easy to do. svn-id: r45712
Diffstat (limited to 'engines/draci/animation.cpp')
-rw-r--r--engines/draci/animation.cpp49
1 files changed, 40 insertions, 9 deletions
diff --git a/engines/draci/animation.cpp b/engines/draci/animation.cpp
index 674e2473df..9d56c89674 100644
--- a/engines/draci/animation.cpp
+++ b/engines/draci/animation.cpp
@@ -33,6 +33,7 @@ Animation::Animation(DraciEngine *vm, int index) : _vm(vm) {
_id = kUnused;
_index = index;
_z = 0;
+ clearShift();
_displacement = kNoDisplacement;
_playing = false;
_looping = false;
@@ -56,6 +57,13 @@ void Animation::setRelative(int relx, int rely) {
_displacement.relY = rely;
}
+Displacement Animation::getCurrentFrameDisplacement() const {
+ Displacement dis = _displacement;
+ dis.relX += (int) (dis.extraScaleX * _shift.x);
+ dis.relY += (int) (dis.extraScaleY * _shift.y);
+ return dis;
+}
+
void Animation::setLooping(bool looping) {
_looping = looping;
debugC(7, kDraciAnimationDebugLevel, "Setting looping to %d on animation %d",
@@ -67,8 +75,8 @@ void Animation::markDirtyRect(Surface *surface) const {
return;
// Fetch the current frame's rectangle
- Drawable *frame = _frames[_currentFrame];
- Common::Rect frameRect = frame->getRect(_displacement);
+ const Drawable *frame = getConstCurrentFrame();
+ Common::Rect frameRect = frame->getRect(getCurrentFrameDisplacement());
// Mark the rectangle dirty on the surface
surface->markDirtyRect(frameRect);
@@ -79,7 +87,7 @@ void Animation::nextFrame(bool force) {
if (getFrameCount() == 0 || !_playing)
return;
- Drawable *frame = _frames[_currentFrame];
+ const Drawable *frame = getConstCurrentFrame();
Surface *surface = _vm->_screen->getSurface();
if (force || (_tick + frame->getDelay() <= _vm->_system->getMillis())) {
@@ -92,7 +100,12 @@ void Animation::nextFrame(bool force) {
// Mark old frame dirty so it gets deleted
markDirtyRect(surface);
+ _shift.x += _relativeShifts[_currentFrame].x;
+ _shift.y += _relativeShifts[_currentFrame].y;
_currentFrame = nextFrameNum();
+ if (!_currentFrame) {
+ clearShift(); // TODO: don't do that, but rather let the animation fly away when needed.
+ }
_tick = _vm->_system->getMillis();
// Fetch new frame and mark it dirty
@@ -123,13 +136,15 @@ void Animation::drawFrame(Surface *surface) {
if (_frames.size() == 0 || !_playing)
return;
- const Drawable *frame = _frames[_currentFrame];
+ const Drawable *frame = getConstCurrentFrame();
if (_id == kOverlayImage) {
+ // No displacement or relative animations is supported.
frame->draw(surface, false, 0, 0);
} else {
- // Draw frame
- frame->drawReScaled(surface, false, _displacement);
+ // Draw frame: first shifted by the relative shift and then
+ // scaled/shifted by the given displacement.
+ frame->drawReScaled(surface, false, getCurrentFrameDisplacement());
}
const SoundSample *sample = _samples[_currentFrame];
@@ -164,6 +179,15 @@ void Animation::setScaleFactors(double scaleX, double scaleY) {
void Animation::addFrame(Drawable *frame, const SoundSample *sample) {
_frames.push_back(frame);
_samples.push_back(sample);
+ _relativeShifts.push_back(Common::Point(0, 0));
+}
+
+void Animation::makeLastFrameRelative(int x, int y) {
+ _relativeShifts.back() = Common::Point(x, y);
+}
+
+void Animation::clearShift() {
+ _shift = Common::Point(0, 0);
}
void Animation::replaceFrame(int i, Drawable *frame, const SoundSample *sample) {
@@ -171,6 +195,11 @@ void Animation::replaceFrame(int i, Drawable *frame, const SoundSample *sample)
_samples[i] = sample;
}
+const Drawable *Animation::getConstCurrentFrame() const {
+ // If there are no frames stored, return NULL
+ return _frames.size() > 0 ? _frames[_currentFrame] : NULL;
+}
+
Drawable *Animation::getCurrentFrame() {
// If there are no frames stored, return NULL
return _frames.size() > 0 ? _frames[_currentFrame] : NULL;
@@ -202,6 +231,7 @@ void Animation::deleteFrames() {
delete _frames[i];
_frames.pop_back();
}
+ _relativeShifts.clear();
_samples.clear();
}
@@ -280,6 +310,7 @@ void AnimationManager::stop(int id) {
// Reset the animation to the beginning
anim->setCurrentFrame(0);
+ anim->clearShift();
debugC(3, kDraciAnimationDebugLevel, "Stopping animation %d...", id);
}
@@ -499,19 +530,19 @@ int AnimationManager::getTopAnimationID(int x, int y) const {
continue;
}
- const Drawable *frame = anim->getCurrentFrame();
+ const Drawable *frame = anim->getConstCurrentFrame();
if (frame == NULL) {
continue;
}
- if (frame->getRect(anim->getDisplacement()).contains(x, y)) {
+ if (frame->getRect(anim->getCurrentFrameDisplacement()).contains(x, y)) {
if (frame->getType() == kDrawableText) {
retval = anim->getID();
} else if (frame->getType() == kDrawableSprite &&
- reinterpret_cast<const Sprite *>(frame)->getPixel(x, y, anim->getDisplacement()) != transparent) {
+ reinterpret_cast<const Sprite *>(frame)->getPixel(x, y, anim->getCurrentFrameDisplacement()) != transparent) {
retval = anim->getID();
}