MYST3: Implement script driven camera movement

This commit is contained in:
Bastien Bouclet 2011-11-05 09:07:25 +01:00
parent 0ecc03f28f
commit 656c342af6
6 changed files with 79 additions and 0 deletions

View file

@ -809,4 +809,61 @@ Common::Error Myst3Engine::loadGameState(int slot) {
return Common::kUnknownError;
}
void Myst3Engine::animateDirectionChange(float targetPitch, float targetHeading, uint16 scriptFrames) {
float startPitch = _state->getLookAtPitch();
float startHeading = _state->getLookAtHeading();
if (startPitch == targetPitch && startHeading == targetHeading)
return; // Fast path
float pitchDistance = targetPitch - startPitch;
float headingDistance = targetHeading - startHeading;
// Compute animation duration in frames
float numFrames;
if (scriptFrames) {
numFrames = scriptFrames;
} else {
numFrames = sqrt(pitchDistance * pitchDistance + headingDistance * headingDistance)
* 30.0f / _state->getCameraMoveSpeed();
if (numFrames > 0.0f)
numFrames += 10.0f;
}
uint startFrame = _state->getFrameCount();
// Draw animation
if (numFrames != 0.0f) {
while (1) {
uint elapsedFrames = _state->getFrameCount() - startFrame;
if (elapsedFrames >= numFrames)
break;
float step;
if (numFrames >= 15) {
// Fast then slow movement
if (elapsedFrames > numFrames / 2.0f)
step = 1.0f - (numFrames - elapsedFrames) * (numFrames - elapsedFrames)
/ (numFrames / 2.0f * numFrames / 2.0f) / 2.0f;
else
step = elapsedFrames * elapsedFrames / (numFrames / 2.0f * numFrames / 2.0f) / 2.0f;
} else {
// Constant speed movement
step = elapsedFrames / numFrames;
}
float nextPitch = startPitch + pitchDistance * step;
float nextHeading = startHeading + headingDistance * step;
_state->lookAt(nextPitch, nextHeading);
drawFrame();
}
}
_state->lookAt(targetPitch, targetHeading);
drawFrame();
}
} // end of namespace Myst3

View file

@ -117,6 +117,8 @@ public:
void setMenuAction(uint16 action) { _menuAction = action; }
void setShouldQuit() { _shouldQuit = true; }
void animateDirectionChange(float pitch, float heading, uint16 speed);
void processInput(bool lookOnly);
void drawFrame();
private:

View file

@ -174,6 +174,8 @@ Script::Script(Myst3Engine *vm):
OP_2(141, zipToRoomNode, kValue, kValue );
OP_1(147, moviePlay, kEvalValue );
OP_1(148, moviePlaySynchronized, kEvalValue );
OP_2(153, lootAt, kValue, kValue );
OP_3(154, lootAtInXFrames, kValue, kValue, kValue );
OP_4(157, cameraLimitMovement, kValue, kValue, kValue, kValue );
OP_0(158, cameraFreeMovement );
OP_2(159, cameraLookAt, kValue, kValue );
@ -1889,6 +1891,18 @@ void Script::runScriptWhileCondEachXFrames(Context &c, const Opcode &cmd) {
_vm->drawFrame();
}
void Script::lootAt(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Look at %d, %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->animateDirectionChange(cmd.args[0], cmd.args[1], 0);
}
void Script::lootAtInXFrames(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Look at %d, %d in %d frames", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
_vm->animateDirectionChange(cmd.args[0], cmd.args[1], cmd.args[2]);
}
void Script::runScriptForVarDrawFramesHelper(uint16 var, int32 startValue, int32 endValue, uint16 script, int32 numFrames) {
if (numFrames < 0) {
numFrames = -numFrames;

View file

@ -224,6 +224,8 @@ private:
DECLARE_OPCODE(zipToRoomNode);
DECLARE_OPCODE(moviePlay);
DECLARE_OPCODE(moviePlaySynchronized);
DECLARE_OPCODE(lootAt);
DECLARE_OPCODE(lootAtInXFrames);
DECLARE_OPCODE(cameraLimitMovement);
DECLARE_OPCODE(cameraFreeMovement);
DECLARE_OPCODE(cameraLookAt);

View file

@ -97,6 +97,8 @@ GameState::GameState(Myst3Engine *vm):
VAR(178, MovieUseBackground, false)
VAR(185, CameraMoveSpeed, false)
VAR(189, LocationNextNode, false)
VAR(190, LocationNextRoom, false)
VAR(191, LocationNextAge, false)

View file

@ -111,6 +111,8 @@ public:
DECLARE_VAR(178, MovieUseBackground)
DECLARE_VAR(185, CameraMoveSpeed)
DECLARE_VAR(189, LocationNextNode)
DECLARE_VAR(190, LocationNextRoom)
DECLARE_VAR(191, LocationNextAge)