diff options
-rw-r--r-- | engines/sherlock/events.cpp | 10 | ||||
-rw-r--r-- | engines/sherlock/events.h | 1 | ||||
-rw-r--r-- | engines/sherlock/map.cpp | 271 | ||||
-rw-r--r-- | engines/sherlock/map.h | 32 |
4 files changed, 309 insertions, 5 deletions
diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp index 67d09e52b2..79fe1b58d4 100644 --- a/engines/sherlock/events.cpp +++ b/engines/sherlock/events.cpp @@ -67,9 +67,15 @@ void Events::setCursor(CursorId cursorId) { // Set the cursor data Graphics::Surface &s = (*_cursorImages)[cursorId]; - CursorMan.replaceCursor(s.getPixels(), s.w, s.h, 0, 0, 0xff); - showCursor(); + setCursor(s); +} + +/** + * Set the cursor to show from a passed frame + */ +void Events::setCursor(const Graphics::Surface &src) { + CursorMan.replaceCursor(src.getPixels(), src.w, src.h, 0, 0, 0xff); } /** diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h index 71f7623002..ccf6eb1c59 100644 --- a/engines/sherlock/events.h +++ b/engines/sherlock/events.h @@ -63,6 +63,7 @@ public: void loadCursors(const Common::String &filename); void setCursor(CursorId cursorId); + void setCursor(const Graphics::Surface &src); void showCursor(); diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp index 8257c16a38..aae8d683c0 100644 --- a/engines/sherlock/map.cpp +++ b/engines/sherlock/map.cpp @@ -21,10 +21,20 @@ */ #include "sherlock/map.h" +#include "sherlock/sherlock.h" namespace Sherlock { -Map::Map(SherlockEngine *vm): _vm(vm) { +Map::Map(SherlockEngine *vm): _vm(vm), _topLine(SHERLOCK_SCREEN_WIDTH, 12) { + _shapes = nullptr; + _iconShapes = nullptr; + _point = 0; + _placesShown = false; + _charPoint = -1; + for (int idx = 0; idx < 3; ++idx) + Common::fill(&_sequences[idx][0], &_sequences[idx][MAX_FRAME], 0); + + loadData(); } /** @@ -37,10 +47,267 @@ void Map::loadPoints(int count, const int *xList, const int *yList) { } /** + * Load data needed for the map + */ +void Map::loadData() { + // Load the list of location names + Common::SeekableReadStream *txtStream = _vm->_res->load("chess.txt"); + char c; + + while (txtStream->pos() < txtStream->size()) { + Common::String line; + while ((c = txtStream->readByte()) != '\0') + line += c; + + _locationNames.push_back(line); + } + + delete txtStream; + + // Load the path data + Common::SeekableReadStream *pathStream = _vm->_res->load("chess.pth"); + + _paths.resize(31); + for (uint idx = 0; idx < _paths.size(); ++idx) { + _paths[idx].resize(_paths.size()); + + for (uint idx2 = 0; idx2 < _paths.size(); ++idx2) + _paths[idx][idx2] = pathStream->readSint16LE(); + } + + // Load in the path point information + _pathPoints.resize(416); + for (uint idx = 0; idx < _pathPoints.size(); ++idx) + _pathPoints[idx] = pathStream->readSint16LE(); + + delete pathStream; +} + +/** * Show the map */ int Map::show() { - return 0; + Events &events = *_vm->_events; + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + Screen &screen = *_vm->_screen; + Common::Point lDrawn(-1, -1); + bool changed = false, exitFlag = false; + bool drawMap = true; + + // Set font and custom cursor for the map + int oldFont = screen.fontNumber(); + screen.setFont(0); + + ImageFile mapCursors("omouse.vgs"); + events.setCursor(mapCursors[0]); + + // Load the entire map + ImageFile bigMap("bigmap.vgs"); + + // Load need sprites + setupSprites(); + + screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, -_bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[2], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[4], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); + + _point = -1; + people[AL]._position = _lDrawnPos = _overPos; + + // Show place icons + showPlaces(); + saveTopLine(); + _placesShown = true; + + // Keep looping until either a location is picked, or the game is ended + while (!_vm->shouldQuit() && !exitFlag) { + events.pollEventsAndWait(); + events.setButtonState(); + + // Keyboard handling + if (events.kbHit()) { + Common::KeyState keyState = events.getKey(); + + if (keyState.keycode == Common::KEYCODE_RETURN || keyState.keycode == Common::KEYCODE_SPACE) { + // Both space and enter simulate a mouse release + events._pressed = false; + events._released = true; + events._oldButtons = 0; + } + } + + // Ignore scrolling attempts until the screen is drawn + if (!drawMap) { + Common::Point pt = events.mousePos(); + + // Check for vertical map scrolling + if ((pt.y > (SHERLOCK_SCREEN_HEIGHT - 10) && _bigPos.y < 200) || (pt.y < 10 && _bigPos.y > 0)) { + if (pt.y > (SHERLOCK_SCREEN_HEIGHT - 10)) + _bigPos.y += 10; + else + _bigPos.y -= 10; + + changed = true; + } + + // Check for horizontal map scrolling + if ((pt.x > (SHERLOCK_SCREEN_WIDTH - 10) && _bigPos.x < 315) || (pt.x < 10 && _bigPos.x > 0)) { + if (pt.x > (SHERLOCK_SCREEN_WIDTH - 10)) + _bigPos.x += 15; + else + _bigPos.x -= 15; + + changed = true; + } + } + + if (changed) { + // Map has scrolled, so redraw new map view + changed = false; + + screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, -_bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[2], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y)); + screen._backBuffer1.blitFrom(bigMap[4], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y)); + + showPlaces(); + _placesShown = false; + + saveTopLine(); + _savedPos.x = -1; + updateMap(true); + } else if (!drawMap) { + if (!_placesShown) { + showPlaces(); + _placesShown = true; + } + + updateMap(false); + } + + if ((events._released || events._rightReleased) && _point != -1) { + if (people[AL]._walkCount == 0) { + _charPoint = _point; + walkTheStreets(); + + events.setCursor(mapCursors[1]); + } + } + + // Check if a scene has beeen selected and we've finished "moving" to it + if (people[AL]._walkCount == 0) { + if (_charPoint >= 1 && _charPoint < (int)_points.size()) + exitFlag = true; + } + + if (drawMap) { + drawMap = false; + + if (screen._fadeStyle) + screen.randomTransition(); + else + screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT); + } + + // Wait for a frame + events.wait(1); + } + + freeSprites(); + _overPos = people[AL]._position; + + // Reset font and cursor + screen.setFont(oldFont); + events.setCursor(ARROW); + + return _charPoint; +} + +/** + * Load and initialize all the sprites that are needed for the map display + */ +void Map::setupSprites() { + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + typedef byte Sequences[16][MAX_FRAME]; + _savedPos.x = -1; + + _shapes = new ImageFile("mapicon.vgs"); + _iconShapes = new ImageFile("overicon.vgs"); + + Person &p = people[AL]; + p._description = " "; + p._type = CHARACTER; + p._position = Common::Point(12400, 5000); + p._sequenceNumber = 0; + p._sequences = (Sequences *)&_sequences; + p._images = _shapes; + p._imageFrame = nullptr; + p._frameNumber = 0; + p._delta = Common::Point(0, 0); + p._oldSize = Common::Point(0, 0); + p._oldSize = Common::Point(0, 0); + p._misc = 0; + p._walkCount = 0; + p._allow = 0; + p._noShapeSize = Common::Point(0, 0); + p._goto = Common::Point(28000, 15000); + p._status = 0; + p.setImageFrame(); + + scene._bgShapes.clear(); +} + +/** + * Free the sprites and data used by the map + */ +void Map::freeSprites() { + delete _shapes; + delete _iconShapes; +} + +/** + * Draws an icon for every place that's currently known + */ +void Map::showPlaces() { + Screen &screen = *_vm->_screen; + + for (uint idx = 0; idx < _points.size(); ++idx) { + const Common::Point &pt = _points[idx]; + + if (pt.x != 0 && pt.y != 0) { + if (pt.x >= _bigPos.x && (pt.x - _bigPos.x) < SHERLOCK_SCREEN_WIDTH + && pt.y >= _bigPos.y && (pt.y - _bigPos.y) < SHERLOCK_SCREEN_HEIGHT) { + if (_vm->readFlags(idx)) { + screen._backBuffer1.transBlitFrom((*_iconShapes)[idx], + Common::Point(pt.x - _bigPos.x - 6, pt.y - _bigPos.y - 12)); + } + } + } + } +} + +/** + * Makes a copy of the top rows of the screen that are used to display location names + */ +void Map::saveTopLine() { + _topLine.blitFrom(_vm->_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 12)); +} + +/** + * Update all on-screen sprites to account for any scrolling of the map + */ +void Map::updateMap(bool flushScreen) { + // TODO +} + +/** + * Handle moving icon for player from their previous location on the map to a destination location + */ +void Map::walkTheStreets() { + // TODO } } // End of namespace Sherlock diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h index 88f2b75805..32051d60b7 100644 --- a/engines/sherlock/map.h +++ b/engines/sherlock/map.h @@ -27,6 +27,9 @@ #include "common/array.h" #include "common/rect.h" #include "common/str.h" +#include "common/str-array.h" +#include "sherlock/graphics.h" +#include "sherlock/objects.h" namespace Sherlock { @@ -36,7 +39,34 @@ class Map { private: SherlockEngine *_vm; Common::Array<Common::Point> _points; // Map locations for each scene -public: + Common::StringArray _locationNames; + Common::Array< Common::Array<int> > _paths; + Common::Array<int> _pathPoints; + Common::Point _savedPos; + Common::Point _savedSize; + Surface _topLine; + ImageFile *_shapes; + ImageFile *_iconShapes; + byte _sequences[3][MAX_FRAME]; + Common::Point _bigPos; + Common::Point _overPos; + Common::Point _lDrawnPos; + int _point; + bool _placesShown; + int _charPoint; +private: + void loadData(); + + void setupSprites(); + void freeSprites(); + + void showPlaces(); + + void saveTopLine(); + + void updateMap(bool flushScreen); + + void walkTheStreets(); public: Map(SherlockEngine *vm); |