[Scummvm-cvs-logs] SF.net SVN: scummvm:[45722] scummvm/trunk/engines/draci

spalek at users.sourceforge.net spalek at users.sourceforge.net
Sat Nov 7 12:45:13 CET 2009


Revision: 45722
          http://scummvm.svn.sourceforge.net/scummvm/?rev=45722&view=rev
Author:   spalek
Date:     2009-11-07 11:45:13 +0000 (Sat, 07 Nov 2009)

Log Message:
-----------
Debugged updating the position of the hero during walking.

I project the hero immediately to the end of each edge for the time being
though.

Modified Paths:
--------------
    scummvm/trunk/engines/draci/game.cpp
    scummvm/trunk/engines/draci/game.h
    scummvm/trunk/engines/draci/script.cpp
    scummvm/trunk/engines/draci/walking.cpp
    scummvm/trunk/engines/draci/walking.h

Modified: scummvm/trunk/engines/draci/game.cpp
===================================================================
--- scummvm/trunk/engines/draci/game.cpp	2009-11-07 10:56:51 UTC (rev 45721)
+++ scummvm/trunk/engines/draci/game.cpp	2009-11-07 11:45:13 UTC (rev 45722)
@@ -954,18 +954,25 @@
 	deleteAnimationsAfterIndex(lastAnimIndex);
 }
 
-void Game::playHeroAnimation(int anim_index) {
+int Game::playHeroAnimation(int anim_index) {
 	const GameObject *dragon = getObject(kDragonObject);
 	const int current_anim_index = playingObjectAnimation(dragon);
+	const int animID = dragon->_anim[anim_index];
+	Animation *anim = _vm->_anims->getAnimation(animID);
+
 	if (anim_index == current_anim_index) {
-		return;
+		anim->markDirtyRect(_vm->_screen->getSurface());
+	} else {
+		stopObjectAnimations(dragon);
 	}
+	positionAnimAsHero(anim);
+	if (anim_index == current_anim_index) {
+		anim->markDirtyRect(_vm->_screen->getSurface());
+	} else {
+		_vm->_anims->play(animID);
+	}
 
-	const int animID = dragon->_anim[anim_index];
-	Animation *anim = _vm->_anims->getAnimation(animID);
-	stopObjectAnimations(dragon);
-	positionAnimAsHero(anim);
-	_vm->_anims->play(animID);
+	return anim->currentFrameNum();
 }
 
 void Game::redrawWalkingPath(int id, byte colour, const WalkingPath &path) {
@@ -981,12 +988,6 @@
 	_hero = p;
 }
 
-void Game::positionHero(const Common::Point &p, SightDirection dir) {
-	setHeroPosition(p);
-	Common::Point mousePos(_vm->_mouse->getPosX(), _vm->_mouse->getPosY());
-	playHeroAnimation(WalkingState::animationForSightDirection(dir, _hero, mousePos, WalkingPath()));
-}
-
 Common::Point Game::findNearestWalkable(int x, int y) const {
 	Surface *surface = _vm->_screen->getSurface();
 	return _walkingMap.findNearestWalkable(x, y, surface->getDimensions());
@@ -1493,6 +1494,12 @@
 	anim->setScaleFactors(scale, scale);
 
 	anim->setRelative(p.x, p.y);
+
+	// Clear the animation's shift so that the real sprite stays at place
+	// regardless of what the current phase is.  If the animation starts
+	// from the beginning, the shift is already [0,0], but if it is in the
+	// middle, it may be different.
+	anim->clearShift();
 }
 
 void Game::positionHeroAsAnim(Animation *anim) {
@@ -1502,17 +1509,10 @@
 
 	// Update our hero coordinates (don't forget that our control point is
 	// elsewhere).
+	// TODO: what about rounding errors?
 	Drawable *frame = anim->getCurrentFrame();
 	_hero.x += (int) (anim->getScaleX() * frame->getWidth() / 2);
 	_hero.y += (int) (anim->getScaleY() * frame->getHeight());
-
-	// Clear the animation's shift so that by updating the coordinates the
-	// animation will stay in place.
-	anim->clearShift();
-
-	// Call the inverse procedure to calculate new scaling factors.
-	// TODO: what about rounding errors?
-	positionAnimAsHero(anim);
 }
 
 void Game::pushNewRoom() {

Modified: scummvm/trunk/engines/draci/game.h
===================================================================
--- scummvm/trunk/engines/draci/game.h	2009-11-07 10:56:51 UTC (rev 45721)
+++ scummvm/trunk/engines/draci/game.h	2009-11-07 11:45:13 UTC (rev 45722)
@@ -209,15 +209,20 @@
 	Common::Point findNearestWalkable(int x, int y) const;
 	void heroAnimationFinished() { _walkingState.heroAnimationFinished(); }
 	void stopWalking() { _walkingState.stopWalking(); }	// and clear callback
-	void positionHero(const Common::Point &p, SightDirection dir);	// teleport the dragon
 	void walkHero(int x, int y, SightDirection dir);	// start walking and leave callback as is
 	void setHeroPosition(const Common::Point &p);
-	int getHeroX() const { return _hero.x; }
-	int getHeroY() const { return _hero.y; }
+	const Common::Point &getHeroPosition() const { return _hero; }
 	void positionAnimAsHero(Animation *anim);
 	void positionHeroAsAnim(Animation *anim);
-	void playHeroAnimation(int anim_index);
 
+	// Makes sure animation anim_index plays on the hero.  If the hero's
+	// position has changed, it updates the animation position.  If the new
+	// animation is different, it stops the old one and starts the new one,
+	// otherwise it just marks dirty rectangles for moving the position.
+	// Returns the current animation phase of the new animation (usually 0
+	// unless the animation hasn't changed).
+	int playHeroAnimation(int anim_index);
+
 	int loadAnimation(uint animNum, uint z);
 	void loadOverlays();
 	void loadObject(uint numObj);

Modified: scummvm/trunk/engines/draci/script.cpp
===================================================================
--- scummvm/trunk/engines/draci/script.cpp	2009-11-07 10:56:51 UTC (rev 45721)
+++ scummvm/trunk/engines/draci/script.cpp	2009-11-07 11:45:13 UTC (rev 45722)
@@ -664,8 +664,13 @@
 	SightDirection dir = static_cast<SightDirection> (params.pop());
 
 	// Jumps into the given position regardless of the walking map.
+	Common::Point heroPos(_vm->_game->findNearestWalkable(x, y));
+	Common::Point mousePos(_vm->_mouse->getPosX(), _vm->_mouse->getPosY());
+
 	_vm->_game->stopWalking();
-	_vm->_game->positionHero(_vm->_game->findNearestWalkable(x, y), dir);
+	_vm->_game->setHeroPosition(heroPos);
+	_vm->_game->playHeroAnimation(WalkingState::animationForSightDirection(
+		  dir, heroPos, mousePos, WalkingPath()));
 }
 
 void Script::walkOn(Common::Queue<int> &params) {

Modified: scummvm/trunk/engines/draci/walking.cpp
===================================================================
--- scummvm/trunk/engines/draci/walking.cpp	2009-11-07 10:56:51 UTC (rev 45721)
+++ scummvm/trunk/engines/draci/walking.cpp	2009-11-07 11:45:13 UTC (rev 45722)
@@ -457,7 +457,7 @@
 	}
 
 	// Going to start with the first segment.
-	_segment = _lastAnimPhase = _position = _length = -1;
+	_segment = _lastAnimPhase = -1;
 	turnForTheNextSegment();
 }
 
