diff options
author | D G Turner | 2012-06-14 17:45:30 +0100 |
---|---|---|
committer | D G Turner | 2012-06-14 17:45:30 +0100 |
commit | 57d34d2576d38a2820afeae0ba860dc863a34b08 (patch) | |
tree | f89a438982fca8981845c951bb2e65bc08b945b8 | |
parent | 5ae4ed09ea9b0ffd4ef00e55eb1f738103fdeeeb (diff) | |
parent | 4aa0ec7fc4eae0941efb15affe664544c33822ea (diff) | |
download | scummvm-rg350-57d34d2576d38a2820afeae0ba860dc863a34b08.tar.gz scummvm-rg350-57d34d2576d38a2820afeae0ba860dc863a34b08.tar.bz2 scummvm-rg350-57d34d2576d38a2820afeae0ba860dc863a34b08.zip |
Merge branch 'toon-RAM-reduction'
-rw-r--r-- | engines/toon/character.cpp | 87 | ||||
-rw-r--r-- | engines/toon/character.h | 33 | ||||
-rw-r--r-- | engines/toon/drew.cpp | 2 | ||||
-rw-r--r-- | engines/toon/drew.h | 2 | ||||
-rw-r--r-- | engines/toon/flux.cpp | 4 | ||||
-rw-r--r-- | engines/toon/flux.h | 2 | ||||
-rw-r--r-- | engines/toon/path.cpp | 267 | ||||
-rw-r--r-- | engines/toon/path.h | 71 | ||||
-rw-r--r-- | engines/toon/toon.cpp | 12 |
9 files changed, 221 insertions, 259 deletions
diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp index 0e5189957b..c9073de587 100644 --- a/engines/toon/character.cpp +++ b/engines/toon/character.cpp @@ -56,7 +56,6 @@ Character::Character(ToonEngine *vm) : _vm(vm) { _animScriptId = -1; _animSpecialId = -1; _animSpecialDefaultId = 0; - _currentPathNodeCount = 0; _currentPathNode = 0; _currentWalkStamp = 0; _visible = true; @@ -81,7 +80,7 @@ Character::~Character(void) { void Character::init() { } -void Character::forceFacing( int32 facing ) { +void Character::forceFacing(int32 facing) { debugC(4, kDebugCharacter, "forceFacing(%d)", facing); _facing = facing; } @@ -123,7 +122,7 @@ void Character::setFacing(int32 facing) { _lastWalkTime = _vm->getOldMilli(); } - if (_currentPathNode == 0) + if (_currentPathNode == 0) playStandingAnim(); else playWalkAnim(0, 0); @@ -136,8 +135,7 @@ void Character::setFacing(int32 facing) { _facing = facing; } -void Character::forcePosition(int32 x, int32 y) { - +void Character::forcePosition(int16 x, int16 y) { debugC(5, kDebugCharacter, "forcePosition(%d, %d)", x, y); setPosition(x, y); @@ -145,7 +143,7 @@ void Character::forcePosition(int32 x, int32 y) { _finalY = y; } -void Character::setPosition(int32 x, int32 y) { +void Character::setPosition(int16 x, int16 y) { debugC(5, kDebugCharacter, "setPosition(%d, %d)", x, y); _x = x; @@ -155,7 +153,7 @@ void Character::setPosition(int32 x, int32 y) { return; } -bool Character::walkTo(int32 newPosX, int32 newPosY) { +bool Character::walkTo(int16 newPosX, int16 newPosY) { debugC(1, kDebugCharacter, "walkTo(%d, %d)", newPosX, newPosY); if (!_visible) @@ -167,9 +165,9 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) { _vm->getPathFinding()->resetBlockingRects(); // don't allow flux to go at the same position as drew - if (_id == 1 ) { - int32 sizeX = MAX<int32>(5, 30 * _vm->getDrew()->getScale() / 1024); - int32 sizeY = MAX<int32>(2, 20 * _vm->getDrew()->getScale() / 1024); + if (_id == 1) { + int16 sizeX = MAX<int16>(5, 30 * _vm->getDrew()->getScale() / 1024); + int16 sizeY = MAX<int16>(2, 20 * _vm->getDrew()->getScale() / 1024); _vm->getPathFinding()->addBlockingEllipse(_vm->getDrew()->getFinalX(), _vm->getDrew()->getFinalY(), sizeX, sizeY); } @@ -179,16 +177,14 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) { if (_vm->getPathFinding()->findPath(_x, _y, _finalX, _finalY)) { - int32 localFinalX = _finalX; - int32 localFinalY = _finalY; + int16 localFinalX = _finalX; + int16 localFinalY = _finalY; int32 smoothDx = 0; int32 smoothDy = 0; - for (int32 a = 0; a < _vm->getPathFinding()->getPathNodeCount(); a++) { - _currentPathX[a] = _vm->getPathFinding()->getPathNodeX(a); - _currentPathY[a] = _vm->getPathFinding()->getPathNodeY(a); - } - _currentPathNodeCount = _vm->getPathFinding()->getPathNodeCount(); + _currentPath.clear(); + for (uint32 a = 0; a < _vm->getPathFinding()->getPathNodeCount(); a++) + _currentPath.push_back(Common::Point(_vm->getPathFinding()->getPathNodeX(a), _vm->getPathFinding()->getPathNodeY(a))); _currentPathNode = 0; stopSpecialAnim(); @@ -203,12 +199,12 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) { int32 localWalkStamp = _currentWalkStamp; if (_blockingWalk) { - while ((_x != newPosX || _y != newPosY) && _currentPathNode < _currentPathNodeCount && !_vm->shouldQuitGame()) { - if (_currentPathNode < _currentPathNodeCount - 4) { - int32 delta = MIN<int32>(4, _currentPathNodeCount - _currentPathNode); + while ((_x != newPosX || _y != newPosY) && _currentPathNode < _currentPath.size() && !_vm->shouldQuitGame()) { + if (_currentPathNode < _currentPath.size() - 4) { + int32 delta = MIN<int32>(4, _currentPath.size() - _currentPathNode); - int32 dx = _currentPathX[_currentPathNode+delta] - _x; - int32 dy = _currentPathY[_currentPathNode+delta] - _y; + int16 dx = _currentPath[_currentPathNode+delta].x - _x; + int16 dy = _currentPath[_currentPathNode+delta].y - _y; // smooth the facing computation. It prevents some ugly flickering from happening if (!smoothDx && !smoothDy) { @@ -227,9 +223,9 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) { _numPixelToWalk += _speed * (_vm->getSystem()->getMillis() - _lastWalkTime) * _scale / 1024; _lastWalkTime = _vm->getSystem()->getMillis(); - while (_numPixelToWalk >= 1000 && _currentPathNode < _currentPathNodeCount) { - _x = _currentPathX[_currentPathNode]; - _y = _currentPathY[_currentPathNode]; + while (_numPixelToWalk >= 1000 && _currentPathNode < _currentPath.size()) { + _x = _currentPath[_currentPathNode].x; + _y = _currentPath[_currentPathNode].y; _currentPathNode += 1; _numPixelToWalk -= 1000; } @@ -245,7 +241,7 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) { playStandingAnim(); _flags &= ~0x1; _currentPathNode = 0; - _currentPathNodeCount = 0; + _currentPath.clear(); if (_x != localFinalX || _y != localFinalY) { return false; @@ -264,10 +260,11 @@ int32 Character::getFlag() { return _flags; } -int32 Character::getX() { +int16 Character::getX() { return _x; } -int32 Character::getY() { + +int16 Character::getY() { return _y; } @@ -348,12 +345,12 @@ void Character::stopSpecialAnim() { void Character::update(int32 timeIncrement) { debugC(5, kDebugCharacter, "update(%d)", timeIncrement); - if ((_flags & 0x1) && _currentPathNodeCount > 0) { - if (_currentPathNode < _currentPathNodeCount) { - if (_currentPathNode < _currentPathNodeCount - 10) { - int32 delta = MIN<int32>(10, _currentPathNodeCount - _currentPathNode); - int32 dx = _currentPathX[_currentPathNode+delta] - _x; - int32 dy = _currentPathY[_currentPathNode+delta] - _y; + if ((_flags & 0x1) && _currentPath.size() > 0) { + if (_currentPathNode < _currentPath.size()) { + if (_currentPathNode < _currentPath.size() - 10) { + int32 delta = MIN<int32>(10, _currentPath.size() - _currentPathNode); + int16 dx = _currentPath[_currentPathNode+delta].x - _x; + int16 dy = _currentPath[_currentPathNode+delta].y - _y; setFacing(getFacingFromDirection(dx, dy)); playWalkAnim(0, 0); } @@ -362,9 +359,9 @@ void Character::update(int32 timeIncrement) { _numPixelToWalk += _speed * (_vm->getSystem()->getMillis() - _lastWalkTime) * _scale / 1024; _lastWalkTime = _vm->getSystem()->getMillis(); - while (_numPixelToWalk > 1000 && _currentPathNode < _currentPathNodeCount) { - _x = _currentPathX[_currentPathNode]; - _y = _currentPathY[_currentPathNode]; + while (_numPixelToWalk > 1000 && _currentPathNode < _currentPath.size()) { + _x = _currentPath[_currentPathNode].x; + _y = _currentPath[_currentPathNode].y; _currentPathNode += 1; _numPixelToWalk -= 1000; } @@ -372,7 +369,7 @@ void Character::update(int32 timeIncrement) { } else { playStandingAnim(); _flags &= ~0x1; - _currentPathNodeCount = 0; + _currentPath.clear(); } } @@ -527,7 +524,7 @@ void Character::update(int32 timeIncrement) { } // adapted from Kyra -int32 Character::getFacingFromDirection(int32 dx, int32 dy) { +int32 Character::getFacingFromDirection(int16 dx, int16 dy) { debugC(4, kDebugCharacter, "getFacingFromDirection(%d, %d)", dx, dy); static const int facingTable[] = { @@ -638,7 +635,7 @@ void Character::load(Common::ReadStream *stream) { // "not visible" flag. if (_flags & 0x100) { _flags &= ~0x100; - setVisible(false); + setVisible(false); } } @@ -664,7 +661,7 @@ void Character::stopWalk() { _finalY = _y; _flags &= ~0x1; _currentPathNode = 0; - _currentPathNodeCount = 0; + _currentPath.clear(); } const SpecialCharacterAnimation *Character::getSpecialAnimation(int32 characterId, int32 animationId) { @@ -996,8 +993,8 @@ bool Character::loadShadowAnimation(const Common::String &animName) { } void Character::plotPath(Graphics::Surface& surface) { - for (int i = 0; i < _currentPathNodeCount; i++) { - *(byte *)surface.getBasePtr(_currentPathX[i], _currentPathY[i]) = ( i < _currentPathNode); + for (uint32 i = 0; i < _currentPath.size(); i++) { + *(byte *)surface.getBasePtr(_currentPath[i].x, _currentPath[i].y) = (i < _currentPathNode); } } @@ -1078,11 +1075,11 @@ void Character::setDefaultSpecialAnimationId(int32 defaultAnimationId) { _animSpecialDefaultId = defaultAnimationId; } -int32 Character::getFinalX() { +int16 Character::getFinalX() { return _finalX; } -int32 Character::getFinalY() { +int16 Character::getFinalY() { return _finalY; } diff --git a/engines/toon/character.h b/engines/toon/character.h index d06a6c060c..d33c314bf7 100644 --- a/engines/toon/character.h +++ b/engines/toon/character.h @@ -23,6 +23,9 @@ #ifndef TOON_CHARACTER_H #define TOON_CHARACTER_H +#include "common/array.h" +#include "common/rect.h" + #include "toon/toon.h" namespace Toon { @@ -65,13 +68,13 @@ public: virtual int32 getFlag(); virtual int32 getAnimFlag(); virtual void setAnimFlag(int32 flag); - virtual void setPosition(int32 x, int32 y); - virtual void forcePosition(int32 x, int32 y); - virtual int32 getX(); - virtual int32 getY(); - virtual int32 getFinalX(); - virtual int32 getFinalY(); - virtual bool walkTo(int32 newPosX, int32 newPosY); + virtual void setPosition(int16 x, int16 y); + virtual void forcePosition(int16 x, int16 y); + virtual int16 getX(); + virtual int16 getY(); + virtual int16 getFinalX(); + virtual int16 getFinalY(); + virtual bool walkTo(int16 newPosX, int16 newPosY); virtual bool getVisible(); virtual void setVisible(bool visible); virtual bool loadWalkAnimation(const Common::String &animName); @@ -99,7 +102,7 @@ public: virtual void resetScale() {} virtual void plotPath(Graphics::Surface& surface); - int32 getFacingFromDirection(int32 dx, int32 dy); + int32 getFacingFromDirection(int16 dx, int16 dy); static const SpecialCharacterAnimation *getSpecialAnimation(int32 characterId, int32 animationId); protected: @@ -112,11 +115,11 @@ protected: int32 _sceneAnimationId; int32 _lineToSayId; int32 _time; - int32 _x; - int32 _y; + int16 _x; + int16 _y; int32 _z; - int32 _finalX; - int32 _finalY; + int16 _finalX; + int16 _finalY; int32 _facing; int32 _flags; int32 _animFlags; @@ -137,10 +140,8 @@ protected: Animation *_shadowAnim; Animation *_specialAnim; - int32 _currentPathX[4096]; - int32 _currentPathY[4096]; - int32 _currentPathNodeCount; - int32 _currentPathNode; + Common::Array<Common::Point> _currentPath; + uint32 _currentPathNode; int32 _currentWalkStamp; }; diff --git a/engines/toon/drew.cpp b/engines/toon/drew.cpp index df5cfcfa03..dfd3f515fa 100644 --- a/engines/toon/drew.cpp +++ b/engines/toon/drew.cpp @@ -48,7 +48,7 @@ bool CharacterDrew::setupPalette() { return false; } -void CharacterDrew::setPosition(int32 x, int32 y) { +void CharacterDrew::setPosition(int16 x, int16 y) { debugC(5, kDebugCharacter, "setPosition(%d, %d)", x, y); _z = _vm->getLayerAtPoint(x, y); diff --git a/engines/toon/drew.h b/engines/toon/drew.h index 3357b99846..ff1b619125 100644 --- a/engines/toon/drew.h +++ b/engines/toon/drew.h @@ -35,7 +35,7 @@ public: virtual ~CharacterDrew(); bool setupPalette(); void playStandingAnim(); - void setPosition(int32 x, int32 y); + void setPosition(int16 x, int16 y); void resetScale(); void update(int32 timeIncrement); void playWalkAnim(int32 start, int32 end); diff --git a/engines/toon/flux.cpp b/engines/toon/flux.cpp index b752e65c82..70aa40fb36 100644 --- a/engines/toon/flux.cpp +++ b/engines/toon/flux.cpp @@ -45,7 +45,7 @@ void CharacterFlux::playStandingAnim() { _animationInstance->stopAnimation(); _animationInstance->setLooping(true); - //s/etVisible(true); + //setVisible(true); } void CharacterFlux::setVisible(bool visible) { @@ -99,7 +99,7 @@ int32 CharacterFlux::fixFacingForAnimation(int32 originalFacing, int32 animation return finalFacing; } -void CharacterFlux::setPosition(int32 x, int32 y) { +void CharacterFlux::setPosition(int16 x, int16 y) { debugC(5, kDebugCharacter, "setPosition(%d, %d)", x, y); _z = _vm->getLayerAtPoint(x, y); diff --git a/engines/toon/flux.h b/engines/toon/flux.h index c208bc5bda..1dc0d9c55f 100644 --- a/engines/toon/flux.h +++ b/engines/toon/flux.h @@ -34,7 +34,7 @@ public: CharacterFlux(ToonEngine *vm); virtual ~CharacterFlux(); - void setPosition(int32 x, int32 y); + void setPosition(int16 x, int16 y); void playStandingAnim(); void playWalkAnim(int32 start, int32 end); void update(int32 timeIncrement); diff --git a/engines/toon/path.cpp b/engines/toon/path.cpp index 2dd5fc45e2..7914aed595 100644 --- a/engines/toon/path.cpp +++ b/engines/toon/path.cpp @@ -60,12 +60,12 @@ void PathFindingHeap::clear() { memset(_data, 0, sizeof(HeapDataGrid) * _size); } -void PathFindingHeap::push(int32 x, int32 y, int32 weight) { +void PathFindingHeap::push(int16 x, int16 y, uint16 weight) { debugC(2, kDebugPath, "push(%d, %d, %d)", x, y, weight); if (_count == _size) { // Increase size by 50% - int newSize = _size + (_size >> 1) + 1; + uint32 newSize = _size + (_size / 2) + 1; HeapDataGrid *newData; newData = (HeapDataGrid *)realloc(_data, sizeof(HeapDataGrid) * newSize); @@ -84,13 +84,13 @@ void PathFindingHeap::push(int32 x, int32 y, int32 weight) { _data[_count]._weight = weight; _count++; - int32 lMax = _count-1; - int32 lT = 0; + uint32 lMax = _count - 1; + uint32 lT = 0; - while (1) { + while (true) { if (lMax <= 0) break; - lT = (lMax-1) / 2; + lT = (lMax - 1) / 2; if (_data[lT]._weight > _data[lMax]._weight) { HeapDataGrid temp; @@ -104,7 +104,7 @@ void PathFindingHeap::push(int32 x, int32 y, int32 weight) { } } -void PathFindingHeap::pop(int32 *x, int32 *y, int32 *weight) { +void PathFindingHeap::pop(int16 *x, int16 *y, uint16 *weight) { debugC(2, kDebugPath, "pop(x, y, weight)"); if (!_count) { @@ -120,13 +120,13 @@ void PathFindingHeap::pop(int32 *x, int32 *y, int32 *weight) { if (!_count) return; - int32 lMin = 0; - int32 lT = 0; + uint32 lMin = 0; + uint32 lT = 0; - while (1) { - lT = (lMin << 1) + 1; + while (true) { + lT = (lMin * 2) + 1; if (lT < _count) { - if (lT < _count-1) { + if (lT < _count - 1) { if (_data[lT + 1]._weight < _data[lT]._weight) lT++; } @@ -146,11 +146,11 @@ void PathFindingHeap::pop(int32 *x, int32 *y, int32 *weight) { } } -PathFinding::PathFinding(ToonEngine *vm) : _vm(vm) { +PathFinding::PathFinding() { _width = 0; _height = 0; _heap = new PathFindingHeap(); - _gridTemp = NULL; + _sq = NULL; _numBlockingRects = 0; } @@ -158,17 +158,29 @@ PathFinding::~PathFinding(void) { if (_heap) _heap->unload(); delete _heap; - delete[] _gridTemp; + delete[] _sq; } -bool PathFinding::isLikelyWalkable(int32 x, int32 y) { - for (int32 i = 0; i < _numBlockingRects; i++) { +void PathFinding::init(Picture *mask) { + debugC(1, kDebugPath, "init(mask)"); + + _width = mask->getWidth(); + _height = mask->getHeight(); + _currentMask = mask; + _heap->unload(); + _heap->init(500); + delete[] _sq; + _sq = new uint16[_width * _height]; +} + +bool PathFinding::isLikelyWalkable(int16 x, int16 y) { + for (uint8 i = 0; i < _numBlockingRects; i++) { if (_blockingRects[i][4] == 0) { if (x >= _blockingRects[i][0] && x <= _blockingRects[i][2] && y >= _blockingRects[i][1] && y < _blockingRects[i][3]) return false; } else { - int32 dx = abs(_blockingRects[i][0] - x); - int32 dy = abs(_blockingRects[i][1] - y); + int16 dx = abs(_blockingRects[i][0] - x); + int16 dy = abs(_blockingRects[i][1] - y); if ((dx << 8) / _blockingRects[i][2] < (1 << 8) && (dy << 8) / _blockingRects[i][3] < (1 << 8)) { return false; } @@ -177,15 +189,13 @@ bool PathFinding::isLikelyWalkable(int32 x, int32 y) { return true; } -bool PathFinding::isWalkable(int32 x, int32 y) { +bool PathFinding::isWalkable(int16 x, int16 y) { debugC(2, kDebugPath, "isWalkable(%d, %d)", x, y); - bool maskWalk = (_currentMask->getData(x, y) & 0x1f) > 0; - - return maskWalk; + return (_currentMask->getData(x, y) & 0x1f) > 0; } -int32 PathFinding::findClosestWalkingPoint(int32 xx, int32 yy, int32 *fxx, int32 *fyy, int origX, int origY) { +bool PathFinding::findClosestWalkingPoint(int16 xx, int16 yy, int16 *fxx, int16 *fyy, int16 origX, int16 origY) { debugC(1, kDebugPath, "findClosestWalkingPoint(%d, %d, fxx, fyy, %d, %d)", xx, yy, origX, origY); int32 currentFound = -1; @@ -197,8 +207,8 @@ int32 PathFinding::findClosestWalkingPoint(int32 xx, int32 yy, int32 *fxx, int32 if (origY == -1) origY = yy; - for (int y = 0; y < _height; y++) { - for (int x = 0; x < _width; x++) { + for (int16 y = 0; y < _height; y++) { + for (int16 x = 0; x < _width; x++) { if (isWalkable(x, y) && isLikelyWalkable(x, y)) { int32 ndist = (x - xx) * (x - xx) + (y - yy) * (y - yy); int32 ndist2 = (x - origX) * (x - origX) + (y - origY) * (y - origY); @@ -214,15 +224,15 @@ int32 PathFinding::findClosestWalkingPoint(int32 xx, int32 yy, int32 *fxx, int32 if (currentFound != -1) { *fxx = currentFound % _width; *fyy = currentFound / _width; - return 1; + return true; } else { *fxx = 0; *fyy = 0; - return 0; + return false; } } -bool PathFinding::walkLine(int32 x, int32 y, int32 x2, int32 y2) { +void PathFinding::walkLine(int16 x, int16 y, int16 x2, int16 y2) { uint32 bx = x << 16; int32 dx = x2 - x; uint32 by = y << 16; @@ -238,24 +248,17 @@ bool PathFinding::walkLine(int32 x, int32 y, int32 x2, int32 y2) { 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++; + _tempPath.clear(); + for (int32 i = t; i > 0; i--) { + _tempPath.insert_at(0, Common::Point(bx >> 16, by >> 16)); bx += cdx; by += cdy; - i--; } - _tempPathX[0] = x2; - _tempPathY[0] = y2; - - return true; + _tempPath.insert_at(0, Common::Point(x2, y2)); } -bool PathFinding::lineIsWalkable(int32 x, int32 y, int32 x2, int32 y2) { +bool PathFinding::lineIsWalkable(int16 x, int16 y, int16 x2, int16 y2) { uint32 bx = x << 16; int32 dx = x2 - x; uint32 by = y << 16; @@ -271,27 +274,26 @@ bool PathFinding::lineIsWalkable(int32 x, int32 y, int32 x2, int32 y2) { int32 cdx = (dx << 16) / t; int32 cdy = (dy << 16) / t; - int32 i = t; - while (i) { + for (int32 i = t; i > 0; i--) { if (!isWalkable(bx >> 16, by >> 16)) return false; bx += cdx; by += cdy; - i--; } return true; } -int32 PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) { + +bool PathFinding::findPath(int16 x, int16 y, int16 destx, int16 desty) { debugC(1, kDebugPath, "findPath(%d, %d, %d, %d)", x, y, destx, desty); if (x == destx && y == desty) { - _gridPathCount = 0; + _tempPath.clear(); return true; } // ignore path finding if the character is outside the screen if (x < 0 || x > 1280 || y < 0 || y > 400 || destx < 0 || destx > 1280 || desty < 0 || desty > 400) { - _gridPathCount = 0; + _tempPath.clear(); return true; } @@ -302,40 +304,45 @@ int32 PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) { } // no direct line, we use the standard A* algorithm - memset(_gridTemp , 0, _width * _height * sizeof(int32)); + memset(_sq , 0, _width * _height * sizeof(uint16)); _heap->clear(); - int32 curX = x; - int32 curY = y; - int32 curWeight = 0; - int32 *sq = _gridTemp; + int16 curX = x; + int16 curY = y; + uint16 curWeight = 0; - sq[curX + curY *_width] = 1; + _sq[curX + curY *_width] = 1; _heap->push(curX, curY, abs(destx - x) + abs(desty - y)); - int wei = 0; while (_heap->getCount()) { - wei = 0; _heap->pop(&curX, &curY, &curWeight); - int curNode = curX + curY * _width; + int32 curNode = curX + curY * _width; - int32 endX = MIN<int32>(curX + 1, _width - 1); - int32 endY = MIN<int32>(curY + 1, _height - 1); - int32 startX = MAX<int32>(curX - 1, 0); - int32 startY = MAX<int32>(curY - 1, 0); + int16 endX = MIN<int16>(curX + 1, _width - 1); + int16 endY = MIN<int16>(curY + 1, _height - 1); + int16 startX = MAX<int16>(curX - 1, 0); + int16 startY = MAX<int16>(curY - 1, 0); bool next = false; - for (int32 px = startX; px <= endX && !next; px++) { - for (int py = startY; py <= endY && !next; py++) { + for (int16 px = startX; px <= endX && !next; px++) { + for (int16 py = startY; py <= endY && !next; py++) { if (px != curX || py != curY) { - wei = ((abs(px - curX) + abs(py - curY))); + uint16 wei = abs(px - curX) + abs(py - curY); - int32 curPNode = px + py * _width; if (isWalkable(px, py)) { // walkable ? - int sum = sq[curNode] + wei * (1 + (isLikelyWalkable(px, py) ? 5 : 0)); - if (sq[curPNode] > sum || !sq[curPNode]) { - int newWeight = abs(destx - px) + abs(desty - py); - sq[curPNode] = sum; - _heap->push(px, py, sq[curPNode] + newWeight); + int32 curPNode = px + py * _width; + uint32 sum = _sq[curNode] + wei * (1 + (isLikelyWalkable(px, py) ? 5 : 0)); + if (sum > (uint32)0xFFFF) { + warning("PathFinding::findPath sum exceeds maximum representable!"); + sum = (uint32)0xFFFF; + } + if (_sq[curPNode] > sum || !_sq[curPNode]) { + _sq[curPNode] = sum; + uint32 newWeight = _sq[curPNode] + abs(destx - px) + abs(desty - py); + if (newWeight > (uint32)0xFFFF) { + warning("PathFinding::findPath newWeight exceeds maximum representable!"); + newWeight = (uint16)0xFFFF; + } + _heap->push(px, py, newWeight); if (!newWeight) next = true; // we found it ! } @@ -346,49 +353,37 @@ int32 PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) { } // let's see if we found a result ! - if (!_gridTemp[destx + desty * _width]) { + if (!_sq[destx + desty * _width]) { // didn't find anything - _gridPathCount = 0; + _tempPath.clear(); return false; } curX = destx; curY = desty; - int32 *retPathX = (int32 *)malloc(4096 * sizeof(int32)); - int32 *retPathY = (int32 *)malloc(4096 * sizeof(int32)); - if (!retPathX || !retPathY) { - free(retPathX); - free(retPathY); - - error("[PathFinding::findPath] Cannot allocate pathfinding buffers"); - } - - int32 numpath = 0; + Common::Array<Common::Point> retPath; + retPath.push_back(Common::Point(curX, curY)); - retPathX[numpath] = curX; - retPathY[numpath] = curY; - numpath++; - int32 bestscore = sq[destx + desty * _width]; + uint16 bestscore = _sq[destx + desty * _width]; - while (1) { - int32 bestX = -1; - int32 bestY = -1; + bool retVal = false; + while (true) { + int16 bestX = -1; + int16 bestY = -1; - int32 endX = MIN<int32>(curX + 1, _width - 1); - int32 endY = MIN<int32>(curY + 1, _height - 1); - int32 startX = MAX<int32>(curX - 1, 0); - int32 startY = MAX<int32>(curY - 1, 0); + int16 endX = MIN<int16>(curX + 1, _width - 1); + int16 endY = MIN<int16>(curY + 1, _height - 1); + int16 startX = MAX<int16>(curX - 1, 0); + int16 startY = MAX<int16>(curY - 1, 0); - for (int32 px = startX; px <= endX; px++) { - for (int32 py = startY; py <= endY; py++) { + for (int16 px = startX; px <= endX; px++) { + for (int16 py = startY; py <= endY; py++) { if (px != curX || py != curY) { - wei = abs(px - curX) + abs(py - curY); - - int PNode = px + py * _width; - if (sq[PNode] && (isWalkable(px, py))) { - if (sq[PNode] < bestscore) { - bestscore = sq[PNode]; + int32 PNode = px + py * _width; + if (_sq[PNode] && (isWalkable(px, py))) { + if (_sq[PNode] < bestscore) { + bestscore = _sq[PNode]; bestX = px; bestY = py; } @@ -397,57 +392,33 @@ int32 PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) { } } - if (bestX < 0 || bestY < 0) { - free(retPathX); - free(retPathY); - - return 0; - } + if (bestX < 0 || bestY < 0) + break; - retPathX[numpath] = bestX; - retPathY[numpath] = bestY; - numpath++; + retPath.push_back(Common::Point(bestX, bestY)); if ((bestX == x && bestY == y)) { - _gridPathCount = numpath; - - memcpy(_tempPathX, retPathX, sizeof(int32) * numpath); - memcpy(_tempPathY, retPathY, sizeof(int32) * numpath); - - free(retPathX); - free(retPathY); + _tempPath.clear(); + for (uint32 i = 0; i < retPath.size(); i++) + _tempPath.push_back(retPath[i]); - return true; + retVal = true; + break; } curX = bestX; curY = bestY; } - free(retPathX); - free(retPathY); - - return false; + return retVal; } -void PathFinding::init(Picture *mask) { - debugC(1, kDebugPath, "init(mask)"); - - _width = mask->getWidth(); - _height = mask->getHeight(); - _currentMask = mask; - _heap->unload(); - _heap->init(500); - delete[] _gridTemp; - _gridTemp = new int32[_width*_height]; -} - -void PathFinding::resetBlockingRects() { - _numBlockingRects = 0; -} - -void PathFinding::addBlockingRect(int32 x1, int32 y1, int32 x2, int32 y2) { +void PathFinding::addBlockingRect(int16 x1, int16 y1, int16 x2, int16 y2) { debugC(1, kDebugPath, "addBlockingRect(%d, %d, %d, %d)", x1, y1, x2, y2); + if (_numBlockingRects >= kMaxBlockingRects) { + warning("Maximum number of %d Blocking Rects reached!", kMaxBlockingRects); + return; + } _blockingRects[_numBlockingRects][0] = x1; _blockingRects[_numBlockingRects][1] = y1; @@ -457,8 +428,12 @@ void PathFinding::addBlockingRect(int32 x1, int32 y1, int32 x2, int32 y2) { _numBlockingRects++; } -void PathFinding::addBlockingEllipse(int32 x1, int32 y1, int32 w, int32 h) { - debugC(1, kDebugPath, "addBlockingRect(%d, %d, %d, %d)", x1, y1, w, h); +void PathFinding::addBlockingEllipse(int16 x1, int16 y1, int16 w, int16 h) { + debugC(1, kDebugPath, "addBlockingEllipse(%d, %d, %d, %d)", x1, y1, w, h); + if (_numBlockingRects >= kMaxBlockingRects) { + warning("Maximum number of %d Blocking Rects reached!", kMaxBlockingRects); + return; + } _blockingRects[_numBlockingRects][0] = x1; _blockingRects[_numBlockingRects][1] = y1; @@ -468,16 +443,4 @@ void PathFinding::addBlockingEllipse(int32 x1, int32 y1, int32 w, int32 h) { _numBlockingRects++; } -int32 PathFinding::getPathNodeCount() const { - return _gridPathCount; -} - -int32 PathFinding::getPathNodeX(int32 nodeId) const { - return _tempPathX[ _gridPathCount - nodeId - 1]; -} - -int32 PathFinding::getPathNodeY(int32 nodeId) const { - return _tempPathY[ _gridPathCount - nodeId - 1]; -} - } // End of namespace Toon diff --git a/engines/toon/path.h b/engines/toon/path.h index 2de58064f0..59f74ef286 100644 --- a/engines/toon/path.h +++ b/engines/toon/path.h @@ -23,72 +23,75 @@ #ifndef TOON_PATH_H #define TOON_PATH_H +#include "common/array.h" +#include "common/rect.h" + #include "toon/toon.h" namespace Toon { // binary heap system for fast A* -struct HeapDataGrid { - int16 _x, _y; - int16 _weight; -}; - class PathFindingHeap { public: PathFindingHeap(); ~PathFindingHeap(); - void push(int32 x, int32 y, int32 weight); - void pop(int32 *x, int32 *y, int32 *weight); + void push(int16 x, int16 y, uint16 weight); + void pop(int16 *x, int16 *y, uint16 *weight); void init(int32 size); void clear(); void unload(); - int32 getCount() { return _count; } + uint32 getCount() { return _count; } private: + struct HeapDataGrid { + int16 _x, _y; + uint16 _weight; + }; + HeapDataGrid *_data; - int32 _size; - int32 _count; + uint32 _size; + uint32 _count; }; class PathFinding { public: - PathFinding(ToonEngine *vm); + PathFinding(); ~PathFinding(); - int32 findPath(int32 x, int32 y, int32 destX, int32 destY); - int32 findClosestWalkingPoint(int32 xx, int32 yy, int32 *fxx, int32 *fyy, int origX = -1, int origY = -1); - 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(); - void addBlockingRect(int32 x1, int32 y1, int32 x2, int32 y2); - void addBlockingEllipse(int32 x1, int32 y1, int32 w, int32 h); + bool findPath(int16 x, int16 y, int16 destX, int16 destY); + bool findClosestWalkingPoint(int16 xx, int16 yy, int16 *fxx, int16 *fyy, int16 origX = -1, int16 origY = -1); + bool isWalkable(int16 x, int16 y); + bool isLikelyWalkable(int16 x, int16 y); + bool lineIsWalkable(int16 x, int16 y, int16 x2, int16 y2); + void walkLine(int16 x, int16 y, int16 x2, int16 y2); + + void resetBlockingRects() { _numBlockingRects = 0; } + void addBlockingRect(int16 x1, int16 y1, int16 x2, int16 y2); + void addBlockingEllipse(int16 x1, int16 y1, int16 w, int16 h); + + uint32 getPathNodeCount() const { return _tempPath.size(); } + int16 getPathNodeX(uint32 nodeId) const { return _tempPath[(_tempPath.size() - 1) - nodeId].x; } + int16 getPathNodeY(uint32 nodeId) const { return _tempPath[(_tempPath.size() - 1) - nodeId].y; } + +private: + static const uint8 kMaxBlockingRects = 16; - int32 getPathNodeCount() const; - int32 getPathNodeX(int32 nodeId) const; - int32 getPathNodeY(int32 nodeId) const; -protected: Picture *_currentMask; PathFindingHeap *_heap; - int32 *_gridTemp; - int32 _width; - int32 _height; + uint16 *_sq; + int16 _width; + int16 _height; - int32 _tempPathX[4096]; - int32 _tempPathY[4096]; - int32 _blockingRects[16][5]; - int32 _numBlockingRects; - int32 _allocatedGridPathCount; - int32 _gridPathCount; + Common::Array<Common::Point> _tempPath; - ToonEngine *_vm; + int16 _blockingRects[kMaxBlockingRects][5]; + uint8 _numBlockingRects; }; } // End of namespace Toon diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp index be298e1236..416daa1fe8 100644 --- a/engines/toon/toon.cpp +++ b/engines/toon/toon.cpp @@ -100,7 +100,7 @@ void ToonEngine::init() { syncSoundSettings(); - _pathFinding = new PathFinding(this); + _pathFinding = new PathFinding(); resources()->openPackage("LOCAL.PAK"); resources()->openPackage("ONETIME.PAK"); @@ -168,7 +168,7 @@ void ToonEngine::waitForScriptStep() { // Wait after a specified number of script steps when executing a script // to lower CPU usage if (++_scriptStep >= 40) { - g_system->delayMillis(1); + _system->delayMillis(1); _scriptStep = 0; } } @@ -1488,7 +1488,7 @@ void ToonEngine::clickEvent() { } if (!currentHot) { - int32 xx, yy; + int16 xx, yy; if (_gameState->_inCutaway || _gameState->_inInventory || _gameState->_inCloseUp) return; @@ -2976,8 +2976,7 @@ bool ToonEngine::saveGame(int32 slot, const Common::String &saveGameDesc) { return false; // dialog aborted Common::String savegameFile = getSavegameName(savegameId); - Common::SaveFileManager *saveMan = g_system->getSavefileManager(); - Common::OutSaveFile *saveFile = saveMan->openForSaving(savegameFile); + Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(savegameFile); if (!saveFile) return false; @@ -3062,8 +3061,7 @@ bool ToonEngine::loadGame(int32 slot) { return false; // dialog aborted Common::String savegameFile = getSavegameName(savegameId); - Common::SaveFileManager *saveMan = g_system->getSavefileManager(); - Common::InSaveFile *loadFile = saveMan->openForLoading(savegameFile); + Common::InSaveFile *loadFile = _saveFileMan->openForLoading(savegameFile); if (!loadFile) return false; |