aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Hesse2012-07-02 21:31:23 +0200
committerSven Hesse2012-07-30 01:44:44 +0200
commitdf18bc95834837f1f905bfe5613ffd43dfc908f9 (patch)
tree51f4d28d5cd1e73f2ddc6cd734c2e331d5ff7464
parent60f52ab9a0beccccca4958fbcf4d369e6dd22748 (diff)
downloadscummvm-rg350-df18bc95834837f1f905bfe5613ffd43dfc908f9.tar.gz
scummvm-rg350-df18bc95834837f1f905bfe5613ffd43dfc908f9.tar.bz2
scummvm-rg350-df18bc95834837f1f905bfe5613ffd43dfc908f9.zip
GOB: Implement parts of the Once Upon A Time end sequence
We don't yet support GCT files, so texts are still missing.
-rw-r--r--engines/gob/pregob/onceupon/onceupon.cpp103
-rw-r--r--engines/gob/pregob/onceupon/onceupon.h10
-rw-r--r--engines/gob/pregob/pregob.cpp62
-rw-r--r--engines/gob/pregob/pregob.h37
4 files changed, 176 insertions, 36 deletions
diff --git a/engines/gob/pregob/onceupon/onceupon.cpp b/engines/gob/pregob/onceupon/onceupon.cpp
index fb9629566c..aed1b45e02 100644
--- a/engines/gob/pregob/onceupon/onceupon.cpp
+++ b/engines/gob/pregob/onceupon/onceupon.cpp
@@ -264,14 +264,6 @@ void OnceUpon::setGameCursor() {
setCursor(cursor, 105, 0, 120, 15, 0, 0);
}
-void OnceUpon::setAnimState(ANIObject &ani, uint16 state, bool once, bool pause) const {
- ani.setAnimation(state);
- ani.setMode(once ? ANIObject::kModeOnce : ANIObject::kModeContinuous);
- ani.setPause(pause);
- ani.setVisible(true);
- ani.setPosition();
-}
-
void OnceUpon::drawLineByLine(const Surface &src, int16 left, int16 top, int16 right, int16 bottom,
int16 x, int16 y) const {
@@ -374,6 +366,18 @@ Common::String OnceUpon::fixString(const Common::String &str) const {
return str;
}
+enum ClownAnimation {
+ kClownAnimationStand = 0,
+ kClownAnimationCheer = 1,
+ kClownAnimationCry = 2
+};
+
+const PreGob::AnimProperties OnceUpon::kClownAnimations[] = {
+ { 1, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 0, 0, ANIObject::kModeOnce , true, false, false, 0, 0},
+ { 6, 0, ANIObject::kModeOnce , true, false, false, 0, 0}
+};
+
enum CopyProtectionState {
kCPStateSetup, // Set up the screen
kCPStateWaitUser, // Waiting for the user to pick a shape
@@ -392,8 +396,10 @@ bool OnceUpon::doCopyProtection(const uint8 colors[7], const uint8 shapes[7 * 20
_vm->_video->drawPackedSprite("grille2.cmp", sprites[1]);
// Load the clown animation
- ANIFile ani (_vm, "grille.ani", 320);
- ANIObject clown(ani);
+ ANIFile ani (_vm, "grille.ani", 320);
+ ANIList anims;
+
+ loadAnims(anims, ani, 1, &kClownAnimations[kClownAnimationStand]);
// Set the copy protection cursor
setCursor(sprites[1], 5, 110, 20, 134, 3, 0);
@@ -406,20 +412,20 @@ bool OnceUpon::doCopyProtection(const uint8 colors[7], const uint8 shapes[7 * 20
bool hasCorrect = false;
while (!_vm->shouldQuit() && (state != kCPStateFinish)) {
- clearAnim(clown);
+ clearAnim(anims);
// Set up the screen
if (state == kCPStateSetup) {
animalShape = cpSetup(colors, shapes, obfuscate, sprites);
- setAnimState(clown, kClownAnimationClownStand, false, false);
+ setAnim(*anims[0], kClownAnimations[kClownAnimationStand]);
state = kCPStateWaitUser;
}
- drawAnim(clown);
+ drawAnim(anims);
// If we're waiting for the clown and he finished, evaluate if we're finished
- if (!clown.isVisible() && (state == kCPStateWaitClown))
+ if (!anims[0]->isVisible() && (state == kCPStateWaitClown))
state = (hasCorrect || (--triesLeft == 0)) ? kCPStateFinish : kCPStateSetup;
showCursor();
@@ -443,12 +449,14 @@ bool OnceUpon::doCopyProtection(const uint8 colors[7], const uint8 shapes[7 * 20
hasCorrect = guessedShape == animalShape;
animalShape = -1;
- setAnimState(clown, hasCorrect ? kClownAnimationClownCheer : kClownAnimationClownCry, true, false);
+ setAnim(*anims[0], kClownAnimations[hasCorrect ? kClownAnimationCheer : kClownAnimationCry]);
state = kCPStateWaitClown;
}
}
}
+ freeAnims(anims);
+
fadeOut();
hideCursor();
clearScreen();
@@ -625,6 +633,10 @@ void OnceUpon::showQuote() {
fadeOut();
}
+const PreGob::AnimProperties OnceUpon::kTitleAnimation = {
+ 8, 0, ANIObject::kModeContinuous, true, false, false, 0, 0
+};
+
void OnceUpon::showTitle() {
// Show the Once Upon A Time title animation
// NOTE: This is currently only a mock-up. The real animation is in "ville.seq".
@@ -639,15 +651,15 @@ void OnceUpon::showTitle() {
_vm->_video->drawPackedSprite("ville.cmp", *_vm->_draw->_backSurface);
_vm->_draw->forceBlit();
- ANIFile ani (_vm, "pres.ani", 320);
- ANIObject title(ani);
+ ANIFile ani (_vm, "pres.ani", 320);
+ ANIList anims;
- setAnimState(title, 8, false, false);
+ loadAnims(anims, ani, 1, &kTitleAnimation);
playTitleMusic();
while (!_vm->shouldQuit()) {
- redrawAnim(title);
+ redrawAnim(anims);
fadeIn();
@@ -657,6 +669,8 @@ void OnceUpon::showTitle() {
break;
}
+ freeAnims(anims);
+
fadeOut();
stopTitleMusic();
}
@@ -1349,9 +1363,58 @@ bool OnceUpon::sectionChapter7() {
return true;
}
+const PreGob::AnimProperties OnceUpon::kSectionEndAnimations[] = {
+ { 0, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 6, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ { 9, 0, ANIObject::kModeContinuous, true, false, false, 0, 0},
+ {11, 0, ANIObject::kModeContinuous, true, false, false, 0, 0}
+};
+
bool OnceUpon::sectionEnd() {
- warning("OnceUpon::sectionEnd(): TODO");
+ fadeOut();
+ setGamePalette(9);
+
+ _vm->_video->drawPackedSprite("cadre.cmp", *_vm->_draw->_backSurface);
+
+ Surface endBackground(320, 200, 1);
+ _vm->_video->drawPackedSprite("fin.cmp", endBackground);
+
+ _vm->_draw->_backSurface->blit(endBackground, 0, 0, 288, 137, 16, 50);
+
+ ANIFile ani(_vm, "fin.ani", 320);
+ ANIList anims;
+
+ loadAnims(anims, ani, ARRAYSIZE(kSectionEndAnimations), kSectionEndAnimations);
+ drawAnim(anims);
+
+ _vm->_draw->forceBlit();
+
+ MenuAction action = kMenuActionNone;
+ while (!_vm->shouldQuit() && (action == kMenuActionNone)) {
+ redrawAnim(anims);
+
+ fadeIn();
+
+ endFrame(true);
+
+ int16 mouseX, mouseY;
+ MouseButtons mouseButtons;
+
+ int16 key = checkInput(mouseX, mouseY, mouseButtons);
+ if ((key != 0) && (key != kKeyEscape))
+ // Any key pressed => Quit
+ action = kMenuActionQuit;
+
+ action = doIngameMenu(key, mouseButtons);
+ }
+
+ freeAnims(anims);
+
+ // Restart requested
+ if (action == kMenuActionRestart)
+ return false;
+ // Last scene. Even if we didn't explicitly request a quit, the game ends here
_quit = true;
return false;
}
diff --git a/engines/gob/pregob/onceupon/onceupon.h b/engines/gob/pregob/onceupon/onceupon.h
index 0cae369758..caaf155d06 100644
--- a/engines/gob/pregob/onceupon/onceupon.h
+++ b/engines/gob/pregob/onceupon/onceupon.h
@@ -149,19 +149,23 @@ private:
/** All general game sounds we know about. */
static const char *kSound[kSoundMAX];
+
+ static const AnimProperties kClownAnimations[];
+ static const AnimProperties kTitleAnimation;
+ static const AnimProperties kSectionEndAnimations[];
+
+
/** Function pointer type for a section handler. */
typedef bool (OnceUpon::*SectionFunc)();
/** Section handler function. */
static const SectionFunc kSectionFuncs[kSectionCount];
+
// -- General helpers --
void setGamePalette(uint palette); ///< Set a game palette.
void setGameCursor(); ///< Set the default game cursor.
- /** Set the state of an ANIObject. */
- void setAnimState(ANIObject &ani, uint16 state, bool once, bool pause) const;
-
/** Draw this sprite in a fancy, animated line-by-line way. */
void drawLineByLine(const Surface &src, int16 left, int16 top, int16 right, int16 bottom,
int16 x, int16 y) const;
diff --git a/engines/gob/pregob/pregob.cpp b/engines/gob/pregob/pregob.cpp
index 675958035d..4ee5430de7 100644
--- a/engines/gob/pregob/pregob.cpp
+++ b/engines/gob/pregob/pregob.cpp
@@ -251,24 +251,70 @@ bool PreGob::hasInput() {
return checkInput(mouseX, mouseY, mouseButtons) || (mouseButtons != kMouseButtonsNone);
}
-void PreGob::clearAnim(ANIObject &ani) {
+void PreGob::clearAnim(ANIObject &anim) {
int16 left, top, right, bottom;
- if (ani.clear(*_vm->_draw->_backSurface, left, top, right, bottom))
+ if (anim.clear(*_vm->_draw->_backSurface, left, top, right, bottom))
_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
}
-void PreGob::drawAnim(ANIObject &ani) {
+void PreGob::drawAnim(ANIObject &anim) {
int16 left, top, right, bottom;
- if (ani.draw(*_vm->_draw->_backSurface, left, top, right, bottom))
+ if (anim.draw(*_vm->_draw->_backSurface, left, top, right, bottom))
_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
- ani.advance();
+ anim.advance();
}
-void PreGob::redrawAnim(ANIObject &ani) {
- clearAnim(ani);
- drawAnim(ani);
+void PreGob::redrawAnim(ANIObject &anim) {
+ clearAnim(anim);
+ drawAnim(anim);
+}
+
+void PreGob::clearAnim(const ANIList &anims) {
+ for (int i = (anims.size() - 1); i >= 0; i--)
+ clearAnim(*anims[i]);
+}
+
+void PreGob::drawAnim(const ANIList &anims) {
+ for (ANIList::const_iterator a = anims.begin(); a != anims.end(); ++a)
+ drawAnim(**a);
+}
+
+void PreGob::redrawAnim(const ANIList &anims) {
+ clearAnim(anims);
+ drawAnim(anims);
+}
+
+void PreGob::loadAnims(ANIList &anims, ANIFile &ani, uint count, const AnimProperties *props) const {
+ freeAnims(anims);
+
+ anims.resize(count);
+ for (uint i = 0; i < count; i++) {
+ anims[i] = new ANIObject(ani);
+
+ setAnim(*anims[i], props[i]);
+ }
+}
+
+void PreGob::freeAnims(ANIList &anims) const {
+ for (ANIList::iterator a = anims.begin(); a != anims.end(); ++a)
+ delete *a;
+
+ anims.clear();
+}
+
+void PreGob::setAnim(ANIObject &anim, const AnimProperties &props) const {
+ anim.setAnimation(props.animation);
+ anim.setFrame(props.frame);
+ anim.setMode(props.mode);
+ anim.setPause(props.paused);
+ anim.setVisible(props.visible);
+
+ if (props.hasPosition)
+ anim.setPosition(props.x, props.y);
+ else
+ anim.setPosition();
}
Common::String PreGob::getLocFile(const Common::String &file) const {
diff --git a/engines/gob/pregob/pregob.h b/engines/gob/pregob/pregob.h
index e62a59042b..f1728036ab 100644
--- a/engines/gob/pregob/pregob.h
+++ b/engines/gob/pregob/pregob.h
@@ -27,6 +27,7 @@
#include "common/array.h"
#include "gob/util.h"
+#include "gob/aniobject.h"
#include "gob/sound/sounddesc.h"
@@ -37,8 +38,6 @@ namespace Gob {
class GobEngine;
class Surface;
-class ANIObject;
-
class PreGob {
public:
PreGob(GobEngine *vm);
@@ -46,7 +45,23 @@ public:
virtual void run() = 0;
+ struct AnimProperties {
+ uint16 animation;
+ uint16 frame;
+
+ ANIObject::Mode mode;
+
+ bool visible;
+ bool paused;
+
+ bool hasPosition;
+ int16 x;
+ int16 y;
+ };
+
protected:
+ typedef Common::Array<ANIObject *> ANIList;
+
static const char kLanguageSuffixShort[5];
static const char *kLanguageSuffixLong [5];
@@ -88,11 +103,23 @@ protected:
bool isCursorVisible() const;
/** Remove an animation from the screen. */
- void clearAnim(ANIObject &ani);
+ void clearAnim(ANIObject &anim);
/** Draw an animation to the screen, advancing it. */
- void drawAnim(ANIObject &ani);
+ void drawAnim(ANIObject &anim);
/** Clear and draw an animation to the screen, advancing it. */
- void redrawAnim(ANIObject &ani);
+ void redrawAnim(ANIObject &anim);
+
+ /** Remove animations from the screen. */
+ void clearAnim(const ANIList &anims);
+ /** Draw animations to the screen, advancing them. */
+ void drawAnim(const ANIList &anims);
+ /** Clear and draw animations to the screen, advancing them. */
+ void redrawAnim(const ANIList &anims);
+
+ void loadAnims(ANIList &anims, ANIFile &ani, uint count, const AnimProperties *props) const;
+ void freeAnims(ANIList &anims) const;
+
+ void setAnim(ANIObject &anim, const AnimProperties &props) const;
/** Wait for the frame to end, handling screen updates and optionally update input. */
void endFrame(bool doInput);