From 53f6e1903b9f4247b231955b16dc49cb7d40d3e9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 31 May 2015 11:49:06 -0400 Subject: SHERLOCK: Implement TsAGE object mover code for Scalpel logo display --- engines/sherlock/scalpel/tsage/logo.cpp | 134 ++++++++++++++++++++++++++++++++ engines/sherlock/scalpel/tsage/logo.h | 28 ++++++- 2 files changed, 161 insertions(+), 1 deletion(-) (limited to 'engines/sherlock/scalpel/tsage') diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp index 0fa8bf808a..3fc9973499 100644 --- a/engines/sherlock/scalpel/tsage/logo.cpp +++ b/engines/sherlock/scalpel/tsage/logo.cpp @@ -160,6 +160,7 @@ Object::Object() { _frame = 0; _numFrames = 0; _frameChange = 0; + _angle = _changeCtr = 0; } void Object::setVisage(int visage, int strip) { @@ -176,6 +177,39 @@ void Object::setAnimMode(bool isAnimating) { _frameChange = 1; } +void Object::setDestination(const Common::Point &pt) { + _destination = pt; + + int moveRate = 10; + _walkStartFrame = _vm->_events->getFrameCounter(); + _walkStartFrame += 60 / moveRate; + + calculateMoveAngle(); + + // Get the difference + int diffX = _destination.x - _position.x; + int diffY = _destination.y - _position.y; + int xSign = (diffX < 0) ? -1 : (diffX > 0 ? 1 : 0); + int ySign = (diffY < 0) ? -1 : (diffY > 0 ? 1 : 0); + diffX = ABS(diffX); + diffY = ABS(diffY); + + if (diffX < diffY) { + _minorDiff = diffX / 2; + _majorDiff = diffY; + } else { + _minorDiff = diffY / 2; + _majorDiff = diffX; + } + + // Set the destination position + _moveDelta = Common::Point(diffX, diffY); + _moveSign = Common::Point(xSign, ySign); + _changeCtr = 0; + + assert(diffX || diffY); +} + void Object::erase() { Screen &screen = *_vm->_screen; @@ -187,6 +221,9 @@ void Object::update() { Screen &screen = *_vm->_screen; if (_visage.isLoaded()) { + if (isMoving()) + move(); + if (_isAnimating) { if (_frame < _visage.getFrameCount()) _frame = changeFrame(); @@ -235,6 +272,27 @@ int Object::getNewFrame() { return frameNum; } +void Object::calculateMoveAngle() { + int xDiff = _destination.x - _position.x, yDiff = _position.y - _destination.y; + + if (!xDiff && !yDiff) + _angle = 0; + else if (!xDiff) + _angle = (_destination.y >= _position.y) ? 180 : 0; + else if (!yDiff) + _angle = (_destination.x >= _position.x) ? 90 : 270; + else { + int result = (((xDiff * 100) / ((abs(xDiff) + abs(yDiff))) * 90) / 100); + + if (yDiff < 0) + result = 180 - result; + else if (xDiff < 0) + result += 360; + + _angle = result; + } +} + bool Object::isAnimEnded() const { return _finished; } @@ -243,6 +301,82 @@ bool Object::isMoving() const { return (_destination.x != 0) && (_destination != _position); } +void Object::move() { + Common::Point currPos = _position; + Common::Point moveDiff(5, 3); + int yDiff = 0; + int percent = 100; + + if (dontMove()) + return; + + if (_moveDelta.x >= _moveDelta.y) { + int xAmount = _moveSign.x * moveDiff.x * percent / 100; + if (!xAmount) + xAmount = _moveSign.x; + currPos.x += xAmount; + + int yAmount = ABS(_destination.y - currPos.y); + int yChange = _majorDiff / ABS(xAmount); + int ySign; + + if (!yChange) + ySign = _moveSign.y; + else { + int v = yAmount / yChange; + _changeCtr += yAmount % yChange; + if (_changeCtr >= yChange) { + ++v; + _changeCtr -= yChange; + } + + ySign = _moveSign.y * v; + } + + currPos.y += ySign; + _majorDiff -= ABS(xAmount); + + } + else { + int yAmount = _moveSign.y * moveDiff.y * percent / 100; + if (!yAmount) + yAmount = _moveSign.y; + currPos.y += yAmount; + + int xAmount = ABS(_destination.x - currPos.x); + int xChange = _majorDiff / ABS(yAmount); + int xSign; + + if (!xChange) + xSign = _moveSign.x; + else { + int v = xAmount / xChange; + _changeCtr += xAmount % xChange; + if (_changeCtr >= xChange) { + ++v; + _changeCtr -= xChange; + } + + xSign = _moveSign.x * v; + } + + currPos.x += xSign; + _majorDiff -= ABS(yAmount); + } + + _position = currPos; + if (dontMove()) + _position = _destination; +} + +bool Object::dontMove() const { + return (_majorDiff <= 0); +} + +void Object::endMove() { + _position = _destination; +} + /*----------------------------------------------------------------*/ bool Logo::show(ScalpelEngine *vm) { diff --git a/engines/sherlock/scalpel/tsage/logo.h b/engines/sherlock/scalpel/tsage/logo.h index 0dcd35e281..68b7353a15 100644 --- a/engines/sherlock/scalpel/tsage/logo.h +++ b/engines/sherlock/scalpel/tsage/logo.h @@ -97,6 +97,12 @@ private: uint32 _updateStartFrame; bool _isAnimating; bool _finished; + uint32 _walkStartFrame; + int _angle; + int _changeCtr; + int _majorDiff, _minorDiff; + Common::Point _moveDelta; + Common::Point _moveSign; /** * Return the next frame when the object is animating @@ -107,6 +113,26 @@ private: * Gets the next frame in the sequence */ int getNewFrame(); + + /** + * Calculate the angle between the current position and a designated destination + */ + void calculateMoveAngle(); + + /** + * Handle any object movement + */ + void move(); + + /** + * Returns whether not to make any movement + */ + bool dontMove() const; + + /** + * Ends any current movement + */ + void endMove(); public: static ScalpelEngine *_vm; Common::Point _position; @@ -131,7 +157,7 @@ public: /** * Starts an object moving to a given destination */ - void setDestination(const Common::Point &pt) { _destination = pt; } + void setDestination(const Common::Point &pt); /** * Returns true if an animation is ended -- cgit v1.2.3