aboutsummaryrefslogtreecommitdiff
path: root/engines/draci
diff options
context:
space:
mode:
Diffstat (limited to 'engines/draci')
-rw-r--r--engines/draci/animation.cpp49
-rw-r--r--engines/draci/animation.h9
-rw-r--r--engines/draci/game.cpp10
-rw-r--r--engines/draci/walking.cpp3
4 files changed, 56 insertions, 15 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();
}
diff --git a/engines/draci/animation.h b/engines/draci/animation.h
index 473e875941..9fd5a87f97 100644
--- a/engines/draci/animation.h
+++ b/engines/draci/animation.h
@@ -28,6 +28,7 @@
#include "draci/sprite.h"
#include "draci/sound.h"
+#include "common/rect.h"
namespace Draci {
@@ -75,11 +76,14 @@ public:
void addFrame(Drawable *frame, const SoundSample *sample);
void replaceFrame(int i, Drawable *frame, const SoundSample *sample);
+ const Drawable *getConstCurrentFrame() const;
Drawable *getCurrentFrame();
Drawable *getFrame(int frameNum);
void setCurrentFrame(uint frame);
uint currentFrameNum() const { return _currentFrame; }
uint getFrameCount() const { return _frames.size(); }
+ void makeLastFrameRelative(int x, int y);
+ void clearShift();
bool isPlaying() const { return _playing; }
void setPlaying(bool playing);
@@ -93,7 +97,8 @@ public:
void setRelative(int relx, int rely);
int getRelativeX() const { return _displacement.relX; }
int getRelativeY() const { return _displacement.relY; }
- const Displacement &getDisplacement() const { return _displacement; }
+ const Displacement &getDisplacement() const { return _displacement; } // displacement of the whole animation
+ Displacement getCurrentFrameDisplacement() const; // displacement of the current frame (includes _shift)
int getIndex() const { return _index; }
void setIndex(int index) { _index = index; }
@@ -132,6 +137,7 @@ private:
uint _currentFrame;
uint _z;
+ Common::Point _shift; // partial sum of _relativeShifts from the beginning of the animation until the current frame
bool _hasChangedFrame;
Displacement _displacement;
@@ -144,6 +150,7 @@ private:
/** Array of frames of the animation. The animation object owns these pointers.
*/
Common::Array<Drawable *> _frames;
+ Common::Array<Common::Point> _relativeShifts;
/** Array of samples played during the animation. The animation
* object doesn't own these pointers, but they are stored in the
* cache.
diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp
index 15ec8028f4..ed5768fd42 100644
--- a/engines/draci/game.cpp
+++ b/engines/draci/game.cpp
@@ -1194,9 +1194,7 @@ int Game::loadAnimation(uint animNum, uint z) {
// into details.
animationReader.readByte();
const bool cyclic = animationReader.readByte();
-
- // FIXME: handle this properly
- animationReader.readByte(); // Relative field, not used
+ const bool relative = animationReader.readByte();
Animation *anim = _vm->_anims->addAnimation(animNum, z, false);
@@ -1216,7 +1214,8 @@ int Game::loadAnimation(uint animNum, uint z) {
// _spritesArchive is flushed when entering a room. All
// scripts in a room are responsible for loading their animations.
const BAFile *spriteFile = _vm->_spritesArchive->getFile(spriteNum);
- Sprite *sp = new Sprite(spriteFile->_data, spriteFile->_length, x, y, true);
+ Sprite *sp = new Sprite(spriteFile->_data, spriteFile->_length,
+ relative ? 0 : x, relative ? 0 : y, true);
// Some frames set the scaled dimensions to 0 even though other frames
// from the same animations have them set to normal values
@@ -1239,6 +1238,9 @@ int Game::loadAnimation(uint animNum, uint z) {
const SoundSample *sam = _vm->_soundsArchive->getSample(sample, freq);
anim->addFrame(sp, sam);
+ if (relative) {
+ anim->makeLastFrameRelative(x, y);
+ }
}
return animNum;
diff --git a/engines/draci/walking.cpp b/engines/draci/walking.cpp
index 4a0e65c9b3..9edffc6996 100644
--- a/engines/draci/walking.cpp
+++ b/engines/draci/walking.cpp
@@ -522,8 +522,9 @@ bool WalkingState::continueWalking() {
// We are walking in the middle of an edge. The animation phase has
// just changed. Update the position of the hero.
+ _position += 4; // TODO: compute shifts properly from the animation
Common::Point newPos = WalkingMap::interpolate(
- _path[_segment], _path[_segment+1], ++_position, _length);
+ _path[_segment], _path[_segment+1], _position, _length);
_vm->_game->setHeroPosition(newPos);
_vm->_game->positionAnimAsHero(anim);