mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-04 01:46:42 +00:00
GOB: Implement parts of the Once Upon A Time end sequence
We don't yet support GCT files, so texts are still missing.
This commit is contained in:
parent
60f52ab9a0
commit
df18bc9583
@ -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;
|
||||
}
|
||||
|
||||
bool OnceUpon::sectionEnd() {
|
||||
warning("OnceUpon::sectionEnd(): TODO");
|
||||
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() {
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user