diff options
author | Paul Gilbert | 2015-03-24 22:24:45 -0400 |
---|---|---|
committer | Paul Gilbert | 2015-03-24 22:24:45 -0400 |
commit | 03a969bd0f696f9a7fa0dc56c47c2b05d28a5a47 (patch) | |
tree | dd1a84a328984d0d53f598168371575e9b87cd29 /engines/sherlock | |
parent | 97e58fb0171af885019d997493db33fab9af0091 (diff) | |
download | scummvm-rg350-03a969bd0f696f9a7fa0dc56c47c2b05d28a5a47.tar.gz scummvm-rg350-03a969bd0f696f9a7fa0dc56c47c2b05d28a5a47.tar.bz2 scummvm-rg350-03a969bd0f696f9a7fa0dc56c47c2b05d28a5a47.zip |
SHERLOCK: Implementing walk code
Diffstat (limited to 'engines/sherlock')
-rw-r--r-- | engines/sherlock/people.cpp | 127 | ||||
-rw-r--r-- | engines/sherlock/people.h | 1 | ||||
-rw-r--r-- | engines/sherlock/scene.cpp | 56 | ||||
-rw-r--r-- | engines/sherlock/scene.h | 6 | ||||
-rw-r--r-- | engines/sherlock/sherlock.cpp | 3 | ||||
-rw-r--r-- | engines/sherlock/user_interface.cpp | 6 | ||||
-rw-r--r-- | engines/sherlock/user_interface.h | 2 |
7 files changed, 185 insertions, 16 deletions
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 8a8dcb5245..ca840bb5b1 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -58,6 +58,7 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _allowWalkAbort = false; _portraitLoaded = false; _clearingThePortrait = false; + _srcZone = _destZone = 0; } People::~People() { @@ -143,7 +144,7 @@ void People::setWalking() { // If the player is already close to the given destination that no // walking is needed, move to the next straight line segment in the // overall walking route, if there is one - for (;;) { + do { // Since we want the player to be centered on the destination they // clicked, but characters draw positions start at their left, move // the destination half the character width to draw him centered @@ -306,13 +307,131 @@ void People::gotoStand(Sprite &sprite) { _allowWalkAbort = true; } +/** + * Walk to the co-ordinates passed, and then face the given direction + */ void People::walkToCoords(const Common::Point &destPos, int destDir) { - // TODO - warning("TODO: walkToCoords"); + Events &events = *_vm->_events; + Scene &scene = *_vm->_scene; + Talk &talk = *_vm->_talk; + + CursorId oldCursor = events.getCursor(); + events.setCursor(WAIT); + + _walkDest = Common::Point(destPos.x / 100 + 10, destPos.y / 100); + _allowWalkAbort = true; + goAllTheWay(); + + // Keep calling doBgAnim until the walk is done + do { + events.pollEventsAndWait(); + scene.doBgAnim(); + } while (!_vm->shouldQuit() && _player._walkCount); + + if (!talk._talkToAbort) { + // Put player exactly on destination position, and set direction + _player._position = destPos; + _player._sequenceNumber = destDir; + gotoStand(_player); + + // Draw Holmes facing the new direction + scene.doBgAnim(); + + if (!talk._talkToAbort) + events.setCursor(oldCursor); + } } +/** + * Called to set the character walking to the current cursor location. + * It uses the zones and the inter-zone points to determine a series + * of steps to walk to get to that position. + */ void People::goAllTheWay() { - // TODO + Scene &scene = *_vm->_scene; + Common::Point srcPt(_player._position.x / 100 + _player.frameWidth() / 2, + _player._position.y / 100); + + // Get the zone the player is currently in + _srcZone = scene.whichZone(srcPt); + if (_srcZone == -1) + _srcZone = scene.closestZone(srcPt); + + // Get the zone of the destination + _destZone = scene.whichZone(_walkDest); + if (_destZone == -1) { + _destZone = scene.closestZone(_walkDest); + + // The destination isn't in a zone + if (_walkDest.x >= (SHERLOCK_SCREEN_WIDTH - 1)) + _walkDest.x = SHERLOCK_SCREEN_WIDTH - 2; + + // Trace a line between the centroid of the found closest zone to + // the destination, to find the point at which the zone will be left + const Common::Rect &destRect = scene._zones[_destZone]; + const Common::Point destCenter((destRect.left + destRect.right) / 2, + (destRect.top + destRect.bottom) / 2); + const Common::Point delta = _walkDest - destCenter; + Common::Point pt(destCenter.x * 100, destCenter.y * 100); + + // Move along the line until the zone is left + do { + pt += delta; + } while (destRect.contains(pt.x / 100, pt.y / 100)); + + // Set the new walk destination to the last point that was in the + // zone just before it was left + _walkDest = Common::Point((pt.x - delta.x * 2) / 100, + (pt.y - delta.y * 2) / 100); + } + + // Only do a walk if both zones are acceptable + if (_srcZone == -2 || _destZone == -2) + return; + + // If the start and dest zones are the same, walk directly to the dest point + if (_srcZone == _destZone) { + setWalking(); + } else { + // Otherwise a path needs to be formed from the path information + int i = scene._walkDirectory[_srcZone][_destZone]; + + // See if we need to use a reverse path + if (i == -1) + i = scene._walkDirectory[_destZone][_srcZone]; + + int count = scene._walkData[i]; + ++i; + + // See how many points there are between the src and dest zones + if (!count || count == 255) { + // There are none, so just walk to the new zone + setWalking(); + } else { + // There are points, so set up a multi-step path between points + // to reach the given destination + _walkTo.clear(); + + if (scene._walkDirectory[_srcZone][_destZone] != -1) { + for (int idx = 0; idx < count; ++idx, i += 3) { + _walkTo.push(Common::Point(READ_LE_UINT16(&scene._walkData[i]), + scene._walkData[i + 2])); + } + } else { + for (int idx = 0; idx < count; ++idx) + _walkTo.push(Common::Point()); + + for (int idx = count - 1; idx >= 0; --idx, i += 3) { + _walkTo[idx].x = READ_LE_UINT16(&scene._walkData[i]); + _walkTo[idx].y = scene._walkData[i + 2]; + } + } + + // Start walking + _walkDest = _walkTo.top(); + setWalking(); + } + } } } // End of namespace Sherlock diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 8d1953ee20..0393528095 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -59,6 +59,7 @@ private: Sprite &_player; bool _walkLoaded; int _oldWalkSequence; + int _srcZone, _destZone; public: Common::Point _walkDest; Common::Stack<Common::Point> _walkTo; diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 95e8355957..c5cba1b5cd 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -176,7 +176,7 @@ void Scene::freeScene() { _walkData.clear(); _cAnim.clear(); _bgShapes.clear(); - _bounds.clear(); + _zones.clear(); _canimShapes.clear(); for (uint idx = 0; idx < _images.size(); ++idx) @@ -205,8 +205,8 @@ bool Scene::loadScene(const Common::String &filename) { _ongoingCans = 0; // Reset the list of walkable areas - _bounds.clear(); - _bounds.push_back(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); + _zones.clear(); + _zones.push_back(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT)); _descText.clear(); _comments = ""; @@ -311,12 +311,12 @@ bool Scene::loadScene(const Common::String &filename) { Common::SeekableReadStream *boundsStream = !_lzwMode ? rrmStream : decompressLZ(*rrmStream, size); - _bounds.resize(size / 10); - for (uint idx = 0; idx < _bounds.size(); ++idx) { - _bounds[idx].left = boundsStream->readSint16LE(); - _bounds[idx].top = boundsStream->readSint16LE(); - _bounds[idx].setWidth(boundsStream->readSint16LE()); - _bounds[idx].setHeight(boundsStream->readSint16LE()); + _zones.resize(size / 10); + for (uint idx = 0; idx < _zones.size(); ++idx) { + _zones[idx].left = boundsStream->readSint16LE(); + _zones[idx].top = boundsStream->readSint16LE(); + _zones[idx].setWidth(boundsStream->readSint16LE()); + _zones[idx].setHeight(boundsStream->readSint16LE()); boundsStream->skip(2); // Skip unused scene number field } @@ -328,8 +328,8 @@ bool Scene::loadScene(const Common::String &filename) { error("Invalid scene path data"); // Load the walk directory - for (uint idx1 = 0; idx1 < _bounds.size(); ++idx1) { - for (uint idx2 = 0; idx2 < _bounds.size(); ++idx2) + for (uint idx1 = 0; idx1 < _zones.size(); ++idx1) { + for (uint idx2 = 0; idx2 < _zones.size(); ++idx2) _walkDirectory[idx1][idx2] = rrmStream->readSint16LE(); } @@ -1450,4 +1450,38 @@ int Scene::checkForZones(const Common::Point &pt, int zoneType) { return matches; } +/** + * Check which zone the the given position is located in. + */ +int Scene::whichZone(const Common::Point &pt) { + for (uint idx = 0; idx < _zones.size(); ++idx) { + if (_zones[idx].contains(pt)) + return idx; + } + + return -1; +} + +/** + * Returns the index of the closest zone to a given point. + */ +int Scene::closestZone(const Common::Point &pt) { + int dist = 1000; + int zone = -1; + + for (uint idx = 0; idx < _zones.size(); ++idx) { + Common::Point zc((_zones[idx].left + _zones[idx].right) / 2, + (_zones[idx].top + _zones[idx].bottom) / 2); + int d = ABS(zc.x - pt.x) + ABS(zc.y - pt.y); + + if (d < dist) { + // Found a closer zone + dist = d; + zone = idx; + } + } + + return zone; +} + } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 1a9fe7b02c..1b3a730179 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -137,7 +137,7 @@ public: int _invGraphicItems; Common::String _comments; Common::Array<char> _descText; - Common::Array<Common::Rect> _bounds; + Common::Array<Common::Rect> _zones; Common::Array<Object> _bgShapes; Common::Array<CAnim> _cAnim; Common::Array<byte> _sequenceBuffer; @@ -179,6 +179,10 @@ public: int findBgShape(const Common::Rect &r); int checkForZones(const Common::Point &pt, int zoneType); + + int whichZone(const Common::Point &pt); + + int closestZone(const Common::Point &pt); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index a9de32972f..107dee5a41 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -100,6 +100,9 @@ Common::Error SherlockEngine::run() { if (shouldQuit()) break; + // Reset UI flags + _ui->reset(); + // Reset the active characters to initially just Sherlock _people->reset(); diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp index 661604e4bf..fc94cc5a5c 100644 --- a/engines/sherlock/user_interface.cpp +++ b/engines/sherlock/user_interface.cpp @@ -82,6 +82,12 @@ UserInterface::~UserInterface() { delete _controls; } +void UserInterface::reset() { + _oldKey = -1; + _help = _oldHelp = -1; + _oldTemp = _temp = -1; +} + /** * Main input handler for the user interface */ diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index d312ff919c..d2ef8942c3 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -95,6 +95,8 @@ public: UserInterface(SherlockEngine *vm); ~UserInterface(); + void reset(); + void handleInput(); void clearInfo(); |