MYST3: Implement puzzle #14, and WIP for drawing J'nanin's projectors

The zoom and blur effects are missing
This commit is contained in:
Bastien Bouclet 2012-01-19 11:09:26 +01:00
parent 81b7cff635
commit d0de43cb1e
8 changed files with 148 additions and 31 deletions

View File

@ -24,6 +24,8 @@
#include "engines/myst3/myst3.h"
#include "engines/myst3/state.h"
#include "graphics/colormasks.h"
namespace Myst3 {
Movie::Movie(Myst3Engine *vm, uint16 id) :
@ -294,4 +296,57 @@ bool SimpleMovie::update() {
SimpleMovie::~SimpleMovie() {
}
ProjectorMovie::ProjectorMovie(Myst3Engine *vm, uint16 id, Graphics::Surface *background) :
ScriptedMovie(vm, id),
_background(background),
_frame(0) {
_enabled = true;
}
ProjectorMovie::~ProjectorMovie() {
if (_frame) {
_frame->free();
delete _frame;
}
if (_background) {
_background->free();
delete _background;
}
}
void ProjectorMovie::update() {
if (!_frame) {
// First call, get the alpha channel from the bink file
const Graphics::Surface *frame = _bink.decodeNextFrame();
_frame = new Graphics::Surface();
_frame->copyFrom(*frame);
}
uint16 _backgroundX = _vm->_state->getProjectorX() / 10 - _frame->w / 2;
uint16 _backgroundY = _vm->_state->getProjectorY() / 10 - _frame->h / 2;
for (uint i = 0; i < _frame->h; i++) {
uint32 *src = (uint32 *)_background->getBasePtr(_backgroundX, _backgroundY + i);
uint32 *dst = (uint32 *)_frame->getBasePtr(0, i);
for (uint j = 0; j < _frame->w; j++) {
uint8 a, r, g, b;
// Keep the alpha channel from the previous frame
Graphics::colorToARGB< Graphics::ColorMasks<8888> >(*dst, a, r, g, b);
// Get the colors from the background
Graphics::colorToRGB< Graphics::ColorMasks<8888> >(*src++, r, g, b);
// Draw the new frame
*dst++ = Graphics::ARGBToColor< Graphics::ColorMasks<8888> >(a, r, g, b);
}
}
if (_texture)
_texture->update(_frame);
else
_texture = _vm->_gfx->createTexture(_frame);
}
} /* namespace Myst3 */

View File

@ -79,7 +79,7 @@ public:
virtual ~ScriptedMovie();
void draw();
void update();
virtual void update();
void setEndFrameVar(uint16 v) { _endFrameVar = v; }
void setNextFrameReadVar(uint16 v) { _nextFrameReadVar = v; }
@ -97,7 +97,7 @@ public:
void setScriptDriven(bool b) { _scriptDriven = b; }
void setForce2d(bool b) { _force2d = b; }
private:
protected:
bool _enabled;
bool _loop;
bool _disableWhenComplete;
@ -130,5 +130,18 @@ private:
bool _synchronized;
};
// Used by the projectors on J'nanin, see puzzle #14
class ProjectorMovie : public ScriptedMovie {
public:
ProjectorMovie(Myst3Engine *vm, uint16 id, Graphics::Surface *background);
virtual ~ProjectorMovie();
void update();
private:
Graphics::Surface *_background;
Graphics::Surface *_frame;
};
} /* namespace Myst3 */
#endif /* MOVIE_H_ */

View File

@ -54,7 +54,7 @@ Myst3Engine::Myst3Engine(OSystem *syst, int gameFlags) :
_state(0), _node(0), _scene(0), _archiveNode(0),
_cursor(0), _inventory(0), _gfx(0), _menu(0),
_rnd(0), _shouldQuit(false),
_menuAction(0) {
_menuAction(0), _projectorBackground(0) {
DebugMan.addDebugChannel(kDebugVariable, "Variable", "Track Variable Accesses");
DebugMan.addDebugChannel(kDebugSaveLoad, "SaveLoad", "Track Save/Load Function");
DebugMan.addDebugChannel(kDebugScript, "Script", "Track Script Execution");
@ -498,7 +498,16 @@ void Myst3Engine::runScriptsFromNode(uint16 nodeID, uint32 roomID, uint32 ageID)
}
void Myst3Engine::loadMovie(uint16 id, uint16 condition, bool resetCond, bool loop) {
ScriptedMovie *movie = new ScriptedMovie(this, id);
ScriptedMovie *movie;
if (!_state->getMovieUseBackground()) {
movie = new ScriptedMovie(this, id);
} else {
movie = new ProjectorMovie(this, id, _projectorBackground);
_projectorBackground = 0;
_state->setMovieUseBackground(0);
}
movie->setCondition(condition);
movie->setDisableWhenComplete(resetCond);
movie->setLoop(loop);

View File

@ -77,6 +77,9 @@ public:
Common::RandomSource *_rnd;
// Used by the projectors on J'nanin, see puzzle #14
Graphics::Surface *_projectorBackground;
Myst3Engine(OSystem *syst, int gameFlags);
virtual ~Myst3Engine();

View File

@ -42,8 +42,11 @@ void Puzzles::run(uint16 id, uint16 arg0, uint16 arg1, uint16 arg3) {
case 9:
journalAtrus(arg0, arg1);
break;
case 14:
projectorLoadBitmap(arg0);
break;
case 16:
projector();
projectorUpdateCoordinates();
break;
case 20:
saveLoadMenu(arg0, arg1);
@ -206,7 +209,36 @@ void Puzzles::saveLoadMenu(uint16 action, uint16 item) {
}
}
void Puzzles::projector() {
static void copySurfaceRect(Graphics::Surface *dest, const Common::Point &destPoint, const Graphics::Surface *src) {
for (uint16 i = 0; i < src->h; i++)
memcpy(dest->getBasePtr(destPoint.x, i + destPoint.y), src->getBasePtr(0, i), src->pitch);
}
void Puzzles::projectorLoadBitmap(uint16 bitmap) {
assert(_vm->_projectorBackground == 0 && "Previous background not yet used.");
// This surface is freed by the destructor of the movie that uses it
_vm->_projectorBackground = new Graphics::Surface();
_vm->_projectorBackground->create(1024, 1024, Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24));
const DirectorySubEntry *movieDesc = _vm->getFileDescription(0, bitmap, 0, DirectorySubEntry::kStillMovie);
if (!movieDesc)
error("Movie %d does not exist", bitmap);
// Rebuild the complete background image from the frames of the bink movie
Common::MemoryReadStream *movieStream = movieDesc->getData();
Video::SeekableBinkDecoder bink;
bink.loadStream(movieStream, Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24));
for (uint i = 0; i < 1024; i += 256)
for (uint j = 0; j < 1024; j += 256) {
const Graphics::Surface *frame = bink.decodeNextFrame();
copySurfaceRect(_vm->_projectorBackground, Common::Point(j, i), frame);
}
}
void Puzzles::projectorUpdateCoordinates() {
int16 x = CLIP<int16>(_vm->_state->getProjectorX(), 840, 9400);
int16 y = CLIP<int16>(_vm->_state->getProjectorY(), 840, 9400);
int16 zoom = CLIP<int16>(_vm->_state->getProjectorZoom(), 1280, 5120);

View File

@ -1,23 +1,23 @@
/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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.
*
/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 PUZZLES_H_
@ -25,6 +25,8 @@
#include "common/scummsys.h"
#include "graphics/surface.h"
namespace Myst3 {
class Myst3Engine;
@ -45,10 +47,11 @@ private:
bool _journalSaavedroHasChapter(uint16 chapter);
uint16 _journalSaavedroNextChapter(uint16 chapter, bool forward);
void journalAtrus(uint16 node, uint16 var);
void mainMenu(uint16 action);
void saveLoadMenu(uint16 action, uint16 item);
void projector();
void journalAtrus(uint16 node, uint16 var);
void mainMenu(uint16 action);
void saveLoadMenu(uint16 action, uint16 item);
void projectorLoadBitmap(uint16 bitmap);
void projectorUpdateCoordinates();
};
} /* namespace Myst3 */

View File

@ -95,7 +95,7 @@ GameState::GameState(Myst3Engine *vm):
VAR(172, MovieUnk172, true)
VAR(173, MoviePlayingVar, true)
VAR(178, MovieUnk178, true)
VAR(178, MovieUseBackground, false)
VAR(189, LocationNextNode, false)
VAR(190, LocationNextRoom, false)

View File

@ -109,6 +109,8 @@ public:
DECLARE_VAR(168, MovieOverridePosV)
DECLARE_VAR(173, MoviePlayingVar)
DECLARE_VAR(178, MovieUseBackground)
DECLARE_VAR(189, LocationNextNode)
DECLARE_VAR(190, LocationNextRoom)
DECLARE_VAR(191, LocationNextAge)