diff options
Diffstat (limited to 'engines/draci')
-rw-r--r-- | engines/draci/animation.cpp | 49 | ||||
-rw-r--r-- | engines/draci/animation.h | 9 | ||||
-rw-r--r-- | engines/draci/game.cpp | 10 | ||||
-rw-r--r-- | engines/draci/walking.cpp | 3 |
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); |