In progress work implementing the animation player

svn-id: r49347
This commit is contained in:
Paul Gilbert 2010-05-31 12:10:30 +00:00
parent 3f4302214c
commit 088e6456ea
10 changed files with 536 additions and 192 deletions

View File

@ -31,177 +31,397 @@ namespace M4 {
// TODO: this code needs cleanup
Animation::Animation(MadsM4Engine *vm) {
_vm = vm;
MadsAnimation::MadsAnimation(MadsM4Engine *vm, MadsView *view): Animation(vm), _view(view) {
_playing = false;
_font = NULL;
_unk1 = 0;
_skipLoad = false;
_unkIndex = -1;
_messageCtr= 0;
}
void Animation::loadFullScreen(const char *filename) {
_vm->_palette->deleteAllRanges();
load(filename);
MadsAnimation::~MadsAnimation() {
delete _font;
}
void Animation::load(const char *filename) {
MadsPack anim(filename, _vm);
void MadsAnimation::load(const Common::String &filename) {
MadsPack anim(filename.c_str(), _vm);
bool madsRes = filename[0] == '*';
char buffer[20];
int streamIndex = 1;
// Chunk 1: header
// header
// TODO: there are some unknown fields here, plus we don't read
// the entire chunk
Common::SeekableReadStream *animStream = anim.getItemStream(0);
Common::SeekableReadStream *spriteSeriesStream;
//printf("Chunk 0, size %i\n", animStream->size());
_seriesCount = animStream->readUint16LE();
_frameCount = animStream->readUint16LE();
_frameEntryCount = animStream->readUint16LE();
// Unknown
for (int i = 0; i < 43; i++)
animStream->readByte();
int spriteListCount = animStream->readUint16LE();
int miscEntriesCount = animStream->readUint16LE();
int frameEntryCount = animStream->readUint16LE();
int messagesCount = animStream->readUint16LE();
animStream->skip(1);
_flags = animStream->readByte();
_spriteSeriesNames = new Common::String[_seriesCount];
printf("%i sprite series\n", _seriesCount);
animStream->skip(2);
_animMode = animStream->readUint16LE();
assert(_animMode != 4);
_roomNumber = animStream->readUint16LE();
_field12 = animStream->readUint16LE() != 0;
animStream->skip(4);
_spriteListIndex = animStream->readUint16LE();
_scrollX = animStream->readUint16LE();
_scrollY = animStream->readSint16LE();
animStream->skip(10);
animStream->read(buffer, 13);
_field24 = Common::String(buffer, 13);
// TODO: for now, we only load the first sprite series
if (_seriesCount > 1)
printf("TODO: Anim has %i sprite series, for now, we only load the first one\n", _seriesCount);
_seriesCount = 1; // TODO
for (int i = 0; i < _seriesCount; i++) {
for (int i = 0; i < 10; ++i) {
animStream->read(buffer, 13);
_spriteSeriesNames[i] = Common::String(buffer);
//printf("%03d: %s\n", i, _spriteSeriesNames[i].c_str());
_spriteSetNames[i] = Common::String(buffer, 13);
}
spriteSeriesStream = _vm->res()->get(_spriteSeriesNames[i].c_str());
_spriteSeries = new SpriteAsset(_vm, spriteSeriesStream,
spriteSeriesStream->size(), _spriteSeriesNames[i].c_str());
_vm->res()->toss(_spriteSeriesNames[i].c_str());
animStream->skip(81);
animStream->read(buffer, 13);
_lbmFilename = Common::String(buffer, 13);
animStream->read(buffer, 13);
_spritesFilename = Common::String(buffer, 13);
animStream->skip(48);
animStream->read(buffer, 13);
_soundName = Common::String(buffer, 13);
animStream->skip(26);
animStream->read(buffer, 13);
Common::String fontResource(buffer, 13);
// Adjust the palette of the sprites in the sprite series
// so that they can be displayed on screen correctly
RGBList *palData = new RGBList(_spriteSeries->getColorCount(), _spriteSeries->getPalette(), true);
_vm->_palette->addRange(palData);
// TODO: Based on a weird usage of a flags word, a secondary method gets called here.
// Figure out secondary method, and when/if it's called
for (int k = 0; k < _spriteSeries->getCount(); k++) {
M4Sprite *spr = _spriteSeries->getFrame(k);
spr->translate(palData); // sprite pixel translation
// Initialise the reference list
for (int i = 0; i < spriteListCount; ++i)
_spriteListIndexes.push_back(-1);
delete animStream;
if (messagesCount > 0) {
// Chunk 2
// Following is a list of any messages for the animation
Common::SeekableReadStream *animStream = anim.getItemStream(streamIndex++);
for (int i = 0; i < messagesCount; ++i) {
AnimMessage rec;
animStream->read(rec.msg, 70);
rec.pos.x = animStream->readUint16LE();
rec.pos.y = animStream->readUint16LE();
animStream->readUint16LE();
rec.rgb1.r = animStream->readByte();
rec.rgb1.g = animStream->readByte();
rec.rgb1.b = animStream->readByte();
rec.rgb2.r = animStream->readByte();
rec.rgb2.g = animStream->readByte();
rec.rgb2.b = animStream->readByte();
rec.kernelMsgIndex = animStream->readUint16LE();
animStream->skip(6);
rec.startFrame = animStream->readUint16LE();
rec.endFrame = animStream->readUint16LE();
animStream->readUint16LE();
_messages.push_back(rec);
}
delete animStream;
}
//printf("End pos: %i\n", animStream->pos());
if (frameEntryCount > 0) {
// Chunk 3: animation frame info
animStream = anim.getItemStream(streamIndex++);
delete animStream;
for (int i = 0; i < frameEntryCount; i++) {
AnimFrameEntry rec;
rec.frameNumber = animStream->readUint16LE();
rec.seqIndex = animStream->readByte();
rec.spriteSlot.frameNumber = animStream->readUint16LE();
rec.spriteSlot.xp = animStream->readUint16LE();
rec.spriteSlot.yp = animStream->readUint16LE();
rec.spriteSlot.depth = animStream->readUint16LE();
rec.spriteSlot.scale = animStream->readUint16LE();
// ------------------
_frameEntries.push_back(rec);
}
// Chunk 2: anim info
AnimationFrame frame;
animStream = anim.getItemStream(1);
//printf("Chunk 1, size %i\n", animStream->size());
_frameEntries = new AnimationFrame[_frameEntryCount];
for (int i = 0; i < _frameEntryCount; i++) {
frame.animFrameIndex = animStream->readUint16LE();
frame.u = animStream->readByte();
frame.seriesIndex = animStream->readByte();
frame.seriesFrameIndex = animStream->readUint16LE();
frame.x = animStream->readUint16LE();
frame.y = animStream->readUint16LE();
frame.v = animStream->readByte();
frame.w = animStream->readByte();
_frameEntries[i] = frame;
/*
printf(
"animFrameIndex = %4d, "
"u = %3d, "
"seriesIndex = %3d, "
"seriesFrameIndex = %6d, "
"x = %3d, "
"y = %3d, "
"v = %3d, "
"w = %3d\n",
frame.animFrameIndex,
frame.u,
frame.seriesIndex,
frame.seriesFrameIndex,
frame.x,
frame.y,
frame.v,
frame.w
);
*/
delete animStream;
}
//printf("End pos: %i\n", animStream->pos());
delete animStream;
if (miscEntriesCount > 0) {
// Chunk 4: Misc Data
animStream = anim.getItemStream(streamIndex);
// Chunk 3: unknown (seems to be sound data?)
// TODO
for (int i = 0; i < miscEntriesCount; ++i) {
AnimMiscEntry rec;
rec.soundNum = animStream->readUint16LE();
rec.numTicks = animStream->readUint16LE();
rec.posAdjust.x = animStream->readUint16LE();
rec.posAdjust.y = animStream->readUint16LE();
animStream->readUint16LE();
_miscEntries.push_back(rec);
}
delete animStream;
}
// If the animation specifies a font, then load it for access
if (_flags & ANIM_CUSTOM_FONT) {
Common::String fontName;
if (madsRes)
fontName += "*";
fontName += fontResource;
_font = _vm->_font->getFont(fontName);
}
// Load all the sprite sets for the animation
for (int i = 0; i < spriteListCount; ++i) {
_spriteListIndexes[i] = _view->_spriteSlots.addSprites(_spriteSetNames[i].c_str());
}
if (_field12) {
Common::String resName;
if (madsRes)
resName += "*";
resName += _spriteSetNames[_spriteListIndex];
_spriteListIndexes[_spriteListIndex] = _view->_spriteSlots.addSprites(resName.c_str());
}
// TODO: Unknown section about handling palette entries - I think it's adjusting sprite sets
// to the palette of the game screen
// Process the sprite list indexes to remap them to the actual sprite list indexes
}
Animation::~Animation() {
//delete[] _spriteSeriesNames;
//delete[] _spriteSeries;
//delete[] _frameEntries;
}
void Animation::start() {
_curFrame = 0;
_curFrameEntry = 0;
void MadsAnimation::start() {
_currentFrame = 0;
_oldFrameEntry = 0;
//for (int i = 0; i < _seriesCount; i++) {
//_spriteSeries[i] = new SpriteSeries((char*)_spriteSeriesNames[i].c_str());
//}
_playing = true;
updateAnim();
update();
}
bool Animation::updateAnim() {
bool MadsAnimation::update() {
if (!_playing)
return true;
// Get the scene background surface
M4Surface *bg = _vm->_scene->getBackgroundSurface();
if (_field12) {
int spriteListIndex = _spriteListIndexes[_spriteListIndex];
int newIndex = -1;
for (uint idx = _oldFrameEntry; idx < _frameEntries.size(); ++idx) {
if (_frameEntries[idx].frameNumber > _currentFrame)
break;
if (_frameEntries[idx].spriteSlot.spriteListIndex == spriteListIndex)
newIndex = _frameEntries[idx].spriteSlot.frameNumber;
}
while (_frameEntries[_curFrameEntry].animFrameIndex == _curFrame) {
AnimationFrame *frame = &_frameEntries[_curFrameEntry];
int seriesFrameIndex = (frame->seriesFrameIndex & 0x7FFF) - 1;
// Write the sprite onto the screen
M4Sprite *spr = _spriteSeries->getFrame(seriesFrameIndex);
// FIXME: correct x, y
spr->copyTo(bg, frame->x, frame->y, (int)spr->getTransparentColor());
// HACK: wait a bit
g_system->delayMillis(100);
//printf("_curFrameEntry = %d\n", _curFrameEntry);
_curFrameEntry++;
if (newIndex >= 0)
load1(newIndex);
}
//printf("_curFrame = %d\n", _curFrame);
// If it's not time for the next frame, then exit
if (_madsVm->_currentTimer < _nextFrameTimer)
return false;
_curFrame++;
if (_curFrame >= _frameCount) // anim done
// Loop checks for any prior animation sprite slots to be expired
for (int slotIndex = 0; slotIndex < _view->_spriteSlots.startIndex; ++slotIndex) {
if ((_view->_spriteSlots[slotIndex].seqIndex >= 0x80) &&
(_view->_spriteSlots[slotIndex].seqIndex <= 0xFD)) {
// Flag the frame as animation sprite slot
_view->_spriteSlots[slotIndex].spriteType = EXPIRED_SPRITE;
}
}
// Validate the current frame
if (_currentFrame > (int)_miscEntries.size()) {
// Is the animation allowed to be repeated?
if (_resetFlag) {
_currentFrame = 0;
_oldFrameEntry = 0;
} else {
_unk1 = true;
return true;
}
}
// Handle starting any sound for this frame
AnimMiscEntry &misc = _miscEntries[_currentFrame];
if (misc.soundNum)
_vm->_sound->playSound(misc.soundNum);
bool screenChanged = false;
// Handle any scrolling of the screen surface
if ((_scrollX != 0) || (_scrollY != 0)) {
_view->_bgSurface->scrollX(_scrollX);
_view->_bgSurface->scrollY(_scrollY);
screenChanged = true;
}
// Handle any offset adjustment for sprites as of this frame
if (_view->_posAdjust.x != misc.posAdjust.x) {
misc.posAdjust.x = _view->_posAdjust.x;
screenChanged = true;
}
if (_view->_posAdjust.y != misc.posAdjust.y) {
misc.posAdjust.y = _view->_posAdjust.y;
screenChanged = true;
}
if (screenChanged) {
// Signal the entire screen needs refreshing
_view->_spriteSlots.fullRefresh();
}
int spriteSlotsMax = _view->_spriteSlots.startIndex;
// Main frame animation loop - frames get animated by being placed, as necessary, into the
// main sprite slot array
while ((uint)_oldFrameEntry < _frameEntries.size()) {
if (_frameEntries[_oldFrameEntry].frameNumber > _currentFrame)
break;
else if (_frameEntries[_oldFrameEntry].frameNumber == _currentFrame) {
// Found the correct frame
int spriteSlotIndex = 0;
int index = 0;
for (;;) {
if ((spriteSlotIndex == 0) && (index < spriteSlotsMax)) {
int seqIndex = _frameEntries[_oldFrameEntry].seqIndex - _view->_spriteSlots[index].seqIndex;
if (seqIndex == 0x80) {
if (_view->_spriteSlots[index] == _frameEntries[_oldFrameEntry].spriteSlot)
_view->_spriteSlots[index].spriteType = SPRITE_ZERO;
}
++index;
continue;
}
if (spriteSlotIndex == 0) {
int slotIndex = _view->_spriteSlots.getIndex();
_view->_spriteSlots[slotIndex].copy(_frameEntries[_oldFrameEntry].spriteSlot);
_view->_spriteSlots[slotIndex].seqIndex += 0x80;
SpriteAsset &spriteSet = _view->_spriteSlots.getSprite(
_view->_spriteSlots[slotIndex].spriteListIndex);
_view->_spriteSlots[slotIndex].spriteType = (spriteSet.getAssetType() == 0) ?
SPRITE_FOUR : SPRITE_ZERO;
}
break;
}
}
++_oldFrameEntry;
}
// Handle the display of any messages
for (uint idx = 0; idx < _messages.size(); ++idx) {
if (_messages[idx].kernelMsgIndex >= 0) {
// Handle currently active message
if ((_currentFrame < _messages[idx].startFrame) || (_currentFrame > _messages[idx].endFrame)) {
_view->_kernelMessages.remove(_messages[idx].kernelMsgIndex);
_messages[idx].kernelMsgIndex = -1;
--_messageCtr;
}
} else if ((_currentFrame >= _messages[idx].startFrame) && (_currentFrame <= _messages[idx].endFrame)) {
// Start displaying the message
AnimMessage &me = _messages[idx];
// The colour index to use is dependant on how many messages are currently on-screen
uint8 colIndex;
switch (_messageCtr) {
case 1:
colIndex = 252;
break;
case 2:
colIndex = 16;
break;
default:
colIndex = 250;
break;
}
_vm->_palette->setEntry(colIndex, me.rgb1.r, me.rgb1.g, me.rgb1.b);
_vm->_palette->setEntry(colIndex + 1, me.rgb2.r, me.rgb2.g, me.rgb2.b);
// Add a kernel message to display the given text
me.kernelMsgIndex = _view->_kernelMessages.add(me.pos, colIndex * 101, 0, 0, INDEFINITE_TIMEOUT, me.msg);
++_messageCtr;
}
}
// Move to the next frame
_currentFrame++;
if (_currentFrame >= (int)_miscEntries.size()) {
// Animation is complete
stop();
return _curFrame >= _frameCount;
if (_abortTimers != 0) {
_view->_abortTimers = _abortTimers;
_view->_abortTimersMode = _abortMode;
if (_abortMode != ABORTMODE_1) {
// Copy the noun list
for (int i = 0; i < 3; ++i)
_madsVm->scene()->actionNouns[i] = _actionNouns[i];
}
}
}
int frameNum = MIN(_currentFrame, (int)_miscEntries.size() - 1);
_nextFrameTimer = _madsVm->_currentTimer + _miscEntries[frameNum].numTicks;
return _currentFrame >= (int)_miscEntries.size();
}
void Animation::stop() {
void MadsAnimation::stop() {
_playing = false;
}
for (int i = 0; i < _seriesCount; i++) {
// TODO: cleanup
//delete _spriteSeries[i];
//_spriteSeries[i] = NULL;
void MadsAnimation::setCurrentFrame(int frameNumber) {
_currentFrame = frameNumber;
_oldFrameEntry = 0;
_unk1 = 0;
}
void MadsAnimation::load1(int frameNumber) {
if (_skipLoad)
return;
Common::Point pt;
int listIndex = _spriteListIndexes[_spriteListIndex];
SpriteAsset &spriteSet = _view->_spriteSlots.getSprite(listIndex);
if (_unkIndex < 0) {
M4Surface *frame = spriteSet.getFrame(0);
pt.x = frame->bounds().left;
pt.y = frame->bounds().top;
} else {
pt.x = _unkList[_unkIndex].x;
pt.y = _unkList[_unkIndex].y;
_unkIndex = 1 - _unkIndex;
}
if (proc1(spriteSet, pt, frameNumber))
error("proc1 failure");
}
bool MadsAnimation::proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber) {
return 0;
}
} // End of namespace M4

View File

@ -29,39 +29,90 @@
#include "m4/m4.h"
#include "m4/graphics.h"
#include "m4/assets.h"
#include "m4/mads_views.h"
#include "common/array.h"
namespace M4 {
struct AnimationFrame {
uint16 animFrameIndex;
byte u;
byte seriesIndex;
uint16 seriesFrameIndex;
uint16 x, y;
byte v, w;
class MadsView;
class SpriteSlotSubset;
class AnimMessage {
public:
char msg[70];
Common::Point pos;
RGB8 rgb1, rgb2;
int kernelMsgIndex;
int startFrame, endFrame;
};
class Animation {
public:
Animation(MadsM4Engine *vm);
~Animation();
class AnimFrameEntry {
public:
int frameNumber;
int seqIndex;
SpriteSlotSubset spriteSlot;
};
void load(const char *filename);
void loadFullScreen(const char *filename);
void start();
bool updateAnim();
void stop();
class AnimMiscEntry {
public:
int soundNum;
int numTicks;
Common::Point posAdjust;
};
private:
bool _playing;
MadsM4Engine *_vm;
int _seriesCount;
int _frameCount;
int _frameEntryCount;
AnimationFrame *_frameEntries;
Common::String *_spriteSeriesNames;
SpriteAsset *_spriteSeries;
int _curFrame, _curFrameEntry;
#define ANIM_SPRITE_SET_SIZE 50
enum MadsAnimationFlags {ANIM_CUSTOM_FONT = 0x20};
class MadsAnimation: public Animation {
private:
bool _playing;
MadsView *_view;
int _spriteListCount;
Common::Array<AnimMessage> _messages;
Common::Array<AnimFrameEntry> _frameEntries;
Common::Array<AnimMiscEntry> _miscEntries;
Font *_font;
uint8 _flags;
int _animMode;
int _roomNumber;
bool _field12;
int _spriteListIndex;
int _scrollX;
int _scrollY;
Common::String _field24;
Common::String _spriteSetNames[10];
Common::String _lbmFilename;
Common::String _spritesFilename;
Common::String _soundName;
Common::Array<int> _spriteListIndexes;
int _currentFrame, _oldFrameEntry;
bool _resetFlag;
int _unk1;
bool _skipLoad;
int _unkIndex;
Common::Point _unkList[2];
uint32 _nextFrameTimer;
int _messageCtr;
int _abortTimers;
AbortTimerMode _abortMode;
uint16 _actionNouns[3];
void load1(int frameNumber);
bool MadsAnimation::proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber);
public:
MadsAnimation(MadsM4Engine *vm, MadsView *view);
~MadsAnimation();
virtual void load(const Common::String &filename);
virtual void start();
virtual bool update();
virtual void stop();
virtual void setCurrentFrame(int frameNumber);
};
} // End of namespace M4

View File

@ -30,13 +30,13 @@
namespace M4 {
BaseAsset::BaseAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : _vm(vm) {
BaseAsset::BaseAsset(MadsM4Engine *vm) : _vm(vm) {
}
BaseAsset::~BaseAsset() {
}
MachineAsset::MachineAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
MachineAsset::MachineAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {
uint32 stateCount = stream->readUint32LE();
for (uint32 curState = 0; curState < stateCount; curState++) {
uint32 stateOffset = stream->readUint32LE();
@ -61,7 +61,7 @@ uint32 MachineAsset::getStateOffset(uint32 state) {
return _stateTable[state];
}
SequenceAsset::SequenceAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
SequenceAsset::SequenceAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {
_localVarCount = stream->readUint32LE();
_codeSize = size - 4;
_code = new byte[_codeSize];
@ -78,7 +78,7 @@ void SequenceAsset::getCode(byte *&code, uint32 &codeSize) {
}
DataAsset::DataAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
DataAsset::DataAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {
_recCount = stream->readUint32LE();
_recSize = stream->readUint32LE();
@ -98,7 +98,8 @@ long *DataAsset::getRow(int index) {
return &_data[_recSize * index];
}
SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream) : BaseAsset(vm, stream, size, name) {
SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream) :
BaseAsset(vm) {
_stream = stream;
_palInterface = NULL;
_paletteData = NULL;
@ -110,6 +111,20 @@ SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, i
}
}
SpriteAsset::SpriteAsset(MadsM4Engine *vm, const char *name): BaseAsset(vm) {
_stream = vm->res()->get(name);
_palInterface = NULL;
_paletteData = NULL;
if (_vm->isM4()) {
loadM4SpriteAsset(vm, _stream, true);
} else {
loadMadsSpriteAsset(vm, _stream);
}
vm->res()->toss(name);
}
SpriteAsset::~SpriteAsset() {
if (_palInterface) {
// Internally stored palette translation data, so release it

View File

@ -49,7 +49,7 @@ class Palette;
class BaseAsset {
public:
BaseAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name);
BaseAsset(MadsM4Engine *vm);
~BaseAsset();
const Common::String getName() const { return _name; }
protected:
@ -103,6 +103,7 @@ struct SpriteAssetFrame {
class SpriteAsset : public BaseAsset {
public:
SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream = false);
SpriteAsset(MadsM4Engine *vm, const char *name);
~SpriteAsset();
void loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, bool asStream);
void loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream);

View File

@ -47,7 +47,6 @@ Console::Console(MadsM4Engine *vm) : GUI::Debugger() {
DCmd_Register("start_conv", WRAP_METHOD(Console, cmdStartConversation));
DCmd_Register("textview", WRAP_METHOD(Console, cmdShowTextview));
DCmd_Register("animview", WRAP_METHOD(Console, cmdShowAnimview));
DCmd_Register("anim", WRAP_METHOD(Console, cmdPlayAnimation));
}
Console::~Console() {
@ -247,33 +246,6 @@ bool Console::cmdShowAnimview(int argc, const char **argv) {
return false;
}
bool Console::cmdPlayAnimation(int argc, const char **argv) {
View *view = _vm->_viewManager->getView(VIEWID_SCENE);
if (view == NULL) {
DebugPrintf("The scene view isn't currently active\n");
} else if (argc != 2 && argc != 3) {
DebugPrintf("Usage: %s <anim resource (*.aa)> <fullscreen>\n", argv[0]);
DebugPrintf("If fullscreen is 1, the screen palette is replaced with the palette of the animation\n");
} else {
char resourceName[20];
strncpy(resourceName, argv[1], 15);
resourceName[15] = '\0';
if (!strchr(resourceName, '.'))
strcat(resourceName, ".AA");
_vm->_viewManager->moveToFront(view);
if (argc == 3 && atoi(argv[2]) == 1)
_vm->_animation->loadFullScreen(resourceName);
else
_vm->_animation->load(resourceName);
_vm->_animation->start();
view->restore(0, 0, view->width(), view->height());
return false;
}
return true;
}
/*--------------------------------------------------------------------------*/
MadsConsole::MadsConsole(MadsEngine *vm): Console(vm) {
@ -282,6 +254,7 @@ MadsConsole::MadsConsole(MadsEngine *vm): Console(vm) {
DCmd_Register("object", WRAP_METHOD(MadsConsole, cmdObject));
DCmd_Register("message", WRAP_METHOD(MadsConsole, cmdMessage));
DCmd_Register("scene_info", WRAP_METHOD(MadsConsole, cmdSceneInfo));
DCmd_Register("anim", WRAP_METHOD(MadsConsole, cmdPlayAnimation));
}
bool MadsConsole::cmdObject(int argc, const char **argv) {
@ -386,6 +359,34 @@ bool MadsConsole::cmdSceneInfo(int argc, const char **argv) {
return true;
}
bool MadsConsole::cmdPlayAnimation(int argc, const char **argv) {
View *view = _vm->_viewManager->getView(VIEWID_SCENE);
if (view == NULL) {
DebugPrintf("The scene view isn't currently active\n");
} else if (argc != 2 && argc != 3) {
DebugPrintf("Usage: %s <anim resource (*.aa)> <fullscreen>\n", argv[0]);
DebugPrintf("If fullscreen is 1, the screen palette is replaced with the palette of the animation\n");
} else {
char resourceName[20];
strncpy(resourceName, argv[1], 15);
resourceName[15] = '\0';
if (!strchr(resourceName, '.'))
strcat(resourceName, ".AA");
_vm->_viewManager->moveToFront(view);
if (argc == 3 && atoi(argv[2]) == 1)
_madsVm->scene()->_sceneAnimation.loadFullScreen(resourceName);
else
_madsVm->scene()->_sceneAnimation.load(resourceName);
_madsVm->scene()->_sceneAnimation.start();
view->restore(0, 0, view->width(), view->height());
return false;
}
return true;
}
/*--------------------------------------------------------------------------*/
M4Console::M4Console(M4Engine *vm): Console(vm) {

View File

@ -50,7 +50,6 @@ private:
bool cmdStartConversation(int argc, const char **argv);
bool cmdShowTextview(int argc, const char **argv);
bool cmdShowAnimview(int argc, const char **argv);
bool cmdPlayAnimation(int argc, const char **argv);
public:
Console(MadsM4Engine *vm);
@ -64,6 +63,8 @@ private:
bool cmdObject(int argc, const char **argv);
bool cmdMessage(int argc, const char **argv);
bool cmdSceneInfo(int argc, const char **argv);
bool cmdPlayAnimation(int argc, const char **argv);
public:
MadsConsole(MadsEngine *vm);
virtual ~MadsConsole() {}

View File

@ -145,7 +145,6 @@ MadsM4Engine::~MadsM4Engine() {
delete _script;
delete _ws;
delete _random;
delete _animation;
delete _palette;
}
@ -184,7 +183,6 @@ Common::Error MadsM4Engine::run() {
_sound = new Sound(this, _mixer, 255);
_script = new ScriptInterpreter(this);
_ws = new WoodScript(this);
_animation = new Animation(this);
//_callbacks = new Callbacks(this);
_random = new Common::RandomSource();
g_eventRec.registerRandomSource(*_random, "m4");
@ -581,8 +579,6 @@ Common::Error MadsEngine::run() {
while (!_events->quitFlag) {
eventHandler();
_animation->updateAnim();
if (g_system->getMillis() >= nextFrame) {
nextFrame = g_system->getMillis() + GAME_FRAME_DELAY;
++_currentTimer;

View File

@ -200,7 +200,6 @@ public:
Rails *_rails;
ScriptInterpreter *_script;
WoodScript *_ws;
Animation *_animation;
Common::RandomSource *_random;
Scene *scene() { return _scene; }

View File

@ -24,6 +24,7 @@
*/
#include "m4/m4_views.h"
#include "m4/animation.h"
#include "m4/dialogs.h"
#include "m4/events.h"
#include "m4/font.h"
@ -43,6 +44,22 @@ static const int SCROLLER_DELAY = 200;
//--------------------------------------------------------------------------
bool MadsSpriteSlot::operator==(const SpriteSlotSubset &other) const {
return (spriteListIndex == other.spriteListIndex) && (frameNumber == other.frameNumber) &&
(xp == other.xp) && (yp == other.yp) && (depth == other.depth) && (scale == other.scale);
}
void MadsSpriteSlot::copy(const SpriteSlotSubset &other) {
spriteListIndex = other.spriteListIndex;
frameNumber = other.frameNumber;
xp = other.xp;
yp = other.yp;
depth = other.depth;
scale = other.scale;
}
//--------------------------------------------------------------------------
MadsSpriteSlots::MadsSpriteSlots(MadsView &owner): _owner(owner) {
for (int i = 0; i < SPRITE_SLOTS_SIZE; ++i) {
MadsSpriteSlot rec;
@ -74,6 +91,7 @@ int MadsSpriteSlots::addSprites(const char *resName) {
Common::SeekableReadStream *data = _vm->res()->get(resName);
SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName);
spriteSet->translate(_madsVm->_palette);
assert(spriteSet != NULL);
_sprites.push_back(SpriteList::value_type(spriteSet));
_vm->res()->toss(resName);
@ -1125,8 +1143,20 @@ void MadsSequenceList::setAnimRange(int seqIndex, int startVal, int endVal) {
//--------------------------------------------------------------------------
Animation::Animation(MadsM4Engine *vm): _vm(vm) {
}
void Animation::loadFullScreen(const Common::String &filename) {
_vm->_palette->deleteAllRanges();
load(filename);
}
//--------------------------------------------------------------------------
MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceList(*this),
_kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this) {
_kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this),
// FIXME: There's probably a cleaner way to do this, and I don't think the destructor is ever called
_sceneAnimation(*new MadsAnimation(_vm, this)) {
_textSpacing = -1;
_ticksAmount = 3;
_newTimeout = 0;

View File

@ -43,6 +43,16 @@ class MadsView;
enum AbortTimerMode {ABORTMODE_0 = 0, ABORTMODE_1 = 1, ABORTMODE_2 = 2};
class SpriteSlotSubset {
public:
int spriteListIndex;
int frameNumber;
int xp;
int yp;
int depth;
int scale;
};
class MadsSpriteSlot {
public:
int spriteType;
@ -55,12 +65,16 @@ public:
int scale;
MadsSpriteSlot() { }
bool operator==(const SpriteSlotSubset &other) const;
void copy(const SpriteSlotSubset &other);
};
#define SPRITE_SLOTS_SIZE 50
enum SpriteIdSpecial {
BACKGROUND_SPRITE = -4, FULL_SCREEN_REFRESH = -2, FOREGROUND_SPRITE = 1, EXPIRED_SPRITE = -1
BACKGROUND_SPRITE = -4, FULL_SCREEN_REFRESH = -2, EXPIRED_SPRITE = -1, SPRITE_ZERO = 0, FOREGROUND_SPRITE = 1,
SPRITE_FOUR = 4
};
typedef Common::Array<Common::SharedPtr<SpriteAsset> > SpriteList;
@ -138,7 +152,7 @@ public:
};
#define TIMED_TEXT_SIZE 10
#define TEXT_4A_SIZE 30
#define INDEFINITE_TIMEOUT 9999999
enum KernelMessageFlags {KMSG_QUOTED = 1, KMSG_OWNER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, KMSG_RIGHT_ALIGN = 0x10,
KMSG_CENTER_ALIGN = 0x20, KMSG_EXPIRE = 0x40, KMSG_ACTIVE = 0x80};
@ -352,10 +366,26 @@ public:
void setAnimRange(int seqIndex, int startVal, int endVal);
};
class Animation {
protected:
MadsM4Engine *_vm;
public:
Animation(MadsM4Engine *vm);
void loadFullScreen(const Common::String &filename);
virtual void load(const Common::String &filename) = 0;
virtual void start() = 0;
virtual bool update() = 0;
virtual void stop() = 0;
virtual void setCurrentFrame(int frameNumber) = 0;
};
class MadsView {
private:
View *_view;
public:
Animation &_sceneAnimation;
MadsSpriteSlots _spriteSlots;
MadsTextDisplay _textDisplay;
MadsKernelMessageList _kernelMessages;