diff options
author | Sylvain Dupont | 2011-01-29 20:12:27 +0000 |
---|---|---|
committer | Sylvain Dupont | 2011-01-29 20:12:27 +0000 |
commit | 96f4cc4b8a4273ec728419645363952d35f8ebe0 (patch) | |
tree | da8f5f888419a5aade402eb3e3d79b7832e8c17a /engines/toon | |
parent | d925e38acfaa646e7191a4fd6e5197f323df491d (diff) | |
download | scummvm-rg350-96f4cc4b8a4273ec728419645363952d35f8ebe0.tar.gz scummvm-rg350-96f4cc4b8a4273ec728419645363952d35f8ebe0.tar.bz2 scummvm-rg350-96f4cc4b8a4273ec728419645363952d35f8ebe0.zip |
TOON: Pathfinding & walking improvements
Use direct line path if possible
Smooth facing direction to avoid flickering (entering zanidu shuttle for example)
Fix possible lockups
svn-id: r55624
Diffstat (limited to 'engines/toon')
-rw-r--r-- | engines/toon/character.cpp | 32 | ||||
-rw-r--r-- | engines/toon/character.h | 2 | ||||
-rw-r--r-- | engines/toon/drew.cpp | 16 | ||||
-rw-r--r-- | engines/toon/drew.h | 4 | ||||
-rw-r--r-- | engines/toon/path.cpp | 44 | ||||
-rw-r--r-- | engines/toon/path.h | 1 | ||||
-rw-r--r-- | engines/toon/toon.cpp | 4 |
7 files changed, 92 insertions, 11 deletions
diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp index 5cfa421af4..523eac9eb9 100644 --- a/engines/toon/character.cpp +++ b/engines/toon/character.cpp @@ -175,6 +175,8 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) { int32 localFinalX = _finalX; int32 localFinalY = _finalY; + int32 smoothDx = 0; + int32 smoothDy = 0; for (int32 a = 0; a < _vm->getPathFinding()->getPathNodeCount(); a++) { _currentPathX[a] = _vm->getPathFinding()->getPathNodeX(a); @@ -192,16 +194,25 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) { if (_blockingWalk) { while ((_x != newPosX || _y != newPosY) && _currentPathNode < _currentPathNodeCount && !_vm->shouldQuitGame()) { - if (_currentPathNode < _currentPathNodeCount - 10) { - int32 delta = MIN<int32>(10, _currentPathNodeCount - _currentPathNode); + if (_currentPathNode < _currentPathNodeCount - 4) { + int32 delta = MIN<int32>(4, _currentPathNodeCount - _currentPathNode); + int32 dx = _currentPathX[_currentPathNode+delta] - _x; int32 dy = _currentPathY[_currentPathNode+delta] - _y; - setFacing(getFacingFromDirection(dx, dy)); + + // smooth the facing computation. It prevents some ugly flickering from happening + if (!smoothDx && !smoothDy) { + smoothDx = dx; + smoothDy = dy; + } else { + smoothDx = (dx + smoothDx * 3) / 4; + smoothDy = (dy + smoothDy * 3) / 4; + } + + setFacing(getFacingFromDirection(smoothDx, smoothDy)); playWalkAnim(0, 0); } - - // in 1/1000 pixels _numPixelToWalk += _speed * (_vm->getSystem()->getMillis() - _lastWalkTime) * _scale / 1024; _lastWalkTime = _vm->getSystem()->getMillis(); @@ -994,6 +1005,12 @@ bool Character::loadShadowAnimation(Common::String animName) { return true; } +void Character::plotPath(Graphics::Surface& surface) { + for (int i = 0; i < _currentPathNodeCount; i++) { + *(byte*)surface.getBasePtr(_currentPathX[i], _currentPathY[i]) = ( i < _currentPathNode); + } +} + void Character::playAnim(int32 animId, int32 unused, int32 flags) { debugC(3, kDebugCharacter, "playAnim(%d, unused, %d)", animId, flags); @@ -1029,8 +1046,11 @@ void Character::playAnim(int32 animId, int32 unused, int32 flags) { // make the talker busy _flags |= 1; + // old special anim was talking anim ? in this case we don't wait for the character to be ready + bool wasTalkAnim = _specialAnim && strstr(_specialAnim->_name, "TLK"); + // wait for the character to be ready - while (_animScriptId != -1 && _animationInstance && _animationInstance->getFrame() > 0 && (_specialAnim && _animationInstance->getAnimation() != _specialAnim)) { + while (_animScriptId != -1 && _animationInstance && _animationInstance->getFrame() > 0 && !wasTalkAnim && (_specialAnim && _animationInstance->getAnimation() != _specialAnim)) { _vm->simpleUpdate(false); } } diff --git a/engines/toon/character.h b/engines/toon/character.h index 1927200b12..4cd3813f73 100644 --- a/engines/toon/character.h +++ b/engines/toon/character.h @@ -100,6 +100,8 @@ public: virtual void updateTimers(int32 relativeAdd); virtual void setTalking(bool talking) { _isTalking = talking; } virtual bool isTalking() { return _isTalking; } + virtual void resetScale() { }; + virtual void plotPath(Graphics::Surface& surface); int32 getFacingFromDirection(int32 dx, int32 dy); static const SpecialCharacterAnimation *getSpecialAnimation(int32 characterId, int32 animationId); diff --git a/engines/toon/drew.cpp b/engines/toon/drew.cpp index 36ca17dd70..eefb4b8efa 100644 --- a/engines/toon/drew.cpp +++ b/engines/toon/drew.cpp @@ -33,6 +33,7 @@ CharacterDrew::CharacterDrew(ToonEngine *vm) : Character(vm) { _animationInstance = vm->getAnimationManager()->createNewInstance(kAnimationCharacter); _animationInstance->setUseMask(true); vm->getAnimationManager()->addInstance(_animationInstance); + _currentScale = 1024; } CharacterDrew::~CharacterDrew() { @@ -104,6 +105,15 @@ void CharacterDrew::playWalkAnim(int32 start, int32 end) { void CharacterDrew::update(int32 timeIncrement) { debugC(5, kDebugCharacter, "update(%d)", timeIncrement); Character::update(timeIncrement); + if (_currentScale > _scale) { + _scale += timeIncrement * 2; + if (_scale > _currentScale) + _scale = _currentScale; + } else if (_currentScale < _scale) { + _scale -= timeIncrement * 2; + if (_scale < _currentScale) + _scale = _currentScale; + } setPosition(_x, _y); } @@ -114,5 +124,11 @@ int32 CharacterDrew::getRandomIdleAnim() { static const int32 idle[] = { 6, 9, 10, 11, 12 }; return idle[_vm->randRange(0, 4)]; } + +void CharacterDrew::resetScale() +{ + _scale = _currentScale; + setPosition(_x, _y); +} } // End of namespace Toon diff --git a/engines/toon/drew.h b/engines/toon/drew.h index ae9fdff2e9..d8091f2225 100644 --- a/engines/toon/drew.h +++ b/engines/toon/drew.h @@ -40,9 +40,13 @@ public: bool setupPalette(); void playStandingAnim(); void setPosition(int32 x, int32 y); + void resetScale(); void update(int32 timeIncrement); void playWalkAnim(int32 start, int32 end); int32 getRandomIdleAnim(); +protected: + int32 _currentScale; + }; } // End of namespace Toon diff --git a/engines/toon/path.cpp b/engines/toon/path.cpp index 64dfec2dd1..3f948679f4 100644 --- a/engines/toon/path.cpp +++ b/engines/toon/path.cpp @@ -209,8 +209,40 @@ int32 PathFinding::findClosestWalkingPoint(int32 xx, int32 yy, int32 *fxx, int32 } } -bool PathFinding::lineIsWalkable(int32 x, int32 y, int32 x2, int32 y2) { +bool PathFinding::walkLine(int32 x, int32 y, int32 x2, int32 y2) { + uint32 bx = x << 16; + int32 dx = x2 - x; + uint32 by = y << 16; + int32 dy = y2 - y; + uint32 adx = abs(dx); + uint32 ady = abs(dy); + int32 t = 0; + if (adx <= ady) + t = ady; + else + t = adx; + + int32 cdx = (dx << 16) / t; + int32 cdy = (dy << 16) / t; + int32 i = t; + _gridPathCount = 0; + while (i) { + _tempPathX[i] = bx >> 16; + _tempPathY[i] = by >> 16; + _gridPathCount++; + bx += cdx; + by += cdy; + i--; + } + + _tempPathX[0] = x2; + _tempPathY[0] = y2; + + return true; +} + +bool PathFinding::lineIsWalkable(int32 x, int32 y, int32 x2, int32 y2) { uint32 bx = x << 16; int32 dx = x2 - x; uint32 by = y << 16; @@ -228,7 +260,7 @@ bool PathFinding::lineIsWalkable(int32 x, int32 y, int32 x2, int32 y2) { int32 i = t; while (i) { - if(!isWalkable(bx >> 16, by >> 16)) + if (!isWalkable(bx >> 16, by >> 16)) return false; bx += cdx; by += cdy; @@ -251,8 +283,12 @@ int32 PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) { } // first test direct line - //if(lineIsWalkable(x,y,destx,desty)) + if (lineIsWalkable(x,y,destx,desty)) { + walkLine(x,y,destx,desty); + return true; + } + // no direct line, we use the standard A* algorithm memset(_gridTemp , 0, _width * _height * sizeof(int32)); _heap->clear(); int32 curX = x; @@ -277,7 +313,7 @@ int32 PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) { for (int32 px = startX; px <= endX; px++) { for (int py = startY; py <= endY; py++) { if (px != curX || py != curY) { - wei = abs(px - curX) + abs(py - curY); + wei = ((abs(px - curX) + abs(py - curY))); int32 curPNode = px + py * _width; if (isWalkable(px, py)) { // walkable ? diff --git a/engines/toon/path.h b/engines/toon/path.h index e38ec1275e..a2b1b7bf92 100644 --- a/engines/toon/path.h +++ b/engines/toon/path.h @@ -64,6 +64,7 @@ public: bool isWalkable(int32 x, int32 y); bool isLikelyWalkable(int32 x, int32 y); bool lineIsWalkable(int32 x, int32 y, int32 x2, int32 y2); + bool walkLine(int32 x, int32 y, int32 x2, int32 y2); void init(Picture *mask); void resetBlockingRects(); diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp index 65155daac8..49f8f7897f 100644 --- a/engines/toon/toon.cpp +++ b/engines/toon/toon.cpp @@ -386,7 +386,8 @@ void ToonEngine::render() { drawConversationLine(); drawConversationIcons(); drawSack(); - //drawPalette(); + //drawPalette(); // used to debug the current palette + //_drew->plotPath(*_mainSurface); // used to debug path finding #if 0 char test[256]; @@ -1059,6 +1060,7 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) { _mouseButton = 0; _lastMouseButton = 0x3; + // load package strcpy(temp, createRoomFilename(Common::String::format("%s.pak", _gameState->_locations[_gameState->_currentScene]._name).c_str()).c_str()); resources()->openPackage(temp, true); |