diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sherlock/graphics.cpp | 26 | ||||
-rw-r--r-- | engines/sherlock/graphics.h | 8 | ||||
-rw-r--r-- | engines/sherlock/objects.cpp | 104 | ||||
-rw-r--r-- | engines/sherlock/objects.h | 5 | ||||
-rw-r--r-- | engines/sherlock/people.h | 2 | ||||
-rw-r--r-- | engines/sherlock/scene.cpp | 107 | ||||
-rw-r--r-- | engines/sherlock/scene.h | 8 | ||||
-rw-r--r-- | engines/sherlock/sherlock.cpp | 3 | ||||
-rw-r--r-- | engines/sherlock/sherlock.h | 3 |
9 files changed, 251 insertions, 15 deletions
diff --git a/engines/sherlock/graphics.cpp b/engines/sherlock/graphics.cpp index a4990fb6c6..8c096e3c72 100644 --- a/engines/sherlock/graphics.cpp +++ b/engines/sherlock/graphics.cpp @@ -27,12 +27,22 @@ namespace Sherlock { -Surface::Surface(uint16 width, uint16 height) { +Surface::Surface(uint16 width, uint16 height): _freePixels(true) { create(width, height, Graphics::PixelFormat::createFormatCLUT8()); } +Surface::Surface(Surface &src, const Common::Rect &r) : _freePixels(false) { + setPixels(src.getBasePtr(r.left, r.top)); + w = r.width(); + h = r.height(); + pitch = src.pitch; + format = Graphics::PixelFormat::createFormatCLUT8(); +} + + Surface::~Surface() { - free(); + if (_freePixels) + free(); } /** @@ -131,9 +141,19 @@ void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &p } } - +/** + * Fill a given area of the surface with a given color + */ void Surface::fillRect(int x1, int y1, int x2, int y2, byte color) { Graphics::Surface::fillRect(Common::Rect(x1, y1, x2, y2), color); } +/** + * Return a sub-area of the surface as a new surface object. The surfaces + * are shared in common, so changes in the sub-surface affects the original. + */ +Surface Surface::getSubArea(const Common::Rect &r) { + return Surface(*this, r); +} + } // End of namespace Sherlock diff --git a/engines/sherlock/graphics.h b/engines/sherlock/graphics.h index 82c48307d7..0536c016bf 100644 --- a/engines/sherlock/graphics.h +++ b/engines/sherlock/graphics.h @@ -29,11 +29,15 @@ namespace Sherlock { class Surface : public Graphics::Surface { +private: + bool _freePixels; protected: virtual void addDirtyRect(const Common::Rect &r) {} + + Surface(Surface &src, const Common::Rect &r); public: Surface(uint16 width, uint16 height); - ~Surface(); + ~Surface(); void blitFrom(const Graphics::Surface &src); void blitFrom(const Graphics::Surface &src, const Common::Point &pt); @@ -43,6 +47,8 @@ public: bool flipped = false, int overrideColor = 0); void fillRect(int x1, int y1, int x2, int y2, byte color); + + Surface getSubArea(const Common::Rect &r); }; } // End of namespace Sherlock diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp index 63e4bdf621..a12939e787 100644 --- a/engines/sherlock/objects.cpp +++ b/engines/sherlock/objects.cpp @@ -24,9 +24,15 @@ #include "sherlock/sherlock.h" #include "sherlock/people.h" #include "sherlock/scene.h" +#include "common/util.h" namespace Sherlock { +#define UPPER_LIMIT 0 +#define LOWER_LIMIT CONTROLS_Y +#define LEFT_LIMIT 0 +#define RIGHT_LIMIT SHERLOCK_SCREEN_WIDTH + SherlockEngine *Sprite::_vm; /** @@ -56,14 +62,106 @@ void Sprite::clear() { _numFrames = 0; } +/** + * Updates the image frame poiner for the sprite + */ void Sprite::setImageFrame() { - // TODO: check this - int imageNumber = (*_sequences)[_sequenceNumber][_frameNumber]; + int imageNumber = (*_sequences)[_sequenceNumber][_frameNumber] + + (*_sequences)[_sequenceNumber][0] - 2; _imageFrame = &(*_images)[imageNumber]; } +/** + * This adjusts the sprites position, as well as it's animation sequence: + */ void Sprite::adjustSprite() { - // TODO + People &people = *_vm->_people; + Scene &scene = *_vm->_scene; + int checkFrame = _allow ? MAX_FRAME : 32000; + + if (_type == INVALID || (_type == CHARACTER && _vm->_animating)) + return; + + if (!_vm->_talkCounter && _type == CHARACTER && _walkCount) { + // Handle active movement for the sprite + _position += _delta; + --_walkCount; + + if (!_walkCount) { + // If there any points left for the character to walk to along the + // route to a destination, then move to the next point + if (!people._walkTo.empty()) { + people._walkDest = people._walkTo.pop(); + people.setWalking(); + } else { + people.gotoStand(*this); + } + } + } + + if (_type == CHARACTER && !_vm->_onChessboard) { + if ((_position.y / 100) > LOWER_LIMIT) { + _position.y = LOWER_LIMIT * 100; + people.gotoStand(*this); + } + + if ((_position.y / 100) < UPPER_LIMIT) { + _position.y = UPPER_LIMIT * 100; + people.gotoStand(*this); + } + + if ((_position.x / 100) < LEFT_LIMIT) { + _position.x = LEFT_LIMIT * 100; + people.gotoStand(*this); + } + } else if (!_vm->_onChessboard) { + _position.y = CLIP((int)_position.y, UPPER_LIMIT, LOWER_LIMIT); + _position.x = CLIP((int)_position.x, LEFT_LIMIT, RIGHT_LIMIT); + } + + if (!_vm->_onChessboard || (_vm->_slowChess = !_vm->_slowChess)) + ++_frameNumber; + + if ((*_sequences)[_sequenceNumber][_frameNumber] == 0) { + switch (_sequenceNumber) { + case STOP_UP: + case STOP_DOWN: + case STOP_LEFT: + case STOP_RIGHT: + case STOP_UPRIGHT: + case STOP_UPLEFT: + case STOP_DOWNRIGHT: + case STOP_DOWNLEFT: + // We're in a stop sequence, so reset back to the last frame, so + // the character is shown as standing still + --_frameNumber; + break; + + default: + // Move 1 past the first frame - we need to compensate, since we + // already passed the frame increment + _frameNumber = 1; + break; + } + } + + // Update the _imageFrame to point to the new frame's image + setImageFrame(); + + // Check to see if character has entered an exit zone + if (!_walkCount && scene._walkedInScene && scene._goToRoom == -1) { + Common::Rect charRect(_position.x / 100 - 5, _position.y / 100 - 2, + _position.x / 100 + 5, _position.y / 100 + 2); + Exit *exit = scene.checkForExit(charRect); + + if (exit) { + scene._hsavedPos = exit->_people; + scene._hsavedFs = exit->_peopleDir; + + if (scene._hsavedFs > 100 && scene._hsavedPos.x < 1) + scene._hsavedPos.x = 100; + } + } } /*----------------------------------------------------------------*/ diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h index b1207867e4..d9f1c7409e 100644 --- a/engines/sherlock/objects.h +++ b/engines/sherlock/objects.h @@ -66,6 +66,11 @@ enum AType { NOWALK_ZONE = 13 // Player cannot walk here }; +// Different levels for sprites to be at +enum { + BEHIND = 0, NORMAL_BEHIND = 1, NORMAL_FORWARD = 2, FORWARD = 3 +}; + #define MAX_HOLMES_SEQUENCE 16 #define MAX_FRAME 30 diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h index be9be006e8..e58fd33ef2 100644 --- a/engines/sherlock/people.h +++ b/engines/sherlock/people.h @@ -70,6 +70,8 @@ public: Sprite &operator[](PeopleId id) { return _data[id]; } + bool isHolmesActive() const { return _walkLoaded && _holmesOn; } + void reset(); bool loadWalk(); diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp index 13db8d9b94..9fbec6b776 100644 --- a/engines/sherlock/scene.cpp +++ b/engines/sherlock/scene.cpp @@ -49,10 +49,12 @@ void BgfileheaderInfo::synchronize(Common::SeekableReadStream &s) { /*----------------------------------------------------------------*/ void Exit::synchronize(Common::SeekableReadStream &s) { - _position.x = s.readSint16LE(); - _position.y = s.readSint16LE(); - _size.x = s.readSint16LE(); - _size.y = s.readSint16LE(); + int xp = s.readSint16LE(); + int yp = s.readSint16LE(); + int xSize = s.readSint16LE(); + int ySize = s.readSint16LE(); + _bounds = Common::Rect(xp, yp, xp + xSize, yp + ySize); + _scene = s.readSint16LE(); _allow = s.readSint16LE(); _people.x = s.readSint16LE(); @@ -623,13 +625,106 @@ int Scene::toggleObject(const Common::String &name) { */ void Scene::updateBackground() { People &people = *_vm->_people; - //setDisplayBounds(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT); + Screen &screen = *_vm->_screen; + Surface surface = screen._backBuffer.getSubArea( + Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT)); + Sprite &player = people[AL]; // Update Holmes if he's turned on if (people._holmesOn) - people[AL].adjustSprite(); + player.adjustSprite(); + + // Flag the bg shapes which need to be redrawn + checkBgShapes(player._imageFrame, Common::Point(player._position.x / 100, + player._position.y / 100)); + + // Draw all active shapes which are behind the person + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == BEHIND) + surface.transBlitFrom(_bgShapes[idx]._imageFrame->_frame, + _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + } + + // Draw all canimations which are behind the person + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == BEHIND) + surface.transBlitFrom(_canimShapes[idx]._imageFrame->_frame, + _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); + } + + // Draw all active shapes which are normal and behind the person + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == NORMAL_BEHIND) + surface.transBlitFrom(_bgShapes[idx]._imageFrame->_frame, + _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + } + + // Draw all canimations which are normal and behind the person + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == NORMAL_BEHIND) + surface.transBlitFrom(_canimShapes[idx]._imageFrame->_frame, + _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); + } + + // Draw the player if he's active + if (player._type == CHARACTER && people.isHolmesActive()) { + bool flipped = player._sequenceNumber == WALK_LEFT || player._sequenceNumber == STOP_LEFT || + player._sequenceNumber == WALK_UPLEFT || player._sequenceNumber == STOP_UPLEFT || + player._sequenceNumber == WALK_DOWNRIGHT || player._sequenceNumber == STOP_DOWNRIGHT; + + surface.transBlitFrom(player._imageFrame->_frame, + Common::Point(player._position.x / 100, player._position.y / 100), flipped); + } + // Draw all static and active shapes that are NORMAL and are in front of the player + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) && + _bgShapes[idx]._misc == NORMAL_FORWARD) + surface.transBlitFrom(_bgShapes[idx]._imageFrame->_frame, + _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + } + + // Draw all static and active canimations that are NORMAL and are in front of the player + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) && + _canimShapes[idx]._misc == NORMAL_FORWARD) + surface.transBlitFrom(_canimShapes[idx]._imageFrame->_frame, + _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); + } + + // Draw all static and active shapes that are FORWARD + for (uint idx = 0; idx < _bgShapes.size(); ++idx) { + _bgShapes[idx]._oldPosition = _bgShapes[idx]._position; + _bgShapes[idx]._oldSize = Common::Point(_bgShapes[idx]._imageFrame->_frame.w, + _bgShapes[idx]._imageFrame->_frame.h); + + if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) && + _bgShapes[idx]._misc == FORWARD) + surface.transBlitFrom(_bgShapes[idx]._imageFrame->_frame, + _bgShapes[idx]._position, _bgShapes[idx]._flags & 2); + } + + // Draw all static and active canimations that are forward + for (uint idx = 0; idx < _canimShapes.size(); ++idx) { + if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) && + _canimShapes[idx]._misc == FORWARD) + surface.transBlitFrom(_canimShapes[idx]._imageFrame->_frame, + _canimShapes[idx]._position, _canimShapes[idx]._flags & 2); + } +} + +Exit *Scene::checkForExit(const Common::Rect &r) { + for (uint idx = 0; idx < _exits.size(); ++idx) { + if (_exits[idx]._bounds.intersects(r)) + return &_exits[idx]; + } + return nullptr; } +void Scene::checkBgShapes(ImageFrame *frame, const Common::Point &pt) { + // TODO +} + + } // End of namespace Sherlock diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h index a4b94652c8..8986b62bf5 100644 --- a/engines/sherlock/scene.h +++ b/engines/sherlock/scene.h @@ -59,8 +59,7 @@ struct BgfileheaderInfo { }; struct Exit { - Common::Point _position; - Common::Point _size; + Common::Rect _bounds; int _scene; int _allow; @@ -100,6 +99,8 @@ private: int toggleObject(const Common::String &name); void updateBackground(); + + void checkBgShapes(ImageFrame *frame, const Common::Point &pt); public: int _currentScene; int _goToRoom; @@ -134,6 +135,7 @@ public: Common::Array<SceneSound> _sounds; Common::Point _hsavedPos; int _hsavedFs; + Common::Array<Object> _canimShapes; public: Scene(SherlockEngine *vm); ~Scene(); @@ -143,6 +145,8 @@ public: void selectScene(); void checkSceneFlags(bool mode); + + Exit *checkForExit(const Common::Rect &r); }; } // End of namespace Sherlock diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp index 2787e2b924..257cbb2cab 100644 --- a/engines/sherlock/sherlock.cpp +++ b/engines/sherlock/sherlock.cpp @@ -45,6 +45,9 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam _justLoaded = false; _talkToAbort = false; _onChessboard = false; + _slowChess = false; + _animating = false; + _talkCounter = 0; } SherlockEngine::~SherlockEngine() { diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h index 1607cec974..7ce28cfdd7 100644 --- a/engines/sherlock/sherlock.h +++ b/engines/sherlock/sherlock.h @@ -98,6 +98,9 @@ public: Common::Array<Common::Point> _map; // Map locations for each scene bool _talkToAbort; bool _onChessboard; + bool _slowChess; + bool _animating; + int _talkCounter; public: SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc); virtual ~SherlockEngine(); |