diff options
author | johndoe123 | 2014-03-12 13:14:22 +0100 |
---|---|---|
committer | Eugene Sandulenko | 2018-07-20 06:43:33 +0000 |
commit | 08e8f39945c6c89ffc4fa20d6fe50ca39183b00d (patch) | |
tree | dc50d468e8745764aabf1517a2b3cfc7b307f51d /engines | |
parent | 21e1b08b8399bad5a8b88cf6e30b2db9edd0ad60 (diff) | |
download | scummvm-rg350-08e8f39945c6c89ffc4fa20d6fe50ca39183b00d.tar.gz scummvm-rg350-08e8f39945c6c89ffc4fa20d6fe50ca39183b00d.tar.bz2 scummvm-rg350-08e8f39945c6c89ffc4fa20d6fe50ca39183b00d.zip |
ILLUSIONS: More work on the Camera class
- Add fixed point code (untested and probably wrong)
Diffstat (limited to 'engines')
-rw-r--r-- | engines/illusions/camera.cpp | 306 | ||||
-rw-r--r-- | engines/illusions/camera.h | 23 | ||||
-rw-r--r-- | engines/illusions/fixedpoint.cpp | 62 | ||||
-rw-r--r-- | engines/illusions/fixedpoint.h | 45 | ||||
-rw-r--r-- | engines/illusions/illusions.cpp | 5 | ||||
-rw-r--r-- | engines/illusions/illusions.h | 2 | ||||
-rw-r--r-- | engines/illusions/module.mk | 1 |
7 files changed, 421 insertions, 23 deletions
diff --git a/engines/illusions/camera.cpp b/engines/illusions/camera.cpp index df5de4b083..d81c746274 100644 --- a/engines/illusions/camera.cpp +++ b/engines/illusions/camera.cpp @@ -23,6 +23,7 @@ #include "illusions/illusions.h" #include "illusions/camera.h" #include "illusions/backgroundresource.h" +#include "illusions/fixedpoint.h" #include "illusions/time.h" namespace Illusions { @@ -47,8 +48,8 @@ Camera::Camera(IllusionsEngine *vm) _activeState._panNotifyId = 0; _activeState._trackingLimits.x = 0; _activeState._trackingLimits.y = 0; - _activeState._pt.x = 320; - _activeState._pt.y = 240; + _activeState._centerPt.x = 320; + _activeState._centerPt.y = 240; _activeState._pointFlags = 0; } @@ -66,7 +67,7 @@ void Camera::set(Common::Point &panPoint, WidthHeight &dimensions) { _activeState._bounds._bottomRight.x = MAX(0, dimensions._width - 640) + 320; _activeState._bounds._bottomRight.y = MAX(0, dimensions._height - 480) + 240; _activeState._panTargetPoint = panPoint; - // TODO camera_clipPanTargetPoint(); + clipPanTargetPoint(); _activeState._currPan = _activeState._panTargetPoint; _activeState._panXShl = _activeState._currPan.x << 16; _activeState._panYShl = _activeState._currPan.y << 16; @@ -77,8 +78,98 @@ void Camera::set(Common::Point &panPoint, WidthHeight &dimensions) { _activeState._trackingLimits.x = 0; _activeState._trackingLimits.y = 0; _activeState._pointFlags = 0; - _activeState._pt.x = 320; - _activeState._pt.y = 240; + _activeState._centerPt.x = 320; + _activeState._centerPt.y = 240; +} + +void Camera::panCenterObject(uint32 objectId, int16 panSpeed) { + Common::Point *actorPosition = _vm->getObjectActorPositionPtr(objectId); + _activeState._cameraMode = 1; + _activeState._panSpeed = panSpeed; + _activeState._trackingLimits.x = 8; + _activeState._trackingLimits.y = 8; + _activeState._pointFlags = 0; + _activeState._panToPositionPtr = actorPosition; + _activeState._panObjectId = objectId; + _activeState._panTargetPoint = *actorPosition; + _activeState._panNotifyId = 0; + clipPanTargetPoint(); + _activeState._panStartTime = getCurrentTime(); + recalcPan(_activeState._panStartTime); +} + +void Camera::panTrackObject(uint32 objectId) { + Common::Point *actorPosition = _vm->getObjectActorPositionPtr(objectId); + _activeState._cameraMode = 3; + _activeState._panObjectId = objectId; + _activeState._trackingLimits.x = 160; + _activeState._trackingLimits.y = 120; + _activeState._pointFlags = 0; + _activeState._panSpeed = 710; + _activeState._panToPositionPtr = actorPosition; + _activeState._panNotifyId = 0; + _activeState._panTargetPoint = *actorPosition; + clipPanTargetPoint(); + _activeState._panStartTime = getCurrentTime(); + recalcPan(_activeState._panStartTime); +} + +void Camera::panToPoint(Common::Point pt, int16 panSpeed, uint32 panNotifyId) { + + if (_activeState._panNotifyId) { + // TODO scrmgrNotifyID(_activeState._panNotifyId); + _activeState._panNotifyId = 0; + } + + _activeState._panTargetPoint = Camera::getPtOffset(pt); + clipPanTargetPoint(); + + if (panSpeed) { + _activeState._cameraMode = 5; + _activeState._panSpeed = panSpeed; + _activeState._trackingLimits.x = 0; + _activeState._trackingLimits.y = 0; + _activeState._pointFlags = 0; + _activeState._panToPositionPtr = 0; + _activeState._panNotifyId = panNotifyId; + _activeState._panStartTime = getCurrentTime(); + recalcPan(_activeState._panStartTime); + } else { + _activeState._currPan = _activeState._panTargetPoint; + // TODO stopPan(); + if (panNotifyId) { + // TODO scrmgrNotifyID(panNotifyId); + } + } +} + +void Camera::panEdgeFollow(uint32 objectId, int16 panSpeed) { + Common::Point *actorPosition = _vm->getObjectActorPositionPtr(objectId); + _activeState._cameraMode = 2; + _activeState._trackingLimits.x = 318; + _activeState._trackingLimits.y = 238; + _activeState._pointFlags = 0; + _activeState._panSpeed = panSpeed; + _activeState._panToPositionPtr = actorPosition; + _activeState._panObjectId = objectId; + _activeState._panTargetPoint = _activeState._currPan; + _activeState._panNotifyId = 0; + clipPanTargetPoint(); + _activeState._panStartTime = getCurrentTime(); + recalcPan(_activeState._panStartTime); +} + +void Camera::stopPan() { + _activeState._cameraMode = 6; + _activeState._panTargetPoint = _activeState._currPan; + _activeState._panSpeed = 1; + _activeState._panXShl = _activeState._currPan.x << 16; + _activeState._panYShl = _activeState._currPan.y << 16; + _activeState._panToPositionPtr = 0; + _activeState._panObjectId = 0; + _activeState._panNotifyId = 0; + _activeState._pointFlags = 0; + _vm->_backgroundItems->refreshPan(); } void Camera::pause() { @@ -93,6 +184,65 @@ void Camera::unpause() { _activeState._panStartTime += pauseDuration; } +void Camera::pushCameraMode() { + CameraModeStackItem item; + item._cameraMode = _activeState._cameraMode; + item._panSpeed = _activeState._panSpeed; + item._panObjectId = 0; + item._panNotifyId = 0; + item._panTargetPoint.x = 0; + item._panTargetPoint.y = 0; + switch (_activeState._cameraMode) { + case 4: + item._cameraMode = 3; + item._panObjectId = _activeState._panObjectId; + break; + case 1: + case 2: + case 3: + item._panObjectId = _activeState._panObjectId; + break; + case 5: + item._panTargetPoint = _activeState._panTargetPoint; + item._panNotifyId = _activeState._panNotifyId; + break; + } + _stack.push(item); +} + +void Camera::popCameraMode() { + CameraModeStackItem item = _stack.pop(); + + if (item._panObjectId && !_vm->getObjectActorPositionPtr(item._panObjectId)) { + // Tracking object doesn't exist any longer + stopPan(); + return; + } + + switch (item._cameraMode) { + case 1: + panCenterObject(item._panObjectId, item._panSpeed); + break; + case 2: + panEdgeFollow(item._panObjectId, item._panSpeed); + break; + case 3: + panTrackObject(item._panObjectId); + break; + case 5: + panToPoint(item._panTargetPoint, item._panSpeed, item._panNotifyId); + break; + case 6: + stopPan(); + break; + } + +} + +void Camera::clearCameraModeStack() { + _stack.clear(); +} + void Camera::update(uint32 currTime) { if (_activeState._paused) @@ -148,7 +298,7 @@ void Camera::setBoundsToDimensions(WidthHeight &dimensions) { _activeState._bounds._topLeft.y = 240; _activeState._bounds._bottomRight.x = MAX(0, dimensions._width - 640) + 320; _activeState._bounds._bottomRight.y = MAX(0, dimensions._height - 480) + 240; - // TODO camera_clipPanTargetPoint(); + clipPanTargetPoint(); } Common::Point Camera::getCurrentPan() { @@ -164,43 +314,106 @@ Common::Point Camera::getScreenOffset() { void Camera::updateMode1(uint32 currTime) { Common::Point ptOffs = getPtOffset(*_activeState._panToPositionPtr); - int deltaX = ptOffs.x - _activeState._currPan.x + 320 - _activeState._pt.x; - int deltaY = ptOffs.y - _activeState._currPan.y + 240 - _activeState._pt.y; + int deltaX = ptOffs.x - _activeState._currPan.x + 320 - _activeState._centerPt.x; + int deltaY = ptOffs.y - _activeState._currPan.y + 240 - _activeState._centerPt.y; int deltaXAbs = ABS(deltaX); int deltaYAbs = ABS(deltaY); - if (deltaXAbs > _activeState._trackingLimits.x) { + if (deltaXAbs > _activeState._trackingLimits.x) _activeState._panTargetPoint.x = _activeState._currPan.x + ABS(deltaXAbs - _activeState._trackingLimits.x) * (deltaX >= 0 ? 1 : -1); - } else { + else _activeState._panTargetPoint.x = _activeState._currPan.x; - } - if (deltaYAbs > _activeState._trackingLimits.y) { + if (deltaYAbs > _activeState._trackingLimits.y) _activeState._panTargetPoint.y = _activeState._currPan.y + ABS(deltaYAbs - _activeState._trackingLimits.y) * (deltaY >= 0 ? 1 : -1); - } else { + else _activeState._panTargetPoint.y = _activeState._currPan.y; - } - // TODO Camera_clipPanTargetPoint(); + clipPanTargetPoint(); if (!isPanFinished()) { uint32 oldPanTime = _activeState._panStartTime; _activeState._panStartTime = _activeState._time28; - // TODO Camera_recalcPan(oldPanTime); + recalcPan(oldPanTime); } } void Camera::updateMode2(uint32 currTime) { - // TODO + Common::Point panToPosition = *_activeState._panToPositionPtr; + uint pointFlags = 0; + WRect rect; + + rect._topLeft.x = 320 - _activeState._trackingLimits.x; + rect._topLeft.y = 240 - _activeState._trackingLimits.y; + rect._bottomRight.x = 320 + _activeState._trackingLimits.x; + rect._bottomRight.y = 240 + _activeState._trackingLimits.y; + + if (calcPointFlags(panToPosition, rect, pointFlags)) { + if (pointFlags != _activeState._pointFlags) { + _activeState._pointFlags = pointFlags; + if (pointFlags & 1) + _activeState._panTargetPoint.x = _activeState._bounds._topLeft.x; + else if (pointFlags & 2) + _activeState._panTargetPoint.x = _activeState._bounds._bottomRight.x; + else + _activeState._panTargetPoint.x = _activeState._currPan.x; + if (pointFlags & 4) + _activeState._panTargetPoint.y = _activeState._bounds._topLeft.y; + else if (pointFlags & 8) + _activeState._panTargetPoint.y = _activeState._bounds._bottomRight.y; + else + _activeState._panTargetPoint.y = _activeState._currPan.y; + clipPanTargetPoint(); + _activeState._panStartTime = currTime; + recalcPan(currTime); + } + } else if (_activeState._pointFlags) { + _activeState._pointFlags = 0; + _activeState._panTargetPoint = _activeState._currPan; + } + } void Camera::updateMode3(uint32 currTime) { - // TODO + Common::Point panToPosition = *_activeState._panToPositionPtr; + int deltaX = panToPosition.x - _activeState._currPan.x; + int deltaY = panToPosition.y - _activeState._currPan.y; + + if (ABS(deltaX) > _activeState._trackingLimits.x) + _activeState._panTargetPoint.x = _activeState._currPan.x + 2 * _activeState._trackingLimits.x * (deltaX >= 0 ? 1 : -1); + else + _activeState._panTargetPoint.x = _activeState._currPan.x; + + if (ABS(deltaY) > _activeState._trackingLimits.y) + _activeState._panTargetPoint.y = _activeState._currPan.y + 2 * _activeState._trackingLimits.y * (deltaY >= 0 ? 1 : -1); + else + _activeState._panTargetPoint.y = _activeState._currPan.y; + + clipPanTargetPoint(); + + if (!isPanFinished()) { + _activeState._panStartTime = currTime; + recalcPan(currTime); + _activeState._cameraMode = 4; + } + } bool Camera::updatePan(uint32 currTime) { - // TODO + if (currTime - _activeState._time28 >= _activeState._time2E) { + _activeState._panXShl = _activeState._panTargetPoint.x << 16; + _activeState._panYShl = _activeState._panTargetPoint.y << 16; + } else { + _activeState._panXShl += fixedMul(_activeState._someX, (currTime - _activeState._panStartTime) << 16); + _activeState._panYShl += fixedMul(_activeState._someY, (currTime - _activeState._panStartTime) << 16); + } + _activeState._panStartTime = currTime; + Common::Point newPan(_activeState._panXShl >> 16, _activeState._panYShl >> 16); + if (_activeState._currPan.x != newPan.x || _activeState._currPan.y != newPan.y) { + _activeState._currPan = newPan; + return true; + } return false; } @@ -209,9 +422,60 @@ bool Camera::isPanFinished() { } Common::Point Camera::getPtOffset(Common::Point pt) { - pt.x = pt.x - _activeState._pt.x + 320; - pt.y = pt.y - _activeState._pt.y + 240; + pt.x = pt.x - _activeState._centerPt.x + 320; + pt.y = pt.y - _activeState._centerPt.y + 240; return pt; } +void Camera::recalcPan(uint32 currTime) { + _activeState._currPan2 = getCurrentPan(); + _activeState._time28 = currTime; + + if (_activeState._panSpeed == 0) { + _activeState._time2E = 0; + } else { + FP16 x1 = _activeState._currPan2.x << 16; + FP16 y1 = _activeState._currPan2.y << 16; + FP16 x2 = _activeState._panTargetPoint.x << 16; + FP16 y2 = _activeState._panTargetPoint.y << 16; + FP16 distance = fixedDistance(x1, y1, x2, y2); + _activeState._time2E = 60 * fixedTrunc(distance) / _activeState._panSpeed; + } + + if (_activeState._time2E != 0) { + _activeState._someX = fixedDiv((_activeState._panTargetPoint.x - _activeState._currPan2.x) << 16, _activeState._time2E << 16); + _activeState._someY = fixedDiv((_activeState._panTargetPoint.y - _activeState._currPan2.y) << 16, _activeState._time2E << 16); + } else { + _activeState._someX = (_activeState._panTargetPoint.x - _activeState._currPan2.x) << 16; + _activeState._someY = (_activeState._panTargetPoint.y - _activeState._currPan2.y) << 16; + } + +} + +bool Camera::calcPointFlags(Common::Point &pt, WRect &rect, uint &outFlags) { + bool result = false; + if (pt.x < rect._topLeft.x) { + outFlags |= 1; + result = true; + } else if (pt.x > rect._bottomRight.x) { + outFlags |= 2; + result = true; + } + if (pt.y < rect._topLeft.y) { + outFlags |= 4; + result = true; + } else if (pt.y > rect._bottomRight.y) { + outFlags |= 8; + result = true; + } + return result; +} + +void Camera::clipPanTargetPoint() { + _activeState._panTargetPoint.x = CLIP(_activeState._panTargetPoint.x, + _activeState._bounds._topLeft.x, _activeState._bounds._bottomRight.x); + _activeState._panTargetPoint.y = CLIP(_activeState._panTargetPoint.y, + _activeState._bounds._topLeft.y, _activeState._bounds._bottomRight.y); +} + } // End of namespace Illusions diff --git a/engines/illusions/camera.h b/engines/illusions/camera.h index 816c5dda21..6c9556c88d 100644 --- a/engines/illusions/camera.h +++ b/engines/illusions/camera.h @@ -46,20 +46,36 @@ struct CameraState { Common::Point _currPan2; Common::Point _panTargetPoint; Common::Point _trackingLimits; - Common::Point _pt; + Common::Point _centerPt; uint32 _panObjectId; Common::Point *_panToPositionPtr; uint _pointFlags; //field_4A dw }; +struct CameraModeStackItem { + int _cameraMode; + uint32 _panObjectId; + int16 _panSpeed; + Common::Point _panTargetPoint; + uint32 _panNotifyId; +}; + class Camera { public: Camera(IllusionsEngine *vm); void clearStack(); void set(Common::Point &panPoint, WidthHeight &dimensions); + void panCenterObject(uint32 objectId, int16 panSpeed); + void panTrackObject(uint32 objectId); + void panToPoint(Common::Point pt, int16 panSpeed, uint32 panNotifyId); + void panEdgeFollow(uint32 objectId, int16 panSpeed); + void stopPan(); void pause(); void unpause(); + void pushCameraMode(); + void popCameraMode(); + void clearCameraModeStack(); void update(uint32 currTime); void setBounds(Common::Point &minPt, Common::Point &maxPt); void setBoundsToDimensions(WidthHeight &dimensions); @@ -68,13 +84,16 @@ public: protected: IllusionsEngine *_vm; CameraState _activeState; - Common::FixedStack<CameraState, 8> _stack; + Common::FixedStack<CameraModeStackItem, 8> _stack; void updateMode1(uint32 currTime); void updateMode2(uint32 currTime); void updateMode3(uint32 currTime); bool updatePan(uint32 currTime); bool isPanFinished(); Common::Point getPtOffset(Common::Point pt); + void recalcPan(uint32 currTime); + bool calcPointFlags(Common::Point &pt, WRect &rect, uint &outFlags); + void clipPanTargetPoint(); }; } // End of namespace Illusions diff --git a/engines/illusions/fixedpoint.cpp b/engines/illusions/fixedpoint.cpp new file mode 100644 index 0000000000..ee3818d10a --- /dev/null +++ b/engines/illusions/fixedpoint.cpp @@ -0,0 +1,62 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "illusions/illusions.h" +#include "illusions/fixedpoint.h" + +namespace Illusions { + +FP16 floatToFixed(float value) { + return value * 65536.0; +} + +float fixedToFloat(FP16 value) { + return value / 65536.0; +} + +FP16 fixedMul(FP16 a, FP16 b) { + // CHECKME Not sure if this correct + return (a * b) >> 16; +} + +FP16 fixedDiv(FP16 a, FP16 b) { + // CHECKME Not sure if this correct + return (a << 16) / b; +} + +int fixedTrunc(FP16 value) { + // CHECKME Not sure if this correct + int result = value >> 16; + if ((value & 0xFFFF) >= 0x8000) + ++result; + return result; +} + +FP16 fixedDistance(FP16 x1, FP16 y1, FP16 x2, FP16 y2) { + float xd = ABS(fixedToFloat(x1) - fixedToFloat(x2)); + float yd = ABS(fixedToFloat(y1) - fixedToFloat(y2)); + if (xd != 0.0 || yd != 0.0) + return floatToFixed(sqrt(xd * xd + yd * yd)); + return 0; +} + +} // End of namespace Illusions diff --git a/engines/illusions/fixedpoint.h b/engines/illusions/fixedpoint.h new file mode 100644 index 0000000000..a14eb8b51b --- /dev/null +++ b/engines/illusions/fixedpoint.h @@ -0,0 +1,45 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ILLUSIONS_FIXEDPOINT_H +#define ILLUSIONS_FIXEDPOINT_H + +#include "common/rect.h" + +namespace Illusions { + +typedef int32 FP16; + +struct FPRect { + FP16 x1, y1, x2, y2; +}; + +FP16 floatToFixed(float value); +float fixedToFloat(FP16 value); +FP16 fixedMul(FP16 a, FP16 b); +FP16 fixedDiv(FP16 a, FP16 b); +int fixedTrunc(FP16 value); +FP16 fixedDistance(FP16 x1, FP16 y1, FP16 x2, FP16 y2); + +} // End of namespace Illusions + +#endif // ILLUSIONS_FIXEDPOINT_H diff --git a/engines/illusions/illusions.cpp b/engines/illusions/illusions.cpp index 47ed48cc09..e36518d148 100644 --- a/engines/illusions/illusions.cpp +++ b/engines/illusions/illusions.cpp @@ -164,4 +164,9 @@ Graphics::Surface *IllusionsEngine::getBackSurface() { return 0; } +Common::Point *IllusionsEngine::getObjectActorPositionPtr(uint32 objectId) { + // TODO Dummy, to be replaced later + return 0; +} + } // End of namespace Illusions diff --git a/engines/illusions/illusions.h b/engines/illusions/illusions.h index f7348675af..8978d8dd10 100644 --- a/engines/illusions/illusions.h +++ b/engines/illusions/illusions.h @@ -80,6 +80,8 @@ public: bool isDisplayOn(); uint16 getColorKey2(); Graphics::Surface *getBackSurface(); + + Common::Point *getObjectActorPositionPtr(uint32 objectId); #if 0 diff --git a/engines/illusions/module.mk b/engines/illusions/module.mk index 504f636fb8..30fd9b9cd7 100644 --- a/engines/illusions/module.mk +++ b/engines/illusions/module.mk @@ -5,6 +5,7 @@ MODULE_OBJS := \ backgroundresource.o \ camera.o \ detection.o \ + fixedpoint.o \ graphics.o \ illusions.o \ input.o \ |