@@ -489,13 +489,13 @@
 
 bool WalkingState::continueWalking() {
 	const GameObject *dragon = _vm->_game->getObject(kDragonObject);
-	const Movement anim_index = static_cast<Movement> (_vm->_game->playingObjectAnimation(dragon));
+	const Movement movement = static_cast<Movement> (_vm->_game->playingObjectAnimation(dragon));
 
 	// 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(anim_index)) {
+	if (isTurningMovement(movement)) {
 		return true;
 	}
 
@@ -509,41 +509,51 @@
 
 	// 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[anim_index];
+	const int animID = dragon->_anim[movement];
 	Animation *anim = _vm->_anims->getAnimation(animID);
 	const int animPhase = anim->currentFrameNum();
 	const bool wasUpdated = animPhase != _lastAnimPhase;
 	if (!wasUpdated) {
 		return true;
 	}
-	_lastAnimPhase = animPhase;
 
-	debugC(3, kDraciWalkingDebugLevel, "Continuing walking in segment %d and position %d/%d", _segment, _position, _length);
+	// We are walking in the middle of an edge.  The animation phase has
+	// just changed.
 
-	// We are walking in the middle of an edge.  The animation phase has
-	// just changed.  Update the position of the hero.
+	// Read the position of the hero from the animation object, and project
+	// it to the current edge.
 	_vm->_game->positionHeroAsAnim(anim);
-	// TODO: take the [XY] coordinate determined by the animation, update
-	// the other one so that the hero stays on the edge, remove _position
-	// and _length, and instead test reaching the destination by computing
-	// the scalar product
-	_position += 4;
-	// Common::Point newPos = WalkingMap::interpolate(
-	// 	_path[_segment], _path[_segment+1], _position, _length);
-	// _vm->_game->setHeroPosition(newPos);
-	// _vm->_game->positionAnimAsHero(anim);
+	const Common::Point &hero = _vm->_game->getHeroPosition();
+	Common::Point newHero = hero;
+	const bool reachedEnd = alignHeroToEdge(_path[_segment], _path[_segment+1], &newHero);
 
+	debugC(3, kDraciWalkingDebugLevel, "Continuing walking in segment %d and position [%d,%d] projected to [%d,%d]",
+		_segment, hero.x, hero.y, newHero.x, newHero.y);
+
+	// Update the hero position to the projected one.  The animation number
+	// is not changing, so this will just move the sprite and return the
+	// current frame number.
+	_vm->_game->setHeroPosition(newHero);
+	_lastAnimPhase = _vm->_game->playHeroAnimation(movement);
+
 	// If the hero has reached the end of the edge, start transition to the
 	// next phase.  This will increment _segment, either immediately (if no
 	// transition is needed) or in the callback (after the transition is
-	// done).
-	if (_position >= _length) {
+	// done).  The position is equal to the end-point of the edge thanks to
+	// alignHeroToEdge().
+	if (reachedEnd) {
 		turnForTheNextSegment();
 	}
 
 	return true;
 }
 
+bool WalkingState::alignHeroToEdge(const Common::Point &p1, const Common::Point &p2, Common::Point *hero) {
+	// TODO
+	*hero = p2;
+	return true;
+}
+
 void WalkingState::turnForTheNextSegment() {
 	const GameObject *dragon = _vm->_game->getObject(kDragonObject);
 	const Movement currentAnim = static_cast<Movement> (_vm->_game->playingObjectAnimation(dragon));
@@ -565,37 +575,30 @@
 		anim->registerCallback(&Animation::tellWalkingState);
 
 		debugC(2, kDraciWalkingDebugLevel, "Starting turning animation %d", transition);
+		_lastAnimPhase = -1;
 	}
 }
 
 void WalkingState::heroAnimationFinished() {
 	// The hero is turned well for the next line segment or for facing the
-	// target direction.
+	// target direction.  It is also standing on the right spot thanks to
+	// the entry condition for turnForTheNextSegment().
 
-	// Start the desired next animation.  playHeroAnimation() takes care of
-	// stopping the current animation.
+	// Start the desired next animation and retrieve the current animation
+	// phase.
 	// Don't use any callbacks, because continueWalking() will decide the
 	// end on its own and after walking is done callbacks shouldn't be
 	// called either.  It wouldn't make much sense anyway, since the
 	// walking/staying/talking animations are cyclic.
 	Movement nextAnim = directionForNextPhase();
-	_vm->_game->playHeroAnimation(nextAnim);
+	_lastAnimPhase = _vm->_game->playHeroAnimation(nextAnim);
 
-	// Retrieve the current animation phase.  Don't just use 0, because we
-	// cannot assume that nextAnim has just started.  If it was already
-	// playing before, then playHeroAnimation(nextAnim) does nothing.
-	const GameObject *dragon = _vm->_game->getObject(kDragonObject);
-	const int animID = dragon->_anim[nextAnim];
-	Animation *anim = _vm->_anims->getAnimation(animID);
-	_lastAnimPhase = anim->currentFrameNum();
-
 	debugC(2, kDraciWalkingDebugLevel, "Turned for segment %d, starting animation %d", _segment+1, nextAnim);
 
 	if (++_segment < (int) (_path.size() - 1)) {
 		// We are on an edge: track where the hero is on this edge.
-		_position = 0;
-		_length = WalkingMap::pointsBetween(_path[_segment], _path[_segment+1]);
-		debugC(2, kDraciWalkingDebugLevel, "Next segment %d has length %d", _segment, _length);
+		int length = WalkingMap::pointsBetween(_path[_segment], _path[_segment+1]);
+		debugC(2, kDraciWalkingDebugLevel, "Next segment %d has length %d", _segment, length);
 	} else {
 		// Otherwise we are done.  continueWalking() will return false next time.
 		debugC(2, kDraciWalkingDebugLevel, "We have walked the whole path");

Modified: scummvm/trunk/engines/draci/walking.h
===================================================================
--- scummvm/trunk/engines/draci/walking.h	2009-11-07 10:56:51 UTC (rev 45721)
+++ scummvm/trunk/engines/draci/walking.h	2009-11-07 11:45:13 UTC (rev 45722)
@@ -142,7 +142,6 @@
 	SightDirection _dir;
 
 	int _segment;
-	int _position, _length;
 	int _lastAnimPhase;
 
 	const GPL2Program *_callback;
@@ -168,6 +167,10 @@
 	static bool isTurningMovement(Movement m) {
 		return m >= kFirstTurning && m <= kLastTurning;
 	}
+
+	// Projects hero to the given edge, but not behind p2.  Returns true
+	// when hero has reached at least p2.
+	static bool alignHeroToEdge(const Common::Point &p1, const Common::Point &p2, Common::Point *hero);
 };
 
 } // End of namespace Draci


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