aboutsummaryrefslogtreecommitdiff
path: root/engines/m4
diff options
context:
space:
mode:
authorPaul Gilbert2010-07-06 11:33:09 +0000
committerPaul Gilbert2010-07-06 11:33:09 +0000
commitc89fe5f6d56b6d6e11b7d642e85633bc86098ce8 (patch)
tree47c8ae8910e1bbbf654f60e68caa93ed750d3bdc /engines/m4
parent3f7dc9e0e2e4d043b2234b7b66981e16eb8a84b1 (diff)
downloadscummvm-rg350-c89fe5f6d56b6d6e11b7d642e85633bc86098ce8.tar.gz
scummvm-rg350-c89fe5f6d56b6d6e11b7d642e85633bc86098ce8.tar.bz2
scummvm-rg350-c89fe5f6d56b6d6e11b7d642e85633bc86098ce8.zip
Added support for idle character animations
svn-id: r50723
Diffstat (limited to 'engines/m4')
-rw-r--r--engines/m4/assets.cpp4
-rw-r--r--engines/m4/assets.h4
-rw-r--r--engines/m4/m4.cpp2
-rw-r--r--engines/m4/mads_player.cpp190
-rw-r--r--engines/m4/mads_player.h11
-rw-r--r--engines/m4/mads_scene.cpp8
-rw-r--r--engines/m4/mads_views.cpp13
-rw-r--r--engines/m4/mads_views.h3
8 files changed, 205 insertions, 30 deletions
diff --git a/engines/m4/assets.cpp b/engines/m4/assets.cpp
index 9cfb7afc4c..23122eb960 100644
--- a/engines/m4/assets.cpp
+++ b/engines/m4/assets.cpp
@@ -632,9 +632,9 @@ int32 AssetManager::getSpriteFrameCount(int32 hash) {
//--------------------------------------------------------------------------
MadsSpriteSetCharInfo::MadsSpriteSetCharInfo(Common::SeekableReadStream *s) {
- _frameNumber = s->readByte();
+ _totalFrames = s->readByte();
s->skip(1);
- _hasIdling = s->readUint16LE() != 0;
+ _numEntries = s->readUint16LE();
for (int i = 0; i < 16; ++i)
_frameList[i] = s->readUint16LE();
diff --git a/engines/m4/assets.h b/engines/m4/assets.h
index e9902d8aa6..3ae7fb2e22 100644
--- a/engines/m4/assets.h
+++ b/engines/m4/assets.h
@@ -106,8 +106,8 @@ class MadsSpriteSetCharInfo {
public:
MadsSpriteSetCharInfo(Common::SeekableReadStream *s);
- int _frameNumber;
- int _hasIdling;
+ int _totalFrames;
+ int _numEntries;
int _frameList2[16];
int _frameList[16];
int _ticksList[16];
diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp
index f5c6d260a9..a999a6bd5a 100644
--- a/engines/m4/m4.cpp
+++ b/engines/m4/m4.cpp
@@ -538,6 +538,8 @@ Common::Error MadsEngine::run() {
//printf("%s\n----------\n", _globals->loadMessage(i));
if (getGameType() == GType_RexNebular) {
+ MadsGameLogic::initialiseGlobals();
+
_scene = NULL;
loadMenu(MAIN_MENU);
} else {
diff --git a/engines/m4/mads_player.cpp b/engines/m4/mads_player.cpp
index 57cb9eefd3..bb7a1b406d 100644
--- a/engines/m4/mads_player.cpp
+++ b/engines/m4/mads_player.cpp
@@ -38,6 +38,9 @@ MadsPlayer::MadsPlayer() {
_direction = 0;
_direction2 = 0;
_forceRefresh = true;
+ _stepEnabled = true;
+ _ticksAmount = 3;
+ _priorTimer = 0;
_visible = true;
_priorVisible = false;
_visible3 = false;
@@ -53,7 +56,7 @@ MadsPlayer::MadsPlayer() {
_frameNum = 0;
_frameOffset = 0;
_unk1 = 0;
- _newFrame = 0;
+ _frameCount = 0;
_frameListIndex = 0;
_actionIndex = 0;
resetActionList();
@@ -154,7 +157,7 @@ void MadsPlayer::update() {
if (equal)
// Undo the prior expiry of the player sprite
- slot.spriteType = SPRITE_ZERO;
+ s2.spriteType = SPRITE_ZERO;
else
slotIndex = -1;
}
@@ -175,13 +178,13 @@ void MadsPlayer::update() {
}
/**
- * Idling animation for player
+ * Updates the animation frame for the player
*/
-void MadsPlayer::idle() {
+void MadsPlayer::updateFrame() {
SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2);
assert(spriteSet._charInfo);
- if (!spriteSet._charInfo->_hasIdling) {
+ if (!spriteSet._charInfo->_numEntries) {
_frameNum = 1;
} else {
_frameListIndex = _actionList[_actionIndex];
@@ -204,7 +207,7 @@ void MadsPlayer::idle() {
if (frameIndex == 0)
setTicksAmount();
else
- _madsVm->scene()->_ticksAmount = spriteSet._charInfo->_ticksList[frameIndex];
+ _madsVm->_player._ticksAmount = spriteSet._charInfo->_ticksList[frameIndex];
}
}
@@ -223,19 +226,103 @@ void MadsPlayer::setupFrame() {
_unk1 = MAX(spriteSet._charInfo->_unk1, 100);
setTicksAmount();
- _newFrame = spriteSet._charInfo->_frameNumber;
- if (_newFrame == 0)
- _newFrame = spriteSet.getCount();
+ _frameCount = spriteSet._charInfo->_totalFrames;
+ if (_frameCount == 0)
+ _frameCount = spriteSet.getCount();
_yScale = spriteSet._charInfo->_yScale;
- if ((_frameNum <= 0) || (_frameNum > _newFrame))
+ if ((_frameNum <= 0) || (_frameNum > _frameCount))
_frameNum = 1;
_forceRefresh = true;
}
void MadsPlayer::step() {
+ if (_visible && _stepEnabled && !_moving && (_direction == _direction2) && (_madsVm->_currentTimer >= GET_GLOBAL32(2))) {
+ if (_actionIndex == 0) {
+ int randVal = _vm->_random->getRandomNumber(29999);
+
+ if (GET_GLOBAL(0) == SEX_MALE) {
+ switch (_direction) {
+ case 1:
+ case 3:
+ case 7:
+ case 9:
+ if (randVal < 200) {
+ queueAction(-1, 0);
+ queueAction(1, 0);
+ }
+ break;
+
+ case 2:
+ if (randVal < 500) {
+ for (int i = 0; i < 10; ++i)
+ queueAction((randVal < 250) ? 1 : 2, 0);
+ } else if (randVal < 750) {
+ for (int i = 0; i < 5; ++i)
+ queueAction(1, 0);
+ queueAction(0, 0);
+ for (int i = 0; i < 5; ++i)
+ queueAction(2, 0);
+ }
+ break;
+
+ case 4:
+ case 6:
+ if (randVal < 500) {
+ for (int i = 0; i < 10; ++i)
+ queueAction(1, 0);
+ }
+ break;
+
+ case 5:
+ case 8:
+ if (randVal < 200) {
+ queueAction(-1, 0);
+ queueAction(1, 0);
+ }
+ break;
+ }
+ }
+ }
+
+ SET_GLOBAL32(2, GET_GLOBAL32(2) + 6);
+ }
+
+ if (GET_GLOBAL(138) == 1) {
+ uint32 diff = _madsVm->_currentTimer - GET_GLOBAL32(142);
+ if (diff > 60) {
+ SET_GLOBAL32(144, GET_GLOBAL32(144) + 1);
+ } else {
+ SET_GLOBAL32(144, GET_GLOBAL32(144) + diff);
+ }
+
+ SET_GLOBAL32(142, _madsVm->_currentTimer);
+ }
+}
+
+void MadsPlayer::nextFrame() {
+ if (_madsVm->_currentTimer >= (_priorTimer + _ticksAmount)) {
+ _priorTimer = _madsVm->_currentTimer;
+
+ if (_moving)
+ move();
+ else
+ idle();
+
+ // Post update logic
+ if (_moving) {
+ ++_frameNum;
+ if (_frameNum > _frameCount)
+ _frameNum = 1;
+ _forceRefresh = true;
+ } else if (!_forceRefresh) {
+ idle();
+ }
+ // Final update
+ update();
+ }
}
int MadsPlayer::getScale(int yp) {
@@ -262,9 +349,9 @@ int MadsPlayer::getSpriteSlot() {
void MadsPlayer::setTicksAmount() {
SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2);
assert(spriteSet._charInfo);
- _madsVm->scene()->_ticksAmount = spriteSet._charInfo->_ticksAmount;
- if (_madsVm->scene()->_ticksAmount == 0)
- _madsVm->scene()->_ticksAmount = 6;
+ _madsVm->_player._ticksAmount = spriteSet._charInfo->_ticksAmount;
+ if (_madsVm->_player._ticksAmount == 0)
+ _madsVm->_player._ticksAmount = 6;
}
void MadsPlayer::resetActionList() {
@@ -279,7 +366,7 @@ int MadsPlayer::queueAction(int action1, int action2) {
SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2);
assert(spriteSet._charInfo);
- if ((spriteSet._charInfo->_hasIdling) && (_actionIndex < 11)) {
+ if ((action1 < spriteSet._charInfo->_numEntries) && (_actionIndex < 11)) {
++_actionIndex;
_actionList[_actionIndex] = action1;
_actionList2[_actionIndex] = action2;
@@ -289,4 +376,79 @@ int MadsPlayer::queueAction(int action1, int action2) {
return true;
}
+void MadsPlayer::idle() {
+ if (_direction != _direction2) {
+ // The direction has changed, so reset for new direction
+ dirChanged();
+ return;
+ }
+
+ SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2);
+ assert(spriteSet._charInfo);
+ if (spriteSet._charInfo->_numEntries == 0)
+ // No entries, so exit immediately
+ return;
+
+ int frameIndex = ABS(_frameListIndex);
+ int direction = (_frameListIndex < 0) ? -1 : 1;
+
+ if (frameIndex >= spriteSet._charInfo->_numEntries)
+ // Reset back to the start of the list
+ _frameListIndex = 0;
+ else {
+ _frameNum += direction;
+ _forceRefresh = true;
+
+ if (spriteSet._charInfo->_frameList2[frameIndex] < _frameNum) {
+ _unk3 = _unk2;
+ updateFrame();
+ }
+ if (spriteSet._charInfo->_frameList[frameIndex] < _frameNum) {
+ _unk3 = _unk2;
+ updateFrame();
+ }
+ }
+}
+
+void MadsPlayer::move() {
+ // TODO: Handle player movement
+}
+
+void MadsPlayer::dirChanged() {
+ int dirIndex = 0, dirIndex2 = 0;
+ int newDir = 0, newDir2 = 0;
+
+ if (_direction != _direction2) {
+ // Find the index for the given direction in the player direction list
+ int tempDir = _direction;
+ do {
+ ++dirIndex;
+ newDir += tempDir;
+ tempDir = _directionListIndexes[tempDir + 10];
+ } while (tempDir != _direction2);
+ }
+
+
+ if (_direction != _direction2) {
+ // Find the index for the given direction in the player direction list
+ int tempDir = _direction;
+ do {
+ ++dirIndex2;
+ newDir2 += tempDir;
+ tempDir = _directionListIndexes[tempDir + 10];
+ } while (tempDir != _direction2);
+ }
+
+ int diff = dirIndex - dirIndex2;
+ if (diff == 0)
+ diff = newDir - newDir2;
+
+ _direction = (diff >= 0) ? _directionListIndexes[_direction] : _directionListIndexes[_direction + 10];
+ setupFrame();
+ if ((_direction == _direction2) && !_moving)
+ updateFrame();
+
+ _priorTimer += 1;
+}
+
} // End of namespace M4
diff --git a/engines/m4/mads_player.h b/engines/m4/mads_player.h
index 7285796309..7db45cae43 100644
--- a/engines/m4/mads_player.h
+++ b/engines/m4/mads_player.h
@@ -39,13 +39,19 @@ private:
void setTicksAmount();
void resetActionList();
int queueAction(int v0, int v1);
+ void idle();
+ void move();
+ void dirChanged();
public:
char _spritesPrefix[16];
int _spriteSetCount;
bool _spriteSetsPresent[8];
Common::Point _playerPos;
Common::Point _destPos;
+ uint32 _priorTimer;
+ uint _ticksAmount;
int16 _direction, _direction2;
+ bool _stepEnabled;
bool _visible, _priorVisible;
bool _visible3;
bool _forceRefresh;
@@ -57,7 +63,7 @@ public:
uint16 _frameOffset, _frameNum;
bool _moving;
int _unk1;
- int _newFrame;
+ int _frameCount;
int _frameListIndex;
int _actionIndex;
int _actionList[12];
@@ -71,9 +77,10 @@ public:
bool loadSprites(const char *prefix);
void update();
- void idle();
+ void updateFrame();
void setupFrame();
void step();
+ void nextFrame();
};
} // End of namespace M4
diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp
index 66883dd13c..3e838fc1c0 100644
--- a/engines/m4/mads_scene.cpp
+++ b/engines/m4/mads_scene.cpp
@@ -167,7 +167,7 @@ void MadsScene::loadScene(int sceneNumber) {
_madsVm->_player._destPos = _madsVm->_player._destPos;
_madsVm->_player._direction2 = _madsVm->_player._direction;
_madsVm->_player.setupFrame();
- _madsVm->_player.idle();
+ _madsVm->_player.updateFrame();
// Purge resources
_vm->res()->purge();
@@ -337,9 +337,15 @@ void MadsScene::updateState() {
// Step through the scene
_sceneLogic.sceneStep();
+ _madsVm->_player.step();
+ _madsVm->_player._unk3 = 0;
+
if (_abortTimersMode == ABORTMODE_1)
_abortTimers = 0;
+ // Handle updating the player frame
+ _madsVm->_player.nextFrame();
+
if ((_activeAnimation) && !_abortTimers) {
_activeAnimation->update();
if (((MadsAnimation *) _activeAnimation)->freeFlag()) {
diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp
index 580f54b1c0..d7e6435b14 100644
--- a/engines/m4/mads_views.cpp
+++ b/engines/m4/mads_views.cpp
@@ -426,15 +426,15 @@ int MadsKernelMessageList::add(const Common::Point &pt, uint fontColour, uint8 f
for (int i = 0; i < 3; ++i)
rec.actionNouns[i] = _madsVm->globals()->actionNouns[i];
- if (flags & KMSG_OWNER_TIMEOUT)
- rec.frameTimer = _owner._ticksAmount + _owner._newTimeout;
+ if (flags & KMSG_PLAYER_TIMEOUT)
+ rec.frameTimer = _madsVm->_player._ticksAmount + _madsVm->_player._priorTimer;
return idx;
}
int MadsKernelMessageList::addQuote(int quoteId, int abortTimers, uint32 timeout) {
const char *quoteStr = _madsVm->globals()->getQuote(quoteId);
- return add(Common::Point(0, 0), 0x1110, KMSG_OWNER_TIMEOUT | KMSG_CENTER_ALIGN, abortTimers, timeout, quoteStr);
+ return add(Common::Point(0, 0), 0x1110, KMSG_PLAYER_TIMEOUT | KMSG_CENTER_ALIGN, abortTimers, timeout, quoteStr);
}
void MadsKernelMessageList::scrollMessage(int msgIndex, int numTicks, bool quoted) {
@@ -450,8 +450,8 @@ void MadsKernelMessageList::scrollMessage(int msgIndex, int numTicks, bool quote
_entries[msgIndex].asciiChar = *msgP;
_entries[msgIndex].asciiChar2 = *(msgP + 1);
- if (_entries[msgIndex].flags & KMSG_OWNER_TIMEOUT)
- _entries[msgIndex].frameTimer2 = _owner._ticksAmount + _owner._newTimeout;
+ if (_entries[msgIndex].flags & KMSG_PLAYER_TIMEOUT)
+ _entries[msgIndex].frameTimer2 = _madsVm->_player._ticksAmount + _madsVm->_player._priorTimer;
_entries[msgIndex].frameTimer = _entries[msgIndex].frameTimer2;
}
@@ -545,7 +545,7 @@ void MadsKernelMessageList::processText(int msgIndex) {
}
}
- if (msg.flags & KMSG_OWNER_TIMEOUT) {
+ if (msg.flags & KMSG_PLAYER_TIMEOUT) {
if (word_8469E != 0) {
// TODO: Figure out various flags
} else {
@@ -1211,7 +1211,6 @@ MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceL
_kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this) {
_textSpacing = -1;
- _ticksAmount = 3;
_newTimeout = 0;
_abortTimers = 0;
_abortTimers2 = 0;
diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h
index ead6ae94bf..0604ae1ee1 100644
--- a/engines/m4/mads_views.h
+++ b/engines/m4/mads_views.h
@@ -149,7 +149,7 @@ public:
#define TIMED_TEXT_SIZE 10
#define INDEFINITE_TIMEOUT 9999999
-enum KernelMessageFlags {KMSG_QUOTED = 1, KMSG_OWNER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, KMSG_RIGHT_ALIGN = 0x10,
+enum KernelMessageFlags {KMSG_QUOTED = 1, KMSG_PLAYER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, KMSG_RIGHT_ALIGN = 0x10,
KMSG_CENTER_ALIGN = 0x20, KMSG_EXPIRE = 0x40, KMSG_ACTIVE = 0x80};
class MadsKernelMessageEntry {
@@ -395,7 +395,6 @@ public:
MadsDirtyAreas _dirtyAreas;
int _textSpacing;
- int _ticksAmount;
uint32 _newTimeout;
int _abortTimers;
int8 _abortTimers2;