mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-04 01:46:42 +00:00
SHERLOCK: Implemented doBgAnim
This commit is contained in:
parent
7f04ea4425
commit
ff02c29e9c
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
@ -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 {
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -51,6 +51,10 @@ protected:
|
||||
public:
|
||||
ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc);
|
||||
virtual ~ScalpelEngine();
|
||||
|
||||
void eraseMirror12();
|
||||
void doMirror12();
|
||||
void flushMirror12();
|
||||
};
|
||||
|
||||
} // End of namespace Scalpel
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user