From 8629feb410068c084741de1bc2126ed6cd53a4cd Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 14 Jun 2015 00:43:19 -0400 Subject: SHERLOCK: RT: Implemented walk setup --- engines/sherlock/objects.cpp | 302 +++++++++++----------- engines/sherlock/people.cpp | 3 +- engines/sherlock/people.h | 5 + engines/sherlock/scalpel/scalpel_people.cpp | 5 + engines/sherlock/scalpel/scalpel_people.h | 5 + engines/sherlock/scalpel/scalpel_scene.cpp | 1 - engines/sherlock/tattoo/tattoo_people.cpp | 45 +++- engines/sherlock/tattoo/tattoo_people.h | 5 + engines/sherlock/tattoo/tattoo_scene.cpp | 2 +- engines/sherlock/tattoo/tattoo_scene.h | 2 +- engines/sherlock/tattoo/tattoo_user_interface.cpp | 6 + 11 files changed, 217 insertions(+), 164 deletions(-) (limited to 'engines') diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 1c184df547..29c5d73ad9 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -226,174 +226,184 @@ void Sprite::checkSprite() { Common::Rect objBounds; Common::Point spritePt(_position.x / FIXED_INT_MULTIPLIER, _position.y / FIXED_INT_MULTIPLIER); - if (!talk._talkCounter && _type == CHARACTER) { - pt = _walkCount ? _position + _delta : _position; - pt.x /= FIXED_INT_MULTIPLIER; - pt.y /= FIXED_INT_MULTIPLIER; - - for (uint idx = 0; idx < scene._bgShapes.size() && !talk._talkToAbort; ++idx) { - Object &obj = scene._bgShapes[idx]; - if (obj._aType <= PERSON || obj._type == INVALID || obj._type == HIDDEN) - continue; - - if (obj._type == NO_SHAPE) { - objBounds = Common::Rect(obj._position.x, obj._position.y, - obj._position.x + obj._noShapeSize.x + 1, obj._position.y + obj._noShapeSize.y + 1); - } else { - int xp = obj._position.x + obj._imageFrame->_offset.x; - int yp = obj._position.y + obj._imageFrame->_offset.y; - objBounds = Common::Rect(xp, yp, - xp + obj._imageFrame->_frame.w + 1, yp + obj._imageFrame->_frame.h + 1); - } + if (_type != CHARACTER || (IS_SERRATED_SCALPEL && talk._talkCounter)) + return; - if (objBounds.contains(pt)) { - if (objBounds.contains(spritePt)) { - // Current point is already inside the the bounds, so impact occurred - // on a previous call. So simply do nothing until we're clear of the box - switch (obj._aType) { - case TALK_MOVE: - if (_walkCount) { - // Holmes is moving - obj._type = HIDDEN; - obj.setFlagsAndToggles(); - talk.talkTo(obj._use[0]._target); - } - break; + pt = _walkCount ? _position + _delta : _position; + pt.x /= FIXED_INT_MULTIPLIER; + pt.y /= FIXED_INT_MULTIPLIER; - case PAL_CHANGE: - case PAL_CHANGE2: - if (_walkCount) { - int palStart = atoi(obj._use[0]._names[0].c_str()) * 3; - int palLength = atoi(obj._use[0]._names[1].c_str()) * 3; - int templ = atoi(obj._use[0]._names[2].c_str()) * 3; - if (templ == 0) - templ = 100; - - // Ensure only valid palette change data found - if (palLength > 0) { - // Figure out how far into the shape Holmes is so that we - // can figure out what percentage of the original palette - // to set the current palette to - int palPercent = (pt.x - objBounds.left) * 100 / objBounds.width(); - palPercent = palPercent * templ / 100; - if (obj._aType == PAL_CHANGE) - // Invert percentage - palPercent = 100 - palPercent; - - for (int i = palStart; i < (palStart + palLength); ++i) - screen._sMap[i] = screen._cMap[i] * palPercent / 100; - - events.pollEvents(); - screen.setPalette(screen._sMap); - } - } - break; + if (IS_ROSE_TATTOO) { + // TODO: Needs to be called + //checkObject(1001); + + // For Rose Tattoo, we only do the further processing for Sherlock + if (this != &people[HOLMES]) + return; + } + + for (uint idx = 0; idx < scene._bgShapes.size() && !talk._talkToAbort; ++idx) { + Object &obj = scene._bgShapes[idx]; + if (obj._aType <= PERSON || obj._type == INVALID || obj._type == HIDDEN) + continue; + + if (obj._type == NO_SHAPE) { + objBounds = Common::Rect(obj._position.x, obj._position.y, + obj._position.x + obj._noShapeSize.x + 1, obj._position.y + obj._noShapeSize.y + 1); + } else { + int xp = obj._position.x + obj._imageFrame->_offset.x; + int yp = obj._position.y + obj._imageFrame->_offset.y; + objBounds = Common::Rect(xp, yp, + xp + obj._imageFrame->_frame.w + 1, yp + obj._imageFrame->_frame.h + 1); + } - case TALK: - case TALK_EVERY: + if (objBounds.contains(pt)) { + if (objBounds.contains(spritePt)) { + // Current point is already inside the the bounds, so impact occurred + // on a previous call. So simply do nothing until we're clear of the box + switch (obj._aType) { + case TALK_MOVE: + if (_walkCount) { + // Holmes is moving obj._type = HIDDEN; obj.setFlagsAndToggles(); talk.talkTo(obj._use[0]._target); - break; - - default: - break; } - } else { - // New impact just occurred - switch (obj._aType) { - case BLANK_ZONE: - // A blank zone masks out all other remaining zones underneath it. - // If this zone is hit, exit the outer loop so we do not check anymore - return; - - case SOLID: - case TALK: - // Stop walking - if (obj._aType == TALK) { - obj.setFlagsAndToggles(); - talk.talkTo(obj._use[0]._target); - } else { - gotoStand(); - } - break; + break; - case TALK_EVERY: - if (obj._aType == TALK_EVERY) { - obj._type = HIDDEN; - obj.setFlagsAndToggles(); - talk.talkTo(obj._use[0]._target); - } else { - gotoStand(); + case PAL_CHANGE: + case PAL_CHANGE2: + if (_walkCount) { + int palStart = atoi(obj._use[0]._names[0].c_str()) * 3; + int palLength = atoi(obj._use[0]._names[1].c_str()) * 3; + int templ = atoi(obj._use[0]._names[2].c_str()) * 3; + if (templ == 0) + templ = 100; + + // Ensure only valid palette change data found + if (palLength > 0) { + // Figure out how far into the shape Holmes is so that we + // can figure out what percentage of the original palette + // to set the current palette to + int palPercent = (pt.x - objBounds.left) * 100 / objBounds.width(); + palPercent = palPercent * templ / 100; + if (obj._aType == PAL_CHANGE) + // Invert percentage + palPercent = 100 - palPercent; + + for (int i = palStart; i < (palStart + palLength); ++i) + screen._sMap[i] = screen._cMap[i] * palPercent / 100; + + events.pollEvents(); + screen.setPalette(screen._sMap); } - break; + } + break; - case FLAG_SET: + case TALK: + case TALK_EVERY: + obj._type = HIDDEN; + obj.setFlagsAndToggles(); + talk.talkTo(obj._use[0]._target); + break; + + default: + break; + } + } else { + // New impact just occurred + switch (obj._aType) { + case BLANK_ZONE: + // A blank zone masks out all other remaining zones underneath it. + // If this zone is hit, exit the outer loop so we do not check anymore + return; + + case SOLID: + case TALK: + // Stop walking + if (obj._aType == TALK) { obj.setFlagsAndToggles(); + talk.talkTo(obj._use[0]._target); + } else { + gotoStand(); + } + break; + + case TALK_EVERY: + if (obj._aType == TALK_EVERY) { obj._type = HIDDEN; - break; + obj.setFlagsAndToggles(); + talk.talkTo(obj._use[0]._target); + } else { + gotoStand(); + } + break; - case WALK_AROUND: - if (objBounds.contains(people[HOLMES]._walkTo.front())) { - // Reached zone - gotoStand(); - } else { - // Destination not within box, walk to best corner - Common::Point walkPos; - - if (spritePt.x >= objBounds.left && spritePt.x < objBounds.right) { - // Impact occurred due to vertical movement. Determine whether to - // travel to the left or right side - if (_delta.x > 0) - // Go to right side + case FLAG_SET: + obj.setFlagsAndToggles(); + obj._type = HIDDEN; + break; + + case WALK_AROUND: + if (objBounds.contains(people[HOLMES]._walkTo.front())) { + // Reached zone + gotoStand(); + } else { + // Destination not within box, walk to best corner + Common::Point walkPos; + + if (spritePt.x >= objBounds.left && spritePt.x < objBounds.right) { + // Impact occurred due to vertical movement. Determine whether to + // travel to the left or right side + if (_delta.x > 0) + // Go to right side + walkPos.x = objBounds.right + CLEAR_DIST_X; + else if (_delta.x < 0) { + // Go to left side + walkPos.x = objBounds.left - CLEAR_DIST_X; + } else { + // Going straight up or down. So choose best side + if (spritePt.x >= (objBounds.left + objBounds.width() / 2)) walkPos.x = objBounds.right + CLEAR_DIST_X; - else if (_delta.x < 0) { - // Go to left side + else walkPos.x = objBounds.left - CLEAR_DIST_X; - } else { - // Going straight up or down. So choose best side - if (spritePt.x >= (objBounds.left + objBounds.width() / 2)) - walkPos.x = objBounds.right + CLEAR_DIST_X; - else - walkPos.x = objBounds.left - CLEAR_DIST_X; - } - - walkPos.y = (_delta.y >= 0) ? objBounds.top - CLEAR_DIST_Y : - objBounds.bottom + CLEAR_DIST_Y; - } else { - // Impact occurred due to horizontal movement - if (_delta.y > 0) - // Go to bottom of box + } + + walkPos.y = (_delta.y >= 0) ? objBounds.top - CLEAR_DIST_Y : + objBounds.bottom + CLEAR_DIST_Y; + } else { + // Impact occurred due to horizontal movement + if (_delta.y > 0) + // Go to bottom of box + walkPos.y = objBounds.bottom + CLEAR_DIST_Y; + else if (_delta.y < 0) + // Go to top of box + walkPos.y = objBounds.top - CLEAR_DIST_Y; + else { + // Going straight horizontal, so choose best side + if (spritePt.y >= (objBounds.top + objBounds.height() / 2)) walkPos.y = objBounds.bottom + CLEAR_DIST_Y; - else if (_delta.y < 0) - // Go to top of box + else walkPos.y = objBounds.top - CLEAR_DIST_Y; - else { - // Going straight horizontal, so choose best side - if (spritePt.y >= (objBounds.top + objBounds.height() / 2)) - walkPos.y = objBounds.bottom + CLEAR_DIST_Y; - else - walkPos.y = objBounds.top - CLEAR_DIST_Y; - } - - walkPos.x = (_delta.x >= 0) ? objBounds.left - CLEAR_DIST_X : - objBounds.right + CLEAR_DIST_X; } - walkPos.x += people[HOLMES]._imageFrame->_frame.w / 2; - people._walkDest = walkPos; - people[HOLMES]._walkTo.push(walkPos); - people[HOLMES].setWalking(); + walkPos.x = (_delta.x >= 0) ? objBounds.left - CLEAR_DIST_X : + objBounds.right + CLEAR_DIST_X; } - break; - - case DELTA: - _position.x += 200; - break; - default: - break; + walkPos.x += people[HOLMES]._imageFrame->_frame.w / 2; + people._walkDest = walkPos; + people[HOLMES]._walkTo.push(walkPos); + people[HOLMES].setWalking(); } + break; + + case DELTA: + _position.x += 200; + break; + + default: + break; } } } diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp index 349be671a4..7cdaab7626 100644 --- a/engines/sherlock/people.cpp +++ b/engines/sherlock/people.cpp @@ -73,8 +73,7 @@ Person::Person() : Sprite() { void Person::goAllTheWay() { People &people = *_vm->_people; Scene &scene = *_vm->_scene; - Common::Point srcPt(_position.x / FIXED_INT_MULTIPLIER + frameWidth() / 2, - _position.y / FIXED_INT_MULTIPLIER); + Common::Point srcPt = getSourcePoint(); // Get the zone the player is currently in _srcZone = scene.whichZone(srcPt); diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index 19e050ead1..5b5aac6908 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -57,6 +57,11 @@ struct PersonData { }; class Person : public Sprite { +protected: + /** + * Get the source position for a character potentially affected by scaling + */ + virtual Common::Point getSourcePoint() const = 0; public: Common::Queue _walkTo; int _srcZone, _destZone; diff --git a/engines/sherlock/scalpel/scalpel_people.cpp b/engines/sherlock/scalpel/scalpel_people.cpp index 89f3eeaeb6..72d8d32812 100644 --- a/engines/sherlock/scalpel/scalpel_people.cpp +++ b/engines/sherlock/scalpel/scalpel_people.cpp @@ -334,6 +334,11 @@ void ScalpelPerson::setWalking() { _frameNumber = oldFrame; } +Common::Point ScalpelPerson::getSourcePoint() const { + return Common::Point(_position.x / FIXED_INT_MULTIPLIER + frameWidth() / 2, + _position.y / FIXED_INT_MULTIPLIER); +} + /*----------------------------------------------------------------*/ ScalpelPeople::ScalpelPeople(SherlockEngine *vm) : People(vm) { diff --git a/engines/sherlock/scalpel/scalpel_people.h b/engines/sherlock/scalpel/scalpel_people.h index 9d1214bc68..dc1258308f 100644 --- a/engines/sherlock/scalpel/scalpel_people.h +++ b/engines/sherlock/scalpel/scalpel_people.h @@ -42,6 +42,11 @@ enum ScalpelSequences { }; class ScalpelPerson : public Person { +protected: + /** + * Get the source position for a character potentially affected by scaling + */ + virtual Common::Point getSourcePoint() const; public: ScalpelPerson() : Person() {} virtual ~ScalpelPerson() {} diff --git a/engines/sherlock/scalpel/scalpel_scene.cpp b/engines/sherlock/scalpel/scalpel_scene.cpp index c4da8e09a0..723939211a 100644 --- a/engines/sherlock/scalpel/scalpel_scene.cpp +++ b/engines/sherlock/scalpel/scalpel_scene.cpp @@ -135,7 +135,6 @@ void ScalpelScene::drawAllShapes() { screen.resetDisplayBounds(); } - void ScalpelScene::checkBgShapes() { People &people = *_vm->_people; Person &holmes = people[HOLMES]; diff --git a/engines/sherlock/tattoo/tattoo_people.cpp b/engines/sherlock/tattoo/tattoo_people.cpp index ebada5627c..cec8cd9bdf 100644 --- a/engines/sherlock/tattoo/tattoo_people.cpp +++ b/engines/sherlock/tattoo/tattoo_people.cpp @@ -286,18 +286,28 @@ void TattooPerson::setWalking() { int scaleVal = scene.getScaleVal(_position); Common::Point speed(MAX(WALK_SPEED_X[scene._currentScene - 1] * SCALE_THRESHOLD / scaleVal, 2), MAX(WALK_SPEED_Y[scene._currentScene - 1] * SCALE_THRESHOLD / scaleVal, 2)); - Common::Point diagSpeed(MAX((WALK_SPEED_Y[scene._currentScene - 1] - 2) * SCALE_THRESHOLD / scaleVal, 2), - MAX(WALK_SPEED_DIAG_X[scene._currentScene - 1] * SCALE_THRESHOLD / scaleVal, 2)); + Common::Point diagSpeed(MAX(WALK_SPEED_DIAG_X[scene._currentScene - 1] * SCALE_THRESHOLD / scaleVal, 2), + MAX((WALK_SPEED_Y[scene._currentScene - 1] - 2) * SCALE_THRESHOLD / scaleVal, 2)); // 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 - int temp; - if (people._walkDest.x >= (temp = _imageFrame->_frame.w / 2)) - people._walkDest.x -= temp; + if (_centerWalk || !_walkTo.empty()) { + // Since we want the player to be centered on the ultimate destination, and the player + // is drawn from the left side, move the cursor half the width of the player to center it + delta = Common::Point(_position.x / FIXED_INT_MULTIPLIER - people._walkDest.x, + _position.y / FIXED_INT_MULTIPLIER - people._walkDest.y); + + int dir; + if (ABS(delta.x) > ABS(delta.y)) + dir = (delta.x < 0) ? WALK_LEFT : WALK_RIGHT; + else + dir = (delta.y < 0) ? WALK_UP : WALK_DOWN; + + int scaleVal = scene.getScaleVal(Point32(people._walkDest.x * FIXED_INT_MULTIPLIER, + people._walkDest.y * FIXED_INT_MULTIPLIER)); + people._walkDest.x -= _stopFrames[dir]->sDrawXSize(scaleVal) / 2; + } delta = Common::Point( ABS(_position.x / FIXED_INT_MULTIPLIER - people._walkDest.x), @@ -321,22 +331,22 @@ void TattooPerson::setWalking() { // as setting the delta x depending on direction if (people._walkDest.x < (_position.x / FIXED_INT_MULTIPLIER)) { _sequenceNumber = WALK_LEFT; - _delta.x = speed.x * -FIXED_INT_MULTIPLIER; + _delta.x = speed.x * -(FIXED_INT_MULTIPLIER / 10); } else { _sequenceNumber = WALK_RIGHT; - _delta.x = speed.x * FIXED_INT_MULTIPLIER; + _delta.x = speed.x * (FIXED_INT_MULTIPLIER / 10); } // 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) { + if ((delta.x * 10) >= speed.x) { // Det the delta y - _delta.y = (delta.y * FIXED_INT_MULTIPLIER) / (delta.x / speed.x); + _delta.y = (delta.y * FIXED_INT_MULTIPLIER) / ((delta.x * 10) / speed.x); if (people._walkDest.y < (_position.y / FIXED_INT_MULTIPLIER)) _delta.y = -_delta.y; // Set how many times we should add the delta to the player's position - _walkCount = delta.x / speed.x; + _walkCount = (delta.x * 10) / 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 @@ -365,6 +375,7 @@ void TattooPerson::setWalking() { if (_sequenceNumber == WALK_LEFT || _sequenceNumber == WALK_RIGHT) { _delta.x = _delta.x / speed.x * diagSpeed.x; _delta.y = -1 * (delta.y * FIXED_INT_MULTIPLIER) / (delta.x * 10 / diagSpeed.x); + _walkCount = (delta.x * 10) / diagSpeed.x; } switch (_sequenceNumber) { @@ -435,6 +446,14 @@ void TattooPerson::pushNPCPath() { warning("TODO: pushNPCPath"); } +Common::Point TattooPerson::getSourcePoint() const { + TattooScene &scene = *(TattooScene *)_vm->_scene; + int scaleVal = scene.getScaleVal(_position); + + return Common::Point(_position.x / FIXED_INT_MULTIPLIER + _imageFrame->sDrawXSize(scaleVal) / 2, + _position.y / FIXED_INT_MULTIPLIER); +} + /*----------------------------------------------------------------*/ TattooPeople::TattooPeople(SherlockEngine *vm) : People(vm) { diff --git a/engines/sherlock/tattoo/tattoo_people.h b/engines/sherlock/tattoo/tattoo_people.h index 50a0cb13ce..25a76b66f9 100644 --- a/engines/sherlock/tattoo/tattoo_people.h +++ b/engines/sherlock/tattoo/tattoo_people.h @@ -74,6 +74,11 @@ enum TattooSequences { class TattooPerson: public Person { private: bool checkCollision() const; +protected: + /** + * Get the source position for a character potentially affected by scaling + */ + virtual Common::Point getSourcePoint() const; public: int _npcIndex; int _npcStack; diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp index ad7d5c0f55..1cc7b65289 100644 --- a/engines/sherlock/tattoo/tattoo_scene.cpp +++ b/engines/sherlock/tattoo/tattoo_scene.cpp @@ -720,7 +720,7 @@ void TattooScene::doBgAnimDrawSprites() { } } -int TattooScene::getScaleVal(const Common::Point &pt) { +int TattooScene::getScaleVal(const Point32 &pt) { bool found = false; int result = SCALE_THRESHOLD; Common::Point pos(pt.x / FIXED_INT_MULTIPLIER, pt.y / FIXED_INT_MULTIPLIER); diff --git a/engines/sherlock/tattoo/tattoo_scene.h b/engines/sherlock/tattoo/tattoo_scene.h index 849144e07c..5561b77aa4 100644 --- a/engines/sherlock/tattoo/tattoo_scene.h +++ b/engines/sherlock/tattoo/tattoo_scene.h @@ -119,7 +119,7 @@ public: * Returns the scale value for the passed co-ordinates. This is taken from the scene's * scale zones, interpolating inbetween the top and bottom values of the zones as needed */ - int getScaleVal(const Common::Point &pt); + int getScaleVal(const Point32 &pt); /** * Draw all objects and characters. diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp index 915acde400..e6a6430a3e 100644 --- a/engines/sherlock/tattoo/tattoo_user_interface.cpp +++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp @@ -403,6 +403,12 @@ void TattooUserInterface::doStandardControl() { } } } + static bool flag = false; + if (!flag) { + flag = true; + people._walkDest = Common::Point(235, 370); + people[HOLMES].goAllTheWay(); + } } void TattooUserInterface::doLookControl() { -- cgit v1.2.3