aboutsummaryrefslogtreecommitdiff
path: root/engines/toon
diff options
context:
space:
mode:
authorSylvain Dupont2011-01-29 20:12:27 +0000
committerSylvain Dupont2011-01-29 20:12:27 +0000
commit96f4cc4b8a4273ec728419645363952d35f8ebe0 (patch)
treeda8f5f888419a5aade402eb3e3d79b7832e8c17a /engines/toon
parentd925e38acfaa646e7191a4fd6e5197f323df491d (diff)
downloadscummvm-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.cpp32
-rw-r--r--engines/toon/character.h2
-rw-r--r--engines/toon/drew.cpp16
-rw-r--r--engines/toon/drew.h4
-rw-r--r--engines/toon/path.cpp44
-rw-r--r--engines/toon/path.h1
-rw-r--r--engines/toon/toon.cpp4
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);