From b6076dd52458320f39442bc225ef8b0ce531ea51 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 21 Mar 2015 11:24:35 -0400 Subject: SHERLOCK: Implemented setWalking --- engines/sherlock/objects.cpp | 17 ++-- engines/sherlock/objects.h | 18 ++-- engines/sherlock/people.cpp | 204 +++++++++++++++++++++++++++++++++++++++++- engines/sherlock/people.h | 20 ++++- engines/sherlock/scene.cpp | 2 +- engines/sherlock/scene.h | 2 +- engines/sherlock/sherlock.cpp | 15 +--- engines/sherlock/sherlock.h | 1 + 8 files changed, 240 insertions(+), 39 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 3fc9901a38..63e4bdf621 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -21,9 +21,14 @@ */ #include "sherlock/objects.h" +#include "sherlock/sherlock.h" +#include "sherlock/people.h" +#include "sherlock/scene.h" namespace Sherlock { +SherlockEngine *Sprite::_vm; + /** * Reset the data for the sprite */ @@ -39,7 +44,7 @@ void Sprite::clear() { _allow = 0; _frameNumber = _sequenceNumber = 0; _position.x = _position.y = 0; - _movement.x = _movement.y = 0; + _delta.x = _delta.y = 0; _oldPosition.x = _oldPosition.y = 0; _oldSize.x = _oldSize.y = 0; _goto.x = _goto.y = 0; @@ -57,15 +62,7 @@ void Sprite::setImageFrame() { _imageFrame = &(*_images)[imageNumber]; } -void Sprite::adjustSprite(bool onChessboard) { - // TODO -} - -void Sprite::gotoStand() { - // TODO -} - -void Sprite::setWalking() { +void Sprite::adjustSprite() { // TODO } diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index a1bdc5933c..b1207867e4 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -74,7 +74,10 @@ enum AType { #define FLIP_CODE (64 + 128) #define SOUND_CODE (34 + 128) -struct Sprite { +class Sprite { +private: + static SherlockEngine *_vm; +public: Common::String _name; // Name Common::String _description; // Description Common::StringArray _examine; // Examine in-depth description @@ -88,7 +91,7 @@ struct Sprite { int _frameNumber; // Frame number in rame sequence to draw int _sequenceNumber; // Sequence being used Common::Point _position; // Current position - Common::Point _movement; // Momvement amount + Common::Point _delta; // Momvement delta Common::Point _oldPosition; // Old position Common::Point _oldSize; // Image's old size Common::Point _goto; // Walk destination @@ -98,18 +101,15 @@ struct Sprite { int _status; // Status: open/closed, moved/not moved int8 _misc; // Miscellaneous use int _numFrames; // How many frames the object has - +public: Sprite() { clear(); } - + static void setVm(SherlockEngine *vm) { _vm = vm; } + void clear(); void setImageFrame(); - void adjustSprite(bool onChessboard = false); - - void gotoStand(); - - void setWalking(); + void adjustSprite(); }; struct ActionType { diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index b187b65ad4..998fe4f0cf 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -21,9 +21,15 @@ */ #include "sherlock/people.h" +#include "sherlock/sherlock.h" namespace Sherlock { +// Walk speeds +#define MWALK_SPEED 2 +#define XWALK_SPEED 4 +#define YWALK_SPEED 1 + // Characer animation sequences static const uint8 CHARACTER_SEQUENCES[MAX_HOLMES_SEQUENCE][MAX_FRAME] = { { 29, 1, 2, 3, 4, 5, 6, 7, 0 }, // Walk Right @@ -45,9 +51,11 @@ static const uint8 CHARACTER_SEQUENCES[MAX_HOLMES_SEQUENCE][MAX_FRAME] = { }; -People::People(SherlockEngine *vm) : _vm(vm) { +People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) { _walkLoaded = false; _holmesOn = true; + _oldWalkSequence = -1; + _allowWalkAbort = false; } People::~People() { @@ -65,7 +73,7 @@ void People::reset() { p._sequences = &CHARACTER_SEQUENCES; p._imageFrame = nullptr; p._frameNumber = 1; - p._movement = Common::Point(0, 0); + p._delta = Common::Point(0, 0); p._oldPosition = Common::Point(0, 0); p._oldSize = Common::Point(0, 0); p._misc = 0; @@ -89,4 +97,196 @@ bool People::loadWalk() { } } +/** +* Set the variables for moving a character from one poisition to another +* in a straight line - goAllTheWay must have been previously called to +* check for any obstacles in the path. +*/ +void People::setWalking() { + Scene &scene = *_vm->_scene; + int oldDirection, oldFrame; + Common::Point speed, delta; + int temp; + + // Flag that player has now walked in the scene + scene._walkedInScene = true; + + // Stop any previous walking, since a new dest is being set + _player._walkCount = 0; + oldDirection = _player._sequenceNumber; + oldFrame = _player._frameNumber; + + // Set speed to use horizontal and vertical movement + if (_vm->_onChessboard) { + speed = Common::Point(MWALK_SPEED, MWALK_SPEED); + } else { + speed = Common::Point(XWALK_SPEED, YWALK_SPEED); + } + + // 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 (;;) { + // 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 + if (_walkDest.x >= (temp = _player._imageFrame->_frame.w / 2)) + _walkDest.x -= temp; + + delta = Common::Point( + ABS(_player._position.x / 100 - _walkDest.x), + ABS(_player._position.y / 100 - _walkDest.y) + ); + + // If we're ready to move a sufficient distance, that's it. Otherwise, + // move onto the next portion of the walk path, if there is one + if ((delta.x > 3 || delta.y > 0) || _walkTo.empty()) + break; + + // Pop next walk segment off the walk route stack + _walkDest = _walkTo.pop(); + } while (!_vm->shouldQuit()); + + // If a sufficient move is being done, then start the move + if (delta.x > 3 || delta.y) { + // See whether the major movement is horizontal or vertical + if (delta.x >= delta.y) { + // Set the initial frame sequence for the left and right, as well + // as settting the delta x depending on direction + if (_walkDest.x < (_player._position.x / 100)) { + _player._sequenceNumber = _vm->_onChessboard ? MAP_LEFT : WALK_LEFT; + _player._delta.x = speed.x * -100; + } else { + _player._sequenceNumber = _vm->_onChessboard ? MAP_RIGHT : WALK_RIGHT; + _player._delta.x = speed.x * 100; + } + + // See if the x delta is too small to be divided by the speed, since + // this would cause a divide by zero error + if (delta.x >= speed.x) { + // Det the delta y + _player._delta.y = (delta.y * 100) / (delta.x / speed.x); + if (_walkDest.y < (_player._position.y / 100)) + _player._delta.y = -_player._delta.y; + + // Set how many times we should add the delta to the player's position + _player._walkCount = delta.x / speed.x; + } else { + // The delta x was less than the speed (ie. we're really close to + // the destination). So set delta to 0 so the player won't move + _player._delta = Common::Point(0, 0); + _player._position = Common::Point(_walkDest.x * 100, _walkDest.y * 100); + _player._walkCount = 1; + } + + // See if the sequence needs to be changed for diagonal walking + if (_player._delta.y > 150) { + if (!_vm->_onChessboard) { + switch (_player._sequenceNumber) { + case WALK_LEFT: + _player._sequenceNumber = WALK_DOWNLEFT; + break; + case WALK_RIGHT: + _player._sequenceNumber = WALK_DOWNRIGHT; + break; + } + } + } else if (_player._delta.y < -150) { + if (!_vm->_onChessboard) { + switch (_player._sequenceNumber) { + case WALK_LEFT: + _player._sequenceNumber = WALK_UPLEFT; + break; + case WALK_RIGHT: + _player._sequenceNumber = WALK_UPRIGHT; + break; + } + } + } + } else { + // Major movement is vertical, so set the sequence for up and down, + // and set the delta Y depending on the direction + if (_walkDest.y < (_player._position.y / 100)) { + _player._sequenceNumber = WALK_UP; + _player._delta.y = speed.y * -100; + } else { + _player._sequenceNumber = WALK_DOWN; + _player._delta.y = speed.y * 100; + } + + // If we're on the overhead map, set the sequence so we keep moving + // in the same direction + _player._sequenceNumber = (oldDirection == -1) ? MAP_RIGHT : oldDirection; + + // Set the delta x + _player._delta.x = (delta.x * 100) / (delta.y / speed.y); + if (_walkDest.x < (_player._position.x / 100)) + _player._delta.x = -_player._delta.x; + } + } + + // See if the new walk sequence is the same as the old. If it's a new one, + // we need to reset the frame number to zero so it's animation starts at + // it's beginning. Otherwise, if it's the same sequence, we can leave it + // as is, so it keeps the animation going at wherever it was up to + if (_player._sequenceNumber != _oldWalkSequence) + _player._frameNumber = 0; + _oldWalkSequence = _player._sequenceNumber; + + if (!_player._walkCount) + gotoStand(_player); + + // If the sequence is the same as when we started, then Holmes was + // standing still and we're trying to re-stand him, so reset Holmes' + // rame to the old frame number from before it was reset to 0 + if (_player._sequenceNumber == oldDirection) + _player._frameNumber = oldFrame; +} + +/** + * Bring a moving character to a standing position. If the Scalpel chessboard + * is being displayed, then the chraracter will always face down. + */ +void People::gotoStand(Sprite &sprite) { + Scene &scene = *_vm->_scene; + _walkTo.clear(); + sprite._walkCount = 0; + + switch (sprite._sequenceNumber) { + case WALK_UP: + sprite._sequenceNumber = STOP_UP; break; + case WALK_DOWN: + sprite._sequenceNumber = STOP_DOWN; break; + case TALK_LEFT: + case WALK_LEFT: + sprite._sequenceNumber = STOP_LEFT; break; + case TALK_RIGHT: + case WALK_RIGHT: + sprite._sequenceNumber = STOP_RIGHT; break; + case WALK_UPRIGHT: + sprite._sequenceNumber = STOP_UPRIGHT; break; + case WALK_UPLEFT: + sprite._sequenceNumber = STOP_UPLEFT; break; + case WALK_DOWNRIGHT: + sprite._sequenceNumber = STOP_DOWNRIGHT; break; + case WALK_DOWNLEFT: + sprite._sequenceNumber = STOP_DOWNLEFT; break; + default: + break; + } + + // Only restart frame at 0 if the sequence number has changed + if (_oldWalkSequence != -1 || sprite._sequenceNumber == STOP_UP) + sprite._frameNumber = 0; + + if (_vm->_onChessboard) { + sprite._sequenceNumber = 0; + _data[AL]._position.x = (_vm->_map[scene._charPoint].x - 6) * 100; + _data[AL]._position.y = (_vm->_map[scene._charPoint].x + 10) * 100; + } + + _oldWalkSequence = -1; + _allowWalkAbort = true; +} + } // End of namespace Sherlock diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 74a4575af6..be9be006e8 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -24,6 +24,7 @@ #define SHERLOCK_PEOPLE_H #include "common/scummsys.h" +#include "common/stack.h" #include "sherlock/objects.h" namespace Sherlock { @@ -39,10 +40,14 @@ enum PeopleId { // Animation sequence identifiers for characters enum { WALK_RIGHT = 0, WALK_DOWN = 1, WALK_LEFT = 2, WALK_UP = 3, STOP_LEFT = 4, - STOP_DOWN = 5, STOP_RIGHT = 6, STOP_UP = 7, WALK_UPRIGHT = 8, + STOP_DOWN = 5, STOP_RIGHT = 6, STOP_UP = 7, WALK_UPRIGHT = 8, WALK_DOWNRIGHT = 9, WALK_UPLEFT = 10, WALK_DOWNLEFT = 11, STOP_UPRIGHT = 12, STOP_UPLEFT = 13, STOP_DOWNRIGHT = 14, - STOP_DOWNLEFT = 15, TALK_RIGHT = 6, TALK_LEFT = 4 + STOP_DOWNLEFT = 15, TALK_RIGHT = 6, TALK_LEFT = 4, +}; +enum { + MAP_UP = 1, MAP_UPRIGHT = 2, MAP_RIGHT = 1, MAP_DOWNRIGHT = 4, + MAP_DOWN = 5, MAP_DOWNLEFT = 6, MAP_LEFT = 2, MAP_UPLEFT = 8 }; class SherlockEngine; @@ -51,18 +56,27 @@ class People { private: SherlockEngine *_vm; Sprite _data[MAX_PEOPLE]; + Sprite &_player; bool _walkLoaded; + int _oldWalkSequence; + bool _allowWalkAbort; public: + Common::Point _walkDest; + Common::Stack _walkTo; bool _holmesOn; public: People(SherlockEngine *vm); ~People(); + Sprite &operator[](PeopleId id) { return _data[id]; } + void reset(); bool loadWalk(); - Sprite &operator[](PeopleId id) { return _data[id]; } + void setWalking(); + + void gotoStand(Sprite &sprite); }; } // End of namespace Sherlock diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 8875327dcf..13db8d9b94 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -86,7 +86,7 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) { _currentScene = -1; _goToRoom = -1; _changes = false; - _oldCharPoint = 0; + _charPoint = _oldCharPoint = 0; _windowOpen = _infoFlag = false; _menuMode = _keyboardInput = 0; _walkedInScene = false; diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index 5625bb1f5b..a4b94652c8 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -108,7 +108,7 @@ public: bool _savedStats[SCENES_COUNT][9]; Common::Point _bigPos; Common::Point _overPos; - int _oldCharPoint; + int _charPoint, _oldCharPoint; ImageFile *_controls; ImageFile *_controlPanel; bool _windowOpen, _infoFlag; diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 60e32bda82..2787e2b924 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -44,6 +44,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _useEpilogue2 = false; _justLoaded = false; _talkToAbort = false; + _onChessboard = false; } SherlockEngine::~SherlockEngine() { @@ -65,20 +66,8 @@ void SherlockEngine::initialize() { DebugMan.addDebugChannel(kDebugScript, "scripts", "Script debug level"); - /* - int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - - MidiDriver *driver = MidiDriver::createMidi(midiDriver); - if (native_mt32) - driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - - _midi = new MidiPlayer(this, driver); - _midi->setGM(true); - _midi->setNativeMT32(native_mt32); - */ - ImageFile::setVm(this); + Sprite::setVm(this); _res = new Resources(); _animation = new Animation(this); _debugger = new Debugger(this); diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 84b6c48f12..1607cec974 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -97,6 +97,7 @@ public: Common::Point _over; // Old map position Common::Array _map; // Map locations for each scene bool _talkToAbort; + bool _onChessboard; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); -- cgit v1.2.3