SHERLOCK: Implemented doBgAnim

This commit is contained in:
Paul Gilbert 2015-03-22 00:52:02 -04:00
parent 7f04ea4425
commit ff02c29e9c
12 changed files with 751 additions and 26 deletions

View File

@ -28,6 +28,8 @@
namespace Sherlock {
#define START_FRAME 0
#define UPPER_LIMIT 0
#define LOWER_LIMIT CONTROLS_Y
#define LEFT_LIMIT 0
@ -37,6 +39,10 @@ namespace Sherlock {
#define CLEAR_DIST_X 5
#define CLEAR_DIST_Y 0
#define INFO_FOREGROUND 11
#define INFO_BACKGROUND 1
SherlockEngine *Sprite::_vm;
/**
@ -83,7 +89,7 @@ void Sprite::adjustSprite() {
Scene &scene = *_vm->_scene;
Talk &talk = *_vm->_talk;
if (_type == INVALID || (_type == CHARACTER && _vm->_animating))
if (_type == INVALID || (_type == CHARACTER && scene._animating))
return;
if (!talk._talkCounter && _type == CHARACTER && _walkCount) {
@ -457,7 +463,7 @@ void Object::synchronize(Common::SeekableReadStream &s) {
_seqStack = s.readByte();
_seqTo = s.readByte();
_descOffset = s.readUint16LE();
_seqcounter2 = s.readByte();
_seqCounter2 = s.readByte();
_seqSize = s.readUint16LE();
s.skip(1);
_aMove.synchronize(s);
@ -487,7 +493,7 @@ void Object::toggleHidden() {
_sequences[_frameNumber] = _seqTo + SEQ_TO_CODE + 128;
_seqTo = 0;
_seqCounter = _seqcounter2 = 0;
_seqCounter = _seqCounter2 = 0;
_seqStack = 0;
_frameNumber = -1;
@ -544,7 +550,7 @@ void Object::checkObject(Object &o) {
if (v >= 228) {
// Goto code found
v -= 228;
_seqcounter2 = _seqCounter;
_seqCounter2 = _seqCounter;
_seqStack = _frameNumber + 1;
setObjSequence(v, false);
} else if (v >= SOUND_CODE && (v <= (SOUND_CODE + 29))) {
@ -631,29 +637,290 @@ void Object::checkObject(Object &o) {
} while (codeFound);
}
bool Object::checkEndOfSequence() const {
// TODO
return false;
/**
* This will check to see if the object has reached the end of a sequence.
* If it has, it switch to whichever next sequence should be started.
* @returns true if the end of a sequence was reached
*/
bool Object::checkEndOfSequence() {
Screen &screen = *_vm->_screen;
int checkFrame = _allow ? MAX_FRAME : 32000;
bool result = false;
if (_type == REMOVE || _type == INVALID)
return false;
if (_sequences[_frameNumber] == 0 || _frameNumber >= checkFrame) {
result = true;
if (_frameNumber >= (checkFrame - 1)) {
_frameNumber = START_FRAME;
} else {
// Determine next sequence to use
int seq = _sequences[_frameNumber + 1];
if (seq == 99) {
--_frameNumber;
screen._backBuffer.transBlitFrom(_imageFrame->_frame, _position);
screen._backBuffer2.transBlitFrom(_imageFrame->_frame, _position);
_type = INVALID;
} else {
setObjSequence(seq, false);
}
}
}
if (_allow && _frameNumber == 0) {
// canimation just ended
if (_type != NO_SHAPE && _type != REMOVE) {
_type = REMOVE;
if (!_countCAnimFrames) {
// Save details before shape is removed
_delta.x = _imageFrame->_frame.w;
_delta.y = _imageFrame->_frame.h;
_position = _imageFrame->_offset;
// Free the images
delete _images;
}
} else {
_type = INVALID;
}
}
return result;
}
/**
* Scans through the sequences array and finds the designated sequence.
* It then sets the frame number of the start of that sequence
*/
void Object::setObjSequence(int seq, bool wait) {
// TODO
Scene &scene = *_vm->_scene;
int checkFrame = _allow ? MAX_FRAME : 32000;
if (seq >= 128) {
// Loop the sequence until the count exceeded
seq -= 128;
++_seqCounter;
if (_seqCounter >= seq) {
// Go to next sequence
if (_seqStack) {
_frameNumber = _seqStack;
_seqStack = 0;
_seqCounter = _seqCounter2;
_seqCounter2 = 0;
if (_frameNumber >= checkFrame)
_frameNumber = START_FRAME;
return;
}
_frameNumber += 2;
if (_frameNumber >= checkFrame)
_frameNumber = 0;
_seqCounter = 0;
if (_sequences[_frameNumber] == 0)
seq = _sequences[_frameNumber + 1];
else
return;
} else {
// Find beginning of sequence
do {
--_frameNumber;
} while (_frameNumber > 0 && _sequences[_frameNumber] != 0);
if (_frameNumber != 0)
_frameNumber += 2;
return;
}
} else {
// Reset sequence counter
_seqCounter = 0;
}
int idx = 0;
int seqCc = 0;
while (seqCc < seq && idx < checkFrame) {
++idx;
if (_sequences[idx] == 0) {
++seqCc;
idx += 2;
}
}
if (idx >= checkFrame)
idx = 0;
_frameNumber = idx;
if (wait) {
seqCc = idx;
while (_sequences[idx] != 0)
++idx;
idx = idx - seqCc + 2;
for (; idx > 0; --idx)
scene.doBgAnim();
}
}
/**
* Checks for codes
* @param name The name to check for codes
* @param messages If provided, any messages to be returned
* @param messages Provides a lookup list of messages that can be printed
* @returns 0 if no codes are found, 1 if codes were found
*/
int Object::checkNameForCodes(const Common::String &name, Common::StringArray *messages) {
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
bool printed = false;
char ch;
const char *p;
// TODO
return 0;
scene.toggleObject(name);
if (name.hasPrefix("*")) {
// A code was found
printed = true;
ch = toupper(name[1]);
switch (ch) {
case 'C':
talk.talkTo(name.c_str() + 2);
break;
case 'T':
case 'B':
case 'F':
case 'W':
// Nothing: action was already done before canimation
break;
case 'G':
case 'A': {
// G: Have object go somewhere
// A: Add onto existing co-ordinates
Common::String sx(name.c_str() + 2, name.c_str() + 5);
Common::String sy(name.c_str() + 6, name.c_str() + 9);
if (ch == 'G')
_position = Common::Point(atoi(sx.c_str()), atoi(sy.c_str()));
else
_position += Common::Point(atoi(sx.c_str()), atoi(sy.c_str()));
break;
}
default:
if (ch >= '0' && ch <= '9') {
scene._goToRoom = atoi(name.c_str() + 1);
if (scene._goToRoom < 97 && _vm->_map[scene._goToRoom].x) {
_vm->_over.x = _vm->_map[scene._goToRoom].x * 100 - 600;
_vm->_over.y = _vm->_map[scene._goToRoom].y * 100 + 900;
}
if ((p = strchr(name.c_str(), ',')) != nullptr) {
++p;
Common::String s(p, p + 3);
scene._hsavedPos.x = atoi(s.c_str());
s = Common::String(p + 3, p + 6);
scene._hsavedPos.y = atoi(s.c_str());
s = Common::String(p + 6, p + 9);
scene._hsavedFs = atoi(s.c_str());
if (scene._hsavedFs == 0)
scene._hsavedFs = 10;
} else if ((p = strchr(name.c_str(), '/')) != nullptr) {
scene._hsavedPos = Common::Point(1, 0);
scene._hsavedFs = 100 + atoi(p + 1);
}
} else {
scene._goToRoom = 100;
}
people[AL]._position = Common::Point(0, 0);
break;
}
} else if (name.hasPrefix("!")) {
// Message attached to canimation
int messageNum = atoi(name.c_str() + 1);
scene._infoFlag++;
scene.clearInfo();
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, INFO_BACKGROUND,
(*messages)[messageNum].c_str());
_vm->_menuCounter = 25;
} else if (name.hasPrefix("@")) {
// Message attached to canimation
scene._infoFlag++;
scene.clearInfo();
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, INFO_BACKGROUND,
"%s", name.c_str() + 1);
printed = true;
_vm->_menuCounter = 25;
}
return printed;
}
/**
* Handle setting any flags associated with the object
*/
void Object::setFlagsAndToggles() {
// TODO
Scene &scene = *_vm->_scene;
Talk &talk = *_vm->_talk;
for (int useIdx = 0; useIdx < 4; ++useIdx) {
if (_use[useIdx]._useFlag) {
if (!_vm->readFlags(_use[useIdx]._useFlag))
_vm->setFlags(_use[useIdx]._useFlag);
}
if (_use[useIdx]._cAnimSpeed) {
if (_use[useIdx]._cAnimNum == 0)
// 0 is really a 10
scene.startCAnim(_use[useIdx]._cAnimNum - 1, _use[useIdx]._cAnimSpeed);
}
if (!talk._talkToAbort) {
for (int idx = 0; idx < 4; ++idx)
scene.toggleObject(_use[useIdx]._names[idx]);
}
}
}
/**
* Adjusts the sprite's position and animation sequence, advancing by 1 frame.
* If the end of the sequence is reached, the appropriate action is taken.
*/
void Object::adjustObject() {
if (_type == REMOVE)
return;
_position += _delta;
if (_position.y > LOWER_LIMIT)
_position.y = LOWER_LIMIT;
if (_type != NO_SHAPE) {
int frame = _frameNumber;
if (frame == -1)
frame = 0;
int imgNum = _sequences[frame];
if (imgNum > _maxFrames)
imgNum = 1;
_imageFrame = &(*_images)[imgNum - 1];
}
}
/*----------------------------------------------------------------*/

View File

@ -143,7 +143,7 @@ class Object {
private:
static SherlockEngine *_vm;
bool checkEndOfSequence() const;
bool checkEndOfSequence();
void setObjSequence(int seq, bool wait);
public:
@ -190,7 +190,7 @@ public:
int _seqStack; // Allows gosubs to return to calling frame
int _seqTo; // Allows 1-5, 8-3 type sequences encoded in 2 bytes
uint _descOffset; // Tells where description starts in DescText
int _seqcounter2; // Counter of calling frame sequence
int _seqCounter2; // Counter of calling frame sequence
uint _seqSize; // Tells where description starts
ActionType _aMove;
UseType _use[4];
@ -204,6 +204,8 @@ public:
int checkNameForCodes(const Common::String &name, Common::StringArray *messages);
void setFlagsAndToggles();
void adjustObject();
};
struct CAnim {

View File

@ -56,6 +56,8 @@ People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) {
_holmesOn = true;
_oldWalkSequence = -1;
_allowWalkAbort = false;
_portraitLoaded = false;
_clearingThePortrait = false;
}
People::~People() {

View File

@ -64,6 +64,9 @@ public:
Common::Point _walkDest;
Common::Stack<Common::Point> _walkTo;
bool _holmesOn;
bool _portraitLoaded;
Object _portrait;
bool _clearingThePortrait;
public:
People(SherlockEngine *vm);
~People();

View File

@ -336,6 +336,27 @@ void ScalpelEngine::startScene() {
_chessResult = _scene->_goToRoom;
}
/**
* Takes care of clearing the mirror in scene 12, in case anything drew over it
*/
void ScalpelEngine::eraseMirror12() {
// TODO
}
/**
* Takes care of drawing Holme's reflection onto the mirror in scene 12
*/
void ScalpelEngine::doMirror12() {
// TODO
}
/**
* This clears the mirror in scene 12 in case anything messed draw over it
*/
void ScalpelEngine::flushMirror12() {
// TODO
}
} // End of namespace Scalpel
} // End of namespace Scalpel

View File

@ -51,6 +51,10 @@ protected:
public:
ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc);
virtual ~ScalpelEngine();
void eraseMirror12();
void doMirror12();
void flushMirror12();
};
} // End of namespace Scalpel

View File

@ -22,10 +22,42 @@
#include "sherlock/scene.h"
#include "sherlock/sherlock.h"
#include "sherlock/scalpel/scalpel.h"
#include "sherlock/decompress.h"
namespace Sherlock {
// Main Menu control locations
const int MENU_POINTS[12][4] = {
{ 13, 153, 72, 165 },
{ 13, 169, 72, 181 },
{ 13, 185, 72, 197 },
{ 88, 153, 152, 165 },
{ 88, 169, 152, 181 },
{ 88, 185, 152, 197 },
{ 165, 153, 232, 165 },
{ 165, 169, 232, 181 },
{ 165, 185, 233, 197 },
{ 249, 153, 305, 165 },
{ 249, 169, 305, 181 },
{ 249, 185, 305, 197 }
};
// Inventory control locations */
const int INVENTORY_POINTS[8][3] = {
{ 4, 50, 28 },
{ 52, 99, 76 },
{ 101, 140, 122 },
{ 142, 187, 165 },
{ 189, 219, 197 },
{ 221, 251, 233 },
{ 253, 283, 265 },
{ 285, 315, 293 }
};
/*----------------------------------------------------------------*/
void BgFileHeader::synchronize(Common::SeekableReadStream &s) {
_numStructs = s.readUint16LE();
_numImages = s.readUint16LE();
@ -89,7 +121,8 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) {
_goToRoom = -1;
_changes = false;
_charPoint = _oldCharPoint = 0;
_windowOpen = _infoFlag = false;
_windowOpen = false;
_infoFlag = false;
_keyboardInput = 0;
_walkedInScene = false;
_ongoingCans = 0;
@ -102,6 +135,10 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) {
_menuMode = STD_MODE;
_invMode = INVMODE_0;
_restoreFlag = false;
_invLookFlag = false;
_lookHelp = false;
_animating = 0;
_doBgAnimDone = true;
_controlPanel = new ImageFile("controls.vgs");
_controls = nullptr; // new ImageFile("menu.all");
@ -236,7 +273,7 @@ bool Scene::loadScene(const Common::String &filename) {
_bgShapes[idx]._sequences = &_sequenceBuffer[_bgShapes[idx]._sequenceOffset];
_bgShapes[idx]._misc = 0;
_bgShapes[idx]._seqCounter = 0;
_bgShapes[idx]._seqcounter2 = 0;
_bgShapes[idx]._seqCounter2 = 0;
_bgShapes[idx]._seqStack = 0;
_bgShapes[idx]._frameNumber = -1;
_bgShapes[idx]._position = Common::Point(0, 0);
@ -799,7 +836,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) {
Talk &talk = *_vm->_talk;
Common::Point tpPos, walkPos;
int tpDir, walkDir;
int tFrames;
int tFrames = 0;
int gotoCode = -1;
// Validation
@ -996,8 +1033,52 @@ int Scene::startCAnim(int cAnimNum, int playRate) {
return 1;
}
/**
* Print the description of an object
*/
void Scene::printObjDesc(const Common::String &str, bool firstTime) {
/* TODO
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
int savedSelector;
if (str.hasPrefix("_")) {
_lookScriptFlag = true;
events.setCursor(MAGNIFY);
savedSelector = _selector;
talk.talkTo(str.c_str() + 1);
_lookScriptFlag = false;
if (talk._talkToAbort) {
events.setCursor(ARROW);
return;
}
// Check if looking at an inventory object
if (!_invLookFlag) {
// See if this look was called by a right button click or not
if (!_lookHelp) {
// If it wasn't a right button click, then we need depress
// the look button before we close the window. So save a copy of the
// menu area, and draw the controls onto it
Surface tempSurface((*_controls)[0]._frame->w, (*_controls)[0]._frame->h);
tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0),
Common::Rect(MENU_POINTS[0][0], MENU_POINTS[0][1],
MENU_POINTS[0][0] + tempSurface.w, MENU_POINTS[0][1] + tempSurface.h));
screen._backBuffer2.transBlitFrom((*_controls)[0]._frame,
Common::Point(MENU_POINTS[0][0], MENU_POINTS[0][1]));
banishWindow(1);
events.setCursor(MAGNIFY);
}
}
}
// TODO
*/
}
/**
@ -1047,9 +1128,270 @@ void Scene::doBgAnim() {
if (_restoreFlag) {
if (people[AL]._type == CHARACTER)
people[AL].checkSprite();
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE)
_bgShapes[idx].checkObject(_bgShapes[idx]);
}
if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
people._portrait.checkObject(people._portrait);
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if (_canimShapes[idx]._type != INVALID && _canimShapes[idx]._type != REMOVE)
_canimShapes[idx].checkObject(_bgShapes[0]);
}
if (_currentScene == 12 && _vm->getGameID() == GType_SerratedScalpel)
((Scalpel::ScalpelEngine *)_vm)->eraseMirror12();
// Restore the back buffer from the back buffer 2 in the changed area
Common::Rect bounds(people[AL]._oldPosition.x, people[AL]._oldPosition.y,
people[AL]._oldPosition.x + people[AL]._oldSize.x,
people[AL]._oldPosition.y + people[AL]._oldSize.y);
Common::Point pt(bounds.left, bounds.top);
if (people[AL]._type == CHARACTER)
screen.restoreBackground(bounds);
else if (people[AL]._type == REMOVE)
screen._backBuffer.blitFrom(screen._backBuffer2, pt, bounds);
for (uint idx = 0; _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == ACTIVE_BG_SHAPE || o._type == HIDE_SHAPE || o._type == REMOVE)
screen.restoreBackground(bounds);
}
if (people._portraitLoaded)
screen.restoreBackground(Common::Rect(
people._portrait._oldPosition.x, people._portrait._oldPosition.y,
people._portrait._oldPosition.x + people._portrait._oldSize.x,
people._portrait._oldPosition.y + people._portrait._oldSize.y
));
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == NO_SHAPE && ((o._flags & 1) == 0)) {
// Restore screen area
screen._backBuffer.blitFrom(screen._backBuffer2, o._position,
Common::Rect(o._position.x, o._position.y,
o._position.x + o._noShapeSize.x, o._position.y + o._noShapeSize.y));
o._oldPosition = o._position;
o._oldSize = o._noShapeSize;
}
}
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = _canimShapes[idx];
if (o._type == ACTIVE_BG_SHAPE || o._type == HIDE_SHAPE || o._type == REMOVE)
screen.restoreBackground(Common::Rect(o._oldPosition.x, o._oldPosition.y,
o._oldPosition.x + o._oldSize.x, o._oldPosition.y + o._oldSize.y));
}
}
//
// Update the background objects and canimations
//
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == ACTIVE_BG_SHAPE || o._type == NO_SHAPE)
o.adjustObject();
}
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if (_canimShapes[idx]._type != INVALID)
_canimShapes[idx].adjustObject();
}
if (people[AL]._type == CHARACTER && people._holmesOn)
people[AL].adjustSprite();
// Flag the bg shapes which need to be redrawn
checkBgShapes(people[AL]._imageFrame,
Common::Point(people[AL]._position.x / 100, people[AL]._position.y / 100));
if (_currentScene == 12 && _vm->getGameID() == GType_SerratedScalpel)
((Scalpel::ScalpelEngine *)_vm)->doMirror12();
// Draw all active shapes which are behind the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND)
screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
}
// Draw all canimations which are behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = _canimShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) {
screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
}
}
// Draw all active shapes which are HAPPEN and behind the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND)
screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
}
// Draw all canimations which are NORMAL and behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = _canimShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) {
screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
}
}
// Draw the person if not animating
if (people[AL]._type == CHARACTER && people.isHolmesActive()) {
// If Holmes is too far to the right, move him back so he's on-screen
int xRight = SHERLOCK_SCREEN_WIDTH - 2 - people[AL]._imageFrame->_frame.w;
int tempX = MIN(people[AL]._position.x / 100, xRight);
bool flipped = people[AL]._frameNumber == WALK_LEFT || people[AL]._frameNumber == STOP_LEFT ||
people[AL]._frameNumber == WALK_UPLEFT || people[AL]._frameNumber == STOP_UPLEFT ||
people[AL]._frameNumber == WALK_DOWNRIGHT || people[AL]._frameNumber == STOP_DOWNRIGHT;
screen._backBuffer.transBlitFrom(people[AL]._imageFrame->_frame,
Common::Point(tempX, people[AL]._position.y / 100 - people[AL]._imageFrame->_frame.h), flipped);
}
// Draw all static and active shapes are NORMAL and are in front of the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD)
screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
}
// Draw all static and active canimations that are NORMAL and are in front of the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = _canimShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_BEHIND) {
screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
}
}
// Draw all static and active shapes that are in front of the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD)
screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
}
// Draw any active portrait
if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
screen._backBuffer.transBlitFrom(people._portrait._imageFrame->_frame,
people._portrait._position, people._portrait._flags & 2);
// Draw all static and active canimations that are in front of the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = _canimShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) {
screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
}
}
// Draw all NO_SHAPE shapes which have flag bit 0 clear
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == NO_SHAPE && (o._flags & 1) == 0)
screen._backBuffer.transBlitFrom(o._imageFrame->_frame, o._position, o._flags & 2);
}
// Bring the newly built picture to the screen
if (_animating == 2) {
_animating = 0;
screen.slamRect(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
} else {
if (people[AL]._type != INVALID && ((_goToRoom == -1 || _ongoingCans == 0))) {
if (people[AL]._type == REMOVE) {
screen.slamRect(Common::Rect(
people[AL]._oldPosition.x, people[AL]._oldPosition.y,
people[AL]._oldPosition.x + people[AL]._oldSize.x,
people[AL]._oldPosition.y + people[AL]._oldSize.y
));
} else {
screen.flushImage(people[AL]._imageFrame,
Common::Point(people[AL]._position.x / 100, people[AL]._position.y / 100),
&people[AL]._oldPosition.x, &people[AL]._oldPosition.y,
&people[AL]._oldSize.x, &people[AL]._oldSize.y);
}
}
if (_currentScene == 12 && _vm->getGameID() == GType_SerratedScalpel)
((Scalpel::ScalpelEngine *)_vm)->flushMirror12();
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == REMOVE) && _goToRoom == -1) {
screen.flushImage(o._imageFrame, o._position,
&o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y);
}
}
if (people._portraitLoaded) {
if (people._portrait._type == REMOVE)
screen.slamRect(Common::Rect(
people._portrait._position.x, people._portrait._position.y,
people._portrait._position.x + people._portrait._delta.x,
people._portrait._position.y + people._portrait._delta.y
));
else
screen.flushImage(people._portrait._imageFrame, people._portrait._position,
&people._portrait._oldPosition.x, &people._portrait._oldPosition.y,
&people._portrait._oldSize.x, &people._portrait._oldSize.y);
if (people._portrait._type == REMOVE)
people._portrait._type = INVALID;
}
if (_goToRoom == -1) {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == NO_SHAPE && (o._flags & 1) == 0) {
screen.slamArea(o._position.x, o._position.y, o._oldSize.x, o._oldSize.y);
screen.slamArea(o._oldPosition.x, o._oldPosition.y, o._oldSize.x, o._oldSize.y);
} else if (o._type == HIDE_SHAPE) {
screen.flushImage(o._imageFrame, o._position,
&o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y);
}
}
}
for (int idx = _canimShapes.size() - 1; idx >= 0; --idx) {
Object &o = _canimShapes[idx];
if (o._type == REMOVE) {
if (_goToRoom == -1)
screen.slamArea(o._position.x, o._position.y, o._delta.x, o._delta.y);
_canimShapes.remove_at(idx);
} else if (o._type == ACTIVE_BG_SHAPE) {
screen.flushImage(o._imageFrame, o._position,
&o._oldPosition.x, &o._oldPosition.y, &o._oldSize.x, &o._oldSize.y);
}
}
}
_restoreFlag = true;
events.wait(1);
_doBgAnimDone = true;
// Check if the method was called for calling a portrait, and a talk was
// interrupting it. This talk file would not have been executed at the time,
// since we needed to finish the 'doBgAnim' to finish clearing the portrait
if (people._clearingThePortrait && _vm->_scriptMoreFlag == 3) {
// Reset the flags and call to talk
people._clearingThePortrait = _vm->_scriptMoreFlag = 0;
talk.talkTo(_vm->_scriptName);
}
}
void Scene::clearInfo() {
// TODO
}
} // End of namespace Sherlock

View File

@ -116,6 +116,10 @@ private:
Common::String _cAnimStr;
MenuMode _menuMode;
InvMode _invMode;
bool _lookScriptFlag;
int _selector;
bool _invLookFlag;
bool _lookHelp;
bool loadScene(const Common::String &filename);
@ -125,15 +129,9 @@ private:
void transitionToScene();
int toggleObject(const Common::String &name);
void updateBackground();
void checkBgShapes(ImageFrame *frame, const Common::Point &pt);
int startCAnim(int cAnimNum, int playRate);
void doBgAnim();
public:
int _currentScene;
int _goToRoom;
@ -170,6 +168,8 @@ public:
int _hsavedFs;
Common::Array<Object> _canimShapes;
bool _restoreFlag;
int _animating;
bool _doBgAnimDone;
public:
Scene(SherlockEngine *vm);
~Scene();
@ -183,6 +183,14 @@ public:
Exit *checkForExit(const Common::Rect &r);
void printObjDesc(const Common::String &str, bool firstTime);
int startCAnim(int cAnimNum, int playRate);
int toggleObject(const Common::String &name);
void doBgAnim();
void clearInfo();
};
} // End of namespace Sherlock

View File

@ -231,4 +231,67 @@ void Screen::verticalTransition() {
}
}
/**
* Prints the text passed onto the back buffer at the given position and color.
* The string is then blitted to the screen
*/
void Screen::print(const Common::Point &pt, int fgColor, int bgColor, const char *format, ...) {
// TODO
}
/**
* Copies a section of the second back buffer into the main back buffer
*/
void Screen::restoreBackground(const Common::Rect &r) {
Common::Rect tempRect = r;
tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
if (tempRect.isValidRect())
_backBuffer.blitFrom(_backBuffer2, Common::Point(tempRect.left, tempRect.top), tempRect);
}
/**
* Copies a given area to the screen
*/
void Screen::slamArea(int16 xp, int16 yp, int16 w, int16 h) {
slamRect(Common::Rect(xp, yp, xp + w, yp + h));
}
/**
* Copies a given area to the screen
*/
void Screen::slamRect(const Common::Rect &r) {
Common::Rect tempRect = r;
tempRect.clip(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
if (tempRect.isValidRect())
blitFrom(_backBuffer, Common::Point(tempRect.left, tempRect.top), tempRect);
}
/**
* Copy an image from the back buffer to the screen, taking care of both the
* new area covered by the shape as well as the old area, which must be restored
*/
void Screen::flushImage(ImageFrame *frame, const Common::Point &pt,
int16 *xp, int16 *yp, int16 *w, int16 *h) {
Common::Point imgPos = pt + frame->_offset;
Common::Rect newBounds(imgPos.x, imgPos.y, imgPos.x + frame->_frame.w, imgPos.y + frame->_frame.h);
Common::Rect oldBounds(*xp, *yp, *xp + *w, *yp + *h);
// See if the areas of the old and new overlap, and if so combine the areas
if (newBounds.intersects(oldBounds)) {
newBounds.extend(oldBounds);
slamRect(newBounds);
} else {
// The two areas are independent, so copy them both
slamRect(newBounds);
slamRect(oldBounds);
}
*xp = newBounds.left;
*yp = newBounds.top;
*w = newBounds.width();
*h = newBounds.height();
}
} // End of namespace Sherlock

View File

@ -26,8 +26,8 @@
#include "common/list.h"
#include "common/rect.h"
#include "graphics/surface.h"
#include "sherlock/graphics.h"
#include "sherlock/resources.h"
namespace Sherlock {
@ -75,6 +75,16 @@ public:
void randomTransition();
void verticalTransition();
void print(const Common::Point &pt, int fgColor, int bgColor, const char *format, ...);
void restoreBackground(const Common::Rect &r);
void slamArea(int16 xp, int16 yp, int16 w, int16 h);
void slamRect(const Common::Rect &r);
void flushImage(ImageFrame *frame, const Common::Point &pt,
int16 *xp, int16 *yp, int16 *w, int16 *h);
};
} // End of namespace Sherlock

View File

@ -45,7 +45,8 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam
_justLoaded = false;
_onChessboard = false;
_slowChess = false;
_animating = false;
_menuCounter = 0;
_scriptMoreFlag = 0;
}
SherlockEngine::~SherlockEngine() {

View File

@ -98,7 +98,9 @@ public:
Common::Array<Common::Point> _map; // Map locations for each scene
bool _onChessboard;
bool _slowChess;
bool _animating;
int _menuCounter;
int _scriptMoreFlag;
Common::String _scriptName;
public:
SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc);
virtual ~SherlockEngine();