diff options
| -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();  | 
