diff options
author | Robert Špalek | 2009-11-01 12:57:06 +0000 |
---|---|---|
committer | Robert Špalek | 2009-11-01 12:57:06 +0000 |
commit | c1cc230e4b41c9e6fff7b531158e50d0bc18a57a (patch) | |
tree | 1404ac074fc40d4dc3afa13811c58669d3eeec86 | |
parent | 5c7a120471000a1e048c5bc7688af77e95886caa (diff) | |
download | scummvm-rg350-c1cc230e4b41c9e6fff7b531158e50d0bc18a57a.tar.gz scummvm-rg350-c1cc230e4b41c9e6fff7b531158e50d0bc18a57a.tar.bz2 scummvm-rg350-c1cc230e4b41c9e6fff7b531158e50d0bc18a57a.zip |
Debugged computation and displaying of optimal walking paths
svn-id: r45597
-rw-r--r-- | engines/draci/animation.cpp | 5 | ||||
-rw-r--r-- | engines/draci/animation.h | 15 | ||||
-rw-r--r-- | engines/draci/draci.cpp | 18 | ||||
-rw-r--r-- | engines/draci/game.cpp | 42 | ||||
-rw-r--r-- | engines/draci/game.h | 1 | ||||
-rw-r--r-- | engines/draci/walking.cpp | 21 | ||||
-rw-r--r-- | engines/draci/walking.h | 2 |
7 files changed, 76 insertions, 28 deletions
diff --git a/engines/draci/animation.cpp b/engines/draci/animation.cpp index a0f983100b..560f03ffcf 100644 --- a/engines/draci/animation.cpp +++ b/engines/draci/animation.cpp @@ -163,6 +163,11 @@ void Animation::addFrame(Drawable *frame, const SoundSample *sample) { _samples.push_back(sample); } +void Animation::replaceFrame(int i, Drawable *frame, const SoundSample *sample) { + _frames[i] = frame; + _samples[i] = sample; +} + Drawable *Animation::getCurrentFrame() { // If there are no frames stored, return NULL return _frames.size() > 0 ? _frames[_currentFrame] : NULL; diff --git a/engines/draci/animation.h b/engines/draci/animation.h index 6805822640..11cdc3d414 100644 --- a/engines/draci/animation.h +++ b/engines/draci/animation.h @@ -38,12 +38,14 @@ namespace Draci { enum { kOverlayImage = -1, kWalkingMapOverlay = -2, - kTitleText = -3, - kSpeechText = -4, - kInventorySprite = -5, - kDialogueLinesID = -6, - kUnused = -10, - kInventoryItemsID = -11 + kWalkingShortestPathOverlay = -3, + kWalkingObliquePathOverlay = -4, + kTitleText = -5, + kSpeechText = -6, + kInventorySprite = -7, + kDialogueLinesID = -8, + kUnused = -12, + kInventoryItemsID = -13 }; /** @@ -72,6 +74,7 @@ public: void drawFrame(Surface *surface); void addFrame(Drawable *frame, const SoundSample *sample); + void replaceFrame(int i, Drawable *frame, const SoundSample *sample); Drawable *getCurrentFrame(); Drawable *getFrame(int frameNum); void setCurrentFrame(uint frame); diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index 6f99a38830..fec53392d6 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -263,6 +263,15 @@ void DraciEngine::handleEvents() { case Common::KEYCODE_w: // Show walking map toggle _showWalkingMap = !_showWalkingMap; + if (_showWalkingMap) { + _anims->play(kWalkingMapOverlay); + _anims->play(kWalkingShortestPathOverlay); + _anims->play(kWalkingObliquePathOverlay); + } else { + _anims->stop(kWalkingMapOverlay); + _anims->stop(kWalkingShortestPathOverlay); + _anims->stop(kWalkingObliquePathOverlay); + } break; case Common::KEYCODE_q: _game->setWantQuickHero(!_game->getWantQuickHero()); @@ -286,15 +295,6 @@ void DraciEngine::handleEvents() { _mouse->handleEvent(event); } } - - // Show walking map overlay - // If the walking map overlay is already in the wanted state don't - // start / stop it constantly - if (_showWalkingMap && !_anims->getAnimation(kWalkingMapOverlay)->isPlaying()) { - _anims->play(kWalkingMapOverlay); - } else if (!_showWalkingMap && _anims->getAnimation(kWalkingMapOverlay)->isPlaying()) { - _anims->stop(kWalkingMapOverlay); - } } DraciEngine::~DraciEngine() { diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index 9f15a1e7fc..89622beff1 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -39,6 +39,12 @@ static const Common::String dialoguePath("ROZH"); static double real_to_double(byte real[6]); +enum { + kWalkingMapOverlayColour = 2, + kWalkingShortestPathOverlayColour = 120, + kWalkingObliquePathOverlayColour = 73 +}; + Game::Game(DraciEngine *vm) : _vm(vm) { uint i; @@ -932,6 +938,14 @@ void Game::playHeroAnimation(int anim_index) { _vm->_anims->play(animID); } +void Game::redrawWalkingPath(int id, byte colour, const WalkingMap::Path &path) { + Animation *anim = _vm->_anims->getAnimation(id); + Sprite *ov = _walkingMap.newOverlayFromPath(path, colour); + delete anim->getFrame(0); + anim->replaceFrame(0, ov, NULL); + anim->markDirtyRect(_vm->_screen->getSurface()); +} + void Game::walkHero(int x, int y, SightDirection dir) { // Needed for the map room with empty walking map. For some reason, // findNearestWalkable() takes several seconds with 100% CPU to finish @@ -939,11 +953,20 @@ void Game::walkHero(int x, int y, SightDirection dir) { if (!_currentRoom._heroOn) return; + Common::Point oldHero = _hero; Surface *surface = _vm->_screen->getSurface(); _hero = _walkingMap.findNearestWalkable(x, y, surface->getDimensions()); debugC(3, kDraciLogicDebugLevel, "Walk to x: %d y: %d", _hero.x, _hero.y); // FIXME: Need to add proper walking (this only warps the dragon to position) + // Compute the shortest and obliqued path. + WalkingMap::Path shortestPath, obliquePath; + _walkingMap.findShortestPath(oldHero.x, oldHero.y, _hero.x, _hero.y, &shortestPath); + _walkingMap.obliquePath(shortestPath, &obliquePath); + + redrawWalkingPath(kWalkingShortestPathOverlay, kWalkingShortestPathOverlayColour, shortestPath); + redrawWalkingPath(kWalkingObliquePathOverlay, kWalkingObliquePathOverlayColour, obliquePath); + Movement movement = kStopRight; switch (dir) { case kDirectionLeft: @@ -1060,6 +1083,19 @@ void Game::loadRoom(int roomNum) { // Load the walking map loadWalkingMap(getMapID()); + // Add overlays for the walking map and shortest/obliqued paths. + Animation *map = _vm->_anims->addAnimation(kWalkingMapOverlay, 256, _vm->_showWalkingMap); + Sprite *ov = _walkingMap.newOverlayFromMap(kWalkingMapOverlayColour); + map->addFrame(ov, NULL); + + Animation *sPath = _vm->_anims->addAnimation(kWalkingShortestPathOverlay, 257, _vm->_showWalkingMap); + Animation *oPath = _vm->_anims->addAnimation(kWalkingObliquePathOverlay, 258, _vm->_showWalkingMap); + WalkingMap::Path emptyPath; + ov = _walkingMap.newOverlayFromPath(emptyPath, 0); + sPath->addFrame(ov, NULL); + ov = _walkingMap.newOverlayFromPath(emptyPath, 0); + oPath->addFrame(ov, NULL); + // Load the room's objects for (uint i = 0; i < _info._numObjects; ++i) { debugC(7, kDraciLogicDebugLevel, @@ -1095,10 +1131,6 @@ void Game::loadRoom(int roomNum) { // Set room palette f = _vm->_paletteArchive->getFile(_currentRoom._palette); _vm->_screen->setPalette(f->_data, 0, kNumColours); - - Animation *map = _vm->_anims->addAnimation(kWalkingMapOverlay, 255, false); - Sprite *ov = _walkingMap.newOverlayFromMap(); - map->addFrame(ov, NULL); } int Game::loadAnimation(uint animNum, uint z) { @@ -1284,6 +1316,8 @@ void Game::enterNewRoom(bool force_reload) { // Delete walking map testing overlay _vm->_anims->deleteAnimation(kWalkingMapOverlay); + _vm->_anims->deleteAnimation(kWalkingShortestPathOverlay); + _vm->_anims->deleteAnimation(kWalkingObliquePathOverlay); // TODO: Make objects capable of stopping their own animations const GameObject *dragon = getObject(kDragonObject); diff --git a/engines/draci/game.h b/engines/draci/game.h index d8155dbcae..3ac27a2997 100644 --- a/engines/draci/game.h +++ b/engines/draci/game.h @@ -321,6 +321,7 @@ private: void enterNewRoom(bool force_reload); void loadRoom(int roomNum); void runGateProgram(int gate); + void redrawWalkingPath(int id, byte colour, const WalkingMap::Path &path); DraciEngine *_vm; diff --git a/engines/draci/walking.cpp b/engines/draci/walking.cpp index c08e97346c..ad1642132e 100644 --- a/engines/draci/walking.cpp +++ b/engines/draci/walking.cpp @@ -57,7 +57,7 @@ bool WalkingMap::isWalkable(int x, int y) const { return getPixel(x / _deltaX, y / _deltaY); } -Sprite *WalkingMap::newOverlayFromMap() const { +Sprite *WalkingMap::newOverlayFromMap(byte colour) const { // HACK: Create a visible overlay from the walking map so we can test it byte *wlk = new byte[_realWidth * _realHeight]; memset(wlk, 255, _realWidth * _realHeight); @@ -65,7 +65,7 @@ Sprite *WalkingMap::newOverlayFromMap() const { for (int i = 0; i < _mapWidth; ++i) { for (int j = 0; j < _mapHeight; ++j) { if (getPixel(i, j)) { - drawOverlayRectangle(i, j, 2, wlk); + drawOverlayRectangle(i, j, colour, wlk); } } } @@ -274,6 +274,9 @@ bool WalkingMap::findShortestPath(int x1, int y1, int x2, int y2, WalkingMap::Pa void WalkingMap::obliquePath(const WalkingMap::Path& path, WalkingMap::Path *obliquedPath) const { // Prune the path to only contain vertices where the direction is changing. obliquedPath->clear(); + if (path.empty()) { + return; + } obliquedPath->push_back(path[0]); uint index = 1; while (index < path.size()) { @@ -315,8 +318,8 @@ void WalkingMap::obliquePath(const WalkingMap::Path& path, WalkingMap::Path *obl bool allPointsOk = true; // Testing only points between (i.e., without the end-points) is OK. for (int step = 1; step < steps; ++step) { - const int x = (v1.x * (steps-step) + v3.x * step) / steps; - const int y = (v1.y * (steps-step) + v3.y * step) / steps; + const int x = (v1.x * (steps-step) + v3.x * step + steps/2) / steps; + const int y = (v1.y * (steps-step) + v3.y * step + steps/2) / steps; if (!getPixel(x, y)) { allPointsOk = false; break; @@ -340,15 +343,17 @@ Sprite *WalkingMap::newOverlayFromPath(const WalkingMap::Path &path, byte colour // Draw only points in the interval [v1, v2). These half-open // half-closed intervals connect all the way to the last point. for (int step = 0; step < steps; ++step) { - const int x = (v1.x * (steps-step) + v2.x * step) / steps; - const int y = (v1.y * (steps-step) + v2.y * step) / steps; + const int x = (v1.x * (steps-step) + v2.x * step + steps/2) / steps; + const int y = (v1.y * (steps-step) + v2.y * step + steps/2) / steps; drawOverlayRectangle(x, y, colour, wlk); } } // Draw the last point. This works also when the path has no segment, // but just one point. - const PathVertex &vLast = path[path.size()-1]; - drawOverlayRectangle(vLast.x, vLast.y, colour, wlk); + if (path.size() > 0) { + const PathVertex &vLast = path[path.size()-1]; + drawOverlayRectangle(vLast.x, vLast.y, colour, wlk); + } Sprite *ov = new Sprite(_realWidth, _realHeight, wlk, 0, 0, false); // ov has taken the ownership of wlk. diff --git a/engines/draci/walking.h b/engines/draci/walking.h index ed6d95ca85..161f16d441 100644 --- a/engines/draci/walking.h +++ b/engines/draci/walking.h @@ -49,7 +49,7 @@ public: bool getPixel(int x, int y) const; bool isWalkable(int x, int y) const; - Sprite *newOverlayFromMap() const; + Sprite *newOverlayFromMap(byte colour) const; Common::Point findNearestWalkable(int x, int y, Common::Rect searchRect) const; typedef Common::Array<PathVertex> Path; |