[Scummvm-cvs-logs] SF.net SVN: scummvm:[45712] scummvm/trunk/engines/draci
spalek at users.sourceforge.net
spalek at users.sourceforge.net
Sat Nov 7 02:28:28 CET 2009
Revision: 45712
http://scummvm.svn.sourceforge.net/scummvm/?rev=45712&view=rev
Author: spalek
Date: 2009-11-07 01:28:27 +0000 (Sat, 07 Nov 2009)
Log Message:
-----------
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.
Modified Paths:
--------------
scummvm/trunk/engines/draci/animation.cpp
scummvm/trunk/engines/draci/animation.h
scummvm/trunk/engines/draci/game.cpp
scummvm/trunk/engines/draci/walking.cpp
Modified: scummvm/trunk/engines/draci/animation.cpp
===================================================================
--- scummvm/trunk/engines/draci/animation.cpp 2009-11-07 00:36:23 UTC (rev 45711)
+++ scummvm/trunk/engines/draci/animation.cpp 2009-11-07 01:28:27 UTC (rev 45712)
@@ -33,6 +33,7 @@
_id = kUnused;
_index = index;
_z = 0;
+ clearShift();
_displacement = kNoDisplacement;
_playing = false;
_looping = false;
@@ -56,6 +57,13 @@
_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 @@
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 @@
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 @@
// 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 @@
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,13 +179,27 @@
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) {
_frames[i] = frame;
_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 @@
delete _frames[i];
_frames.pop_back();
}
+ _relativeShifts.clear();
_samples.clear();
}
@@ -280,6 +310,7 @@
// Reset the animation to the beginning
anim->setCurrentFrame(0);
+ anim->clearShift();
debugC(3, kDraciAnimationDebugLevel, "Stopping animation %d...", id);
}
@@ -499,19 +530,19 @@
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();
}
Modified: scummvm/trunk/engines/draci/animation.h
===================================================================
--- scummvm/trunk/engines/draci/animation.h 2009-11-07 00:36:23 UTC (rev 45711)
+++ scummvm/trunk/engines/draci/animation.h 2009-11-07 01:28:27 UTC (rev 45712)
@@ -28,6 +28,7 @@
#include "draci/sprite.h"
#include "draci/sound.h"
+#include "common/rect.h"
namespace Draci {
@@ -75,11 +76,14 @@
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 @@
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 @@
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 @@
/** 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.
Modified: scummvm/trunk/engines/draci/game.cpp
===================================================================
--- scummvm/trunk/engines/draci/game.cpp 2009-11-07 00:36:23 UTC (rev 45711)
+++ scummvm/trunk/engines/draci/game.cpp 2009-11-07 01:28:27 UTC (rev 45712)
@@ -1194,10 +1194,8 @@
// into details.
animationReader.readByte();
const bool cyclic = animationReader.readByte();
+ const bool relative = animationReader.readByte();
- // FIXME: handle this properly
- animationReader.readByte(); // Relative field, not used
-
Animation *anim = _vm->_anims->addAnimation(animNum, z, false);
anim->setLooping(cyclic);
@@ -1216,7 +1214,8 @@
// _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 @@
const SoundSample *sam = _vm->_soundsArchive->getSample(sample, freq);
anim->addFrame(sp, sam);
+ if (relative) {
+ anim->makeLastFrameRelative(x, y);
+ }
}
return animNum;
Modified: scummvm/trunk/engines/draci/walking.cpp
===================================================================
--- scummvm/trunk/engines/draci/walking.cpp 2009-11-07 00:36:23 UTC (rev 45711)
+++ scummvm/trunk/engines/draci/walking.cpp 2009-11-07 01:28:27 UTC (rev 45712)
@@ -522,8 +522,9 @@
// 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);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list