diff options
author | Denis Kasak | 2009-07-05 03:24:46 +0000 |
---|---|---|
committer | Denis Kasak | 2009-07-05 03:24:46 +0000 |
commit | 6c3e9f5151fac4906c2fabc2e26ee39bc7043664 (patch) | |
tree | 3b27df90db22f61f7b6b6d2c05b8e7717f05146f | |
parent | 960740fe83ee1d1e4cea33f732df4b698d22c479 (diff) | |
download | scummvm-rg350-6c3e9f5151fac4906c2fabc2e26ee39bc7043664.tar.gz scummvm-rg350-6c3e9f5151fac4906c2fabc2e26ee39bc7043664.tar.bz2 scummvm-rg350-6c3e9f5151fac4906c2fabc2e26ee39bc7043664.zip |
* API change for Animation and AnimObj; AnimObj is now a proper class and each instance handles its own animation. Animation handles adding, fetching and deleting of AnimObjs (probably needs a namechange).
* Implemented actual animation (previously only the first frame was display)
* Implemented animation starting, stoping, looping
* Loaded looping dragon animation as a test
svn-id: r42114
-rw-r--r-- | engines/draci/animation.cpp | 215 | ||||
-rw-r--r-- | engines/draci/animation.h | 61 | ||||
-rw-r--r-- | engines/draci/game.cpp | 10 |
3 files changed, 219 insertions, 67 deletions
diff --git a/engines/draci/animation.cpp b/engines/draci/animation.cpp index 5e6578de57..a29281d510 100644 --- a/engines/draci/animation.cpp +++ b/engines/draci/animation.cpp @@ -28,111 +28,224 @@ namespace Draci { -void Animation::addAnimation(uint id, uint z, bool playing) { +AnimObj::AnimObj(DraciEngine *vm) : _vm(vm) { + _id = kUnused; + _z = 0; + _playing = false; + _looping = false; + _delay = 0; + _tick = _vm->_system->getMillis(); + _currentFrame = 0; +} + +AnimObj::~AnimObj() { + deleteFrames(); +} + +bool AnimObj::isLooping() { + return _looping; +} + +void AnimObj::setLooping(bool looping) { + _looping = looping; +} + +void AnimObj::setDelay(uint delay) { + _delay = delay; +} + +void AnimObj::nextFrame(bool force) { + + // If there's only one or no frames, return + if (getFramesNum() < 2) + return; + + Common::Rect frameRect = _frames[_currentFrame]->getRect(); + + // If we are at the last frame and not looping, stop the animation + // The animation is also restarted to frame zero + if ((_currentFrame == nextFrameNum() - 1) && !_looping) { + _currentFrame = 0; + _playing = false; + return; + } + + if (force || (_tick + _delay <= _vm->_system->getMillis())) { + _vm->_screen->getSurface()->markDirtyRect(frameRect); + _currentFrame = nextFrameNum(); + _tick = _vm->_system->getMillis(); + } + + debugC(6, kDraciAnimationDebugLevel, + "tick=%d delay=%d tick+delay=%d currenttime=%d frame=%d framenum=%d", + _tick, _delay, _tick + _delay, _vm->_system->getMillis(), _currentFrame, _frames.size()); +} + +uint AnimObj::nextFrameNum() { + + if ((_currentFrame == getFramesNum() - 1) && _looping) + return 0; + else + return _currentFrame + 1; +} + +void AnimObj::drawFrame(Surface *surface) { - AnimObj *obj = new AnimObj(); - obj->_id = id; - obj->_z = z; - obj->_currentFrame = 0; - obj->_playing = playing; + if (_frames.size() == 0) + return; + + if (_id == kOverlayImage) { + _frames[_currentFrame]->draw(surface, false); + } + else { + _frames[_currentFrame]->draw(surface, true); + } +} - insertAnimation(*obj); +void AnimObj::setID(int id) { + + _id = id; } -void Animation::play(uint id) { +int AnimObj::getID() { + + return _id; +} - AnimObj &obj = *getAnimation(id); +void AnimObj::setZ(uint z) { - obj._playing = true; + _z = z; } -void Animation::stop(uint id) { +uint AnimObj::getZ() { + + return _z; +} - AnimObj &obj = *getAnimation(id); +bool AnimObj::isPlaying() { - obj._playing = false; + return _playing; } -Common::List<AnimObj>::iterator Animation::getAnimation(uint id) { +void AnimObj::setPlaying(bool playing) { - Common::List<AnimObj>::iterator it; + _playing = playing; +} - for (it = _animObjects.begin(); it != _animObjects.end(); ++it) { - if (it->_id == id) { - return it; - } +void AnimObj::addFrame(Drawable *frame) { + + _frames.push_back(frame); +} + +uint AnimObj::getFramesNum() { + + return _frames.size(); +} + +void AnimObj::deleteFrames() { + + for (uint i = 0; i < getFramesNum(); ++i) { + delete _frames[i]; + _frames.pop_back(); } +} + +AnimObj *Animation::addAnimation(int id, uint z, bool playing) { + + AnimObj *obj = new AnimObj(_vm); + obj->setID(id); + obj->setZ(z); + obj->setPlaying(playing); + obj->setLooping(false); + + insertAnimation(obj); + + return obj; +} + +void Animation::play(int id) { + + AnimObj *obj = getAnimation(id); + + obj->setPlaying(true); +} - return _animObjects.end(); +void Animation::stop(int id) { + + AnimObj *obj = getAnimation(id); + + obj->setPlaying(false); } -void Animation::insertAnimation(AnimObj &animObj) { +AnimObj *Animation::getAnimation(int id) { - Common::List<AnimObj>::iterator it; + Common::List<AnimObj *>::iterator it; for (it = _animObjects.begin(); it != _animObjects.end(); ++it) { - if (animObj._z < it->_z) - break; + if ((*it)->getID() == id) { + return *it; + } } - _animObjects.insert(it, animObj); + return *_animObjects.end(); } -void Animation::addFrame(uint id, Drawable *frame) { +void Animation::insertAnimation(AnimObj *animObj) { - Common::List<AnimObj>::iterator it = getAnimation(id); + Common::List<AnimObj *>::iterator it; + + for (it = _animObjects.begin(); it != _animObjects.end(); ++it) { + if (animObj->getZ() < (*it)->getZ()) + break; + } - it->_frames.push_back(frame); + _animObjects.insert(it, animObj); } void Animation::addOverlay(Drawable *overlay, uint z) { - AnimObj *obj = new AnimObj(); - obj->_id = kOverlayImage; - obj->_z = z; - obj->_currentFrame = 0; - obj->_playing = true; - obj->_frames.push_back(overlay); + AnimObj *obj = new AnimObj(_vm); + obj->setID(kOverlayImage); + obj->setZ(z); + obj->setPlaying(true); + obj->addFrame(overlay); - insertAnimation(*obj); + insertAnimation(obj); } void Animation::drawScene(Surface *surf) { - Common::List<AnimObj>::iterator it; + Common::List<AnimObj *>::iterator it; for (it = _animObjects.begin(); it != _animObjects.end(); ++it) { - if (!it->_playing) { + if (! ((*it)->isPlaying()) ) { continue; } - if (it->_id == kOverlayImage) { - it->_frames[it->_currentFrame]->draw(surf, false); - } - else { - it->_frames[it->_currentFrame]->draw(surf, true); - } + (*it)->nextFrame(); + (*it)->drawFrame(surf); } } -void Animation::deleteAnimation(uint id) { +void Animation::deleteAnimation(int id) { - Common::List<AnimObj>::iterator it = getAnimation(id); + Common::List<AnimObj *>::iterator it; - for (uint i = 0; i < it->_frames.size(); ++i) { - delete it->_frames[i]; + for (it = _animObjects.begin(); it != _animObjects.end(); ++it) { + if ((*it)->getID() == id) + break; } + + (*it)->deleteFrames(); _animObjects.erase(it); } void Animation::deleteAll() { - Common::List<AnimObj>::iterator it; + Common::List<AnimObj *>::iterator it; for (it = _animObjects.begin(); it != _animObjects.end(); ++it) { - for (uint i = 0; i < it->_frames.size(); ++i) { - delete it->_frames[i]; - } + (*it)->deleteFrames(); } _animObjects.clear(); diff --git a/engines/draci/animation.h b/engines/draci/animation.h index c69947ea28..d4be8b5ba3 100644 --- a/engines/draci/animation.h +++ b/engines/draci/animation.h @@ -30,44 +30,81 @@ namespace Draci { -enum { kOverlayImage = -1 }; +enum { kOverlayImage = -1, kUnused = -2 }; class DraciEngine; -struct AnimObj { - uint _id; +class AnimObj { +public: + AnimObj(DraciEngine *vm); + ~AnimObj(); + + uint getZ(); + void setZ(uint z); + + void setID(int id); + int getID(); + + void setDelay(uint delay); + + void nextFrame(bool force = false); + void drawFrame(Surface *surface); + + void addFrame(Drawable *frame); + uint getFramesNum(); + void deleteFrames(); + + bool isPlaying(); + void setPlaying(bool playing); + + bool isLooping(); + void setLooping(bool looping); + + +private: + + uint nextFrameNum(); + + int _id; uint _currentFrame; uint _z; - bool _playing; + uint _delay; + uint _tick; + bool _playing; + bool _looping; Common::Array<Drawable*> _frames; + + DraciEngine *_vm; }; +// TODO: Probably needs a namechange to AnimationManager or similar since AnimObj now +// acts as an animation object + class Animation { public: Animation(DraciEngine *vm) : _vm(vm) {}; ~Animation() { deleteAll(); } - void addAnimation(uint id, uint z, bool playing = false); - void addFrame(uint id, Drawable *frame); + AnimObj *addAnimation(int id, uint z, bool playing = false); void addOverlay(Drawable *overlay, uint z); - void play(uint id); - void stop(uint id); + void play(int id); + void stop(int id); - void deleteAnimation(uint id); + void deleteAnimation(int id); void deleteAll(); void drawScene(Surface *surf); - Common::List<AnimObj>::iterator getAnimation(uint id); + AnimObj *getAnimation(int id); private: - void insertAnimation(AnimObj &animObj); + void insertAnimation(AnimObj *animObj); DraciEngine *_vm; - Common::List<AnimObj> _animObjects; + Common::List<AnimObj *> _animObjects; }; } diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index b24d62d36d..a843a8267e 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -189,7 +189,7 @@ int Game::loadAnimation(uint animNum) { animationReader.readByte(); // Cyclic field, not used animationReader.readByte(); // Relative field, not used - _vm->_anims->addAnimation(animNum, 254, false); + AnimObj *obj = _vm->_anims->addAnimation(animNum, 254, false); for (uint i = 0; i < numFrames; ++i) { uint spriteNum = animationReader.readUint16LE() - 1; @@ -202,8 +202,7 @@ int Game::loadAnimation(uint animNum) { uint freq = animationReader.readUint16LE(); uint delay = animationReader.readUint16LE(); - // TODO: implement Animation::setDelay() - //_vm->_anims->setDelay(animNum, delay*10); + obj->setDelay(delay * 10); BAFile *spriteFile = _vm->_spritesArchive->getFile(spriteNum); @@ -212,7 +211,10 @@ int Game::loadAnimation(uint animNum) { if (mirror) sp->setMirrorOn(); - _vm->_anims->addFrame(animNum, sp); + // HACK: This is only for testing + obj->setLooping(true); + + obj->addFrame(sp); } return animNum; |