aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorRobert Špalek2009-11-08 05:29:12 +0000
committerRobert Špalek2009-11-08 05:29:12 +0000
commit57b22e3688fa8f4abbb4db71f2117574978dd10d (patch)
treeeeec4eeff95d6f42b20b78bd95e03def8450b483 /engines
parent354d7f6366d11628030bcfde9186fc6e1c819f9a (diff)
downloadscummvm-rg350-57b22e3688fa8f4abbb4db71f2117574978dd10d.tar.gz
scummvm-rg350-57b22e3688fa8f4abbb4db71f2117574978dd10d.tar.bz2
scummvm-rg350-57b22e3688fa8f4abbb4db71f2117574978dd10d.zip
Walking animations are fully smooth now
svn-id: r45743
Diffstat (limited to 'engines')
-rw-r--r--engines/draci/walking.cpp55
-rw-r--r--engines/draci/walking.h16
2 files changed, 48 insertions, 23 deletions
diff --git a/engines/draci/walking.cpp b/engines/draci/walking.cpp
index bda91b79cc..19d91de8c2 100644
--- a/engines/draci/walking.cpp
+++ b/engines/draci/walking.cpp
@@ -462,6 +462,7 @@ void WalkingState::startWalking(const Common::Point &p1, const Common::Point &p2
// Going to start with the first segment.
_segment = _lastAnimPhase = -1;
+ _turningFinished = false;
turnForTheNextSegment();
}
@@ -495,6 +496,26 @@ bool WalkingState::continueWalking() {
const GameObject *dragon = _vm->_game->getObject(kDragonObject);
const Movement movement = static_cast<Movement> (_vm->_game->playingObjectAnimation(dragon));
+ if (_turningFinished) {
+ // When a turning animation has finished, heroAnimationFinished() callback
+ // gets called, which sets this flag to true. It's important
+ // to not start walking right away in the callback, because
+ // that would disturb the data structures of the animation
+ // manager.
+ _turningFinished = false;
+ return walkOnNextEdge();
+ }
+
+ // If the current segment is the last one, we have reached the
+ // destination and are already facing in the right direction ===>
+ // return false. The code should, however, get here only if the path
+ // has just 1 vertex and startWalking() leaves the path open.
+ // Finishing and nontrivial path will get caught earlier.
+ if (_segment >= (int) (_path.size() - 1)) {
+ _path.clear();
+ return false;
+ }
+
// Read the dragon's animation's current phase. Determine if it has
// changed from the last time. If not, wait until it has.
const int animID = dragon->_anim[movement];
@@ -506,24 +527,13 @@ bool WalkingState::continueWalking() {
return true;
}
- // If the current animation is a turning animation, wait a bit more.
- // When this animation has finished, heroAnimationFinished() callback
- // will be called, which starts a new scheduled one, so the code never
- // gets here if it hasn't finished yet.
if (isTurningMovement(movement)) {
+ // If the current animation is a turning animation, wait a bit more.
debugC(3, kDraciWalkingDebugLevel, "Continuing turning for edge %d with phase %d", _segment+1, animPhase);
_lastAnimPhase = animPhase;
return true;
}
- // If the current segment is the last one, we have reached the
- // destination and are already facing in the right direction ===>
- // return false.
- if (_segment >= (int) (_path.size() - 1)) {
- _path.clear();
- return false;
- }
-
// We are walking in the middle of an edge. The animation phase has
// just changed.
@@ -562,7 +572,7 @@ bool WalkingState::continueWalking() {
_segment+1, _path[_segment+1].x, _path[_segment+1].y, adjustedHero.x, adjustedHero.y);
_path[_segment+1] = adjustedHero;
}
- turnForTheNextSegment();
+ return turnForTheNextSegment();
}
return true;
@@ -582,7 +592,7 @@ bool WalkingState::alignHeroToEdge(const Common::Point &p1, const Common::Point
return reachedEnd;
}
-void WalkingState::turnForTheNextSegment() {
+bool WalkingState::turnForTheNextSegment() {
const GameObject *dragon = _vm->_game->getObject(kDragonObject);
const Movement currentAnim = static_cast<Movement> (_vm->_game->playingObjectAnimation(dragon));
const Movement wantAnim = directionForNextPhase();
@@ -592,10 +602,11 @@ void WalkingState::turnForTheNextSegment() {
if (transition == kMoveUndefined) {
// Start the next segment right away as if the turning has just finished.
- heroAnimationFinished();
+ return walkOnNextEdge();
} else {
// Otherwise start the transition and wait until the Animation
- // class calls heroAnimationFinished() as a callback.
+ // class calls heroAnimationFinished() as a callback, leading
+ // to calling walkOnNextEdge() in the next phase.
assert(isTurningMovement(transition));
_lastAnimPhase = _vm->_game->playHeroAnimation(transition);
const int animID = dragon->_anim[transition];
@@ -603,10 +614,16 @@ void WalkingState::turnForTheNextSegment() {
anim->registerCallback(&Animation::tellWalkingState);
debugC(2, kDraciWalkingDebugLevel, "Starting turning animation %d with phase %d", transition, _lastAnimPhase);
+ return true;
}
}
void WalkingState::heroAnimationFinished() {
+ debugC(2, kDraciWalkingDebugLevel, "Turning callback called");
+ _turningFinished = true;
+}
+
+bool WalkingState::walkOnNextEdge() {
// The hero is turned well for the next line segment or for facing the
// target direction. It is also standing on the right spot thanks to
// the entry condition for turnForTheNextSegment().
@@ -620,18 +637,20 @@ void WalkingState::heroAnimationFinished() {
Movement nextAnim = directionForNextPhase();
_lastAnimPhase = _vm->_game->playHeroAnimation(nextAnim);
+ // TODO: do we need to clear this callback for the animation?
+
debugC(2, kDraciWalkingDebugLevel, "Turned for edge %d, starting animation %d with phase %d", _segment+1, nextAnim, _lastAnimPhase);
if (++_segment < (int) (_path.size() - 1)) {
// We are on an edge: track where the hero is on this edge.
int length = WalkingMap::pointsBetween(_path[_segment], _path[_segment+1]);
debugC(2, kDraciWalkingDebugLevel, "Next edge %d has length %d", _segment, length);
+ return true;
} else {
// Otherwise we are done. continueWalking() will return false next time.
debugC(2, kDraciWalkingDebugLevel, "We have walked the whole path");
+ return false;
}
-
- // TODO: do we need to clear this callback for the animation?
}
Movement WalkingState::animationForDirection(const Common::Point &here, const Common::Point &there) {
diff --git a/engines/draci/walking.h b/engines/draci/walking.h
index b178c2164b..e43abda553 100644
--- a/engines/draci/walking.h
+++ b/engines/draci/walking.h
@@ -124,8 +124,7 @@ public:
// the callback untouched (the caller must call it).
bool continueWalking();
- // Called when the hero's turning animation has finished. Starts
- // scheduled animation.
+ // Called when the hero's turning animation has finished.
void heroAnimationFinished();
// Returns the hero's animation corresponding to looking into given
@@ -144,15 +143,22 @@ private:
int _segment;
int _lastAnimPhase;
+ bool _turningFinished;
const GPL2Program *_callback;
uint16 _callbackOffset;
- // Initiates turning of the dragon into the direction for the next segment / after walking.
- void turnForTheNextSegment();
+ // Initiates turning of the dragon into the direction for the next
+ // segment / after walking. Returns false when there is nothing left
+ // to do and walking is done.
+ bool turnForTheNextSegment();
+
+ // Starts walking on the next edge. Returns false if we are already at
+ // the final vertex and walking is done.
+ bool walkOnNextEdge();
// Return one of the 4 animations kMove{Down,Up,Right,Left}
- // corresponding to the walking from here to there.
+ // corresponding to walking from here to there.
static Movement animationForDirection(const Common::Point &here, const Common::Point &there);
// Returns the desired facing direction to begin the next phase of the