aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorjohndoe1232011-08-30 14:02:12 +0000
committerWillem Jan Palenstijn2013-05-08 20:39:35 +0200
commitc4a4ce4e3561cbaa09e83e9938e6a41b79d8c0f0 (patch)
tree5614e45ccc28049c2c43d6324b83e9cfd093851f /engines
parentb64b0cfac2b066bfdd63e938624d742dc1123365 (diff)
downloadscummvm-rg350-c4a4ce4e3561cbaa09e83e9938e6a41b79d8c0f0.tar.gz
scummvm-rg350-c4a4ce4e3561cbaa09e83e9938e6a41b79d8c0f0.tar.bz2
scummvm-rg350-c4a4ce4e3561cbaa09e83e9938e6a41b79d8c0f0.zip
NEVERHOOD: Implement Scene2202 (sliding puzzle)
Diffstat (limited to 'engines')
-rw-r--r--engines/neverhood/gamemodule.cpp2
-rw-r--r--engines/neverhood/module2200.cpp400
-rw-r--r--engines/neverhood/module2200.h47
3 files changed, 447 insertions, 2 deletions
diff --git a/engines/neverhood/gamemodule.cpp b/engines/neverhood/gamemodule.cpp
index e797240e4e..9d9a97a943 100644
--- a/engines/neverhood/gamemodule.cpp
+++ b/engines/neverhood/gamemodule.cpp
@@ -242,7 +242,7 @@ void GameModule::startup() {
createModule2000(-1);
#endif
#if 1
- _vm->gameState().sceneNum = 0;
+ _vm->gameState().sceneNum = 1;
createModule2200(-1);
#endif
}
diff --git a/engines/neverhood/module2200.cpp b/engines/neverhood/module2200.cpp
index 55f4192e7c..e9cb8fa8f6 100644
--- a/engines/neverhood/module2200.cpp
+++ b/engines/neverhood/module2200.cpp
@@ -197,6 +197,10 @@ void Module2200::createScene2201(int which) {
}
void Module2200::createScene2202(int which) {
+ // TODO Music18hList_play(0x601C908C, 0, 2, 1);
+ _vm->gameState().sceneNum = 1;
+ _childObject = new Scene2202(_vm, this, which);
+ SetUpdateHandler(&Module2200::updateScene2202);
}
void Module2200::createScene2203(int which) {
@@ -354,6 +358,13 @@ void Module2200::updateScene2201() {
}
void Module2200::updateScene2202() {
+ _childObject->handleUpdate();
+ if (_done) {
+ _done = false;
+ delete _childObject;
+ _childObject = NULL;
+ createScene2201(2);
+ }
}
void Module2200::updateScene2203() {
@@ -732,5 +743,394 @@ uint32 Scene2201::handleMessage(int messageNum, const MessageParam &param, Entit
}
return 0;
}
+
+static const NPoint kSsScene2202PuzzleTilePoints[] = {
+ {196, 105},
+ {323, 102},
+ {445, 106},
+ {192, 216},
+ {319, 220},
+ {446, 216},
+ {188, 320},
+ {319, 319},
+ {443, 322}
+};
+
+static const uint32 kSsScene2202PuzzleTileFileHashes1[] = {
+ 0xA500800C,
+ 0x2182910C,
+ 0x2323980C,
+ 0x23049084,
+ 0x21008080,
+ 0x2303900C,
+ 0x6120980C,
+ 0x2504D808
+};
+
+static const uint32 kSsScene2202PuzzleTileFileHashes2[] = {
+ 0x0AAD8080,
+ 0x0A290291,
+ 0x0A2BA398,
+ 0x822B8490,
+ 0x86298080,
+ 0x0A2B8390,
+ 0x0A69A098,
+ 0x0E2D84D8
+};
+
+SsScene2202PuzzleTile::SsScene2202PuzzleTile(NeverhoodEngine *vm, Scene *parentScene, int16 tileIndex, int16 value)
+ : StaticSprite(vm, 900), _soundResource1(vm), _soundResource2(vm), _parentScene(parentScene),
+ _value(value), _tileIndex(tileIndex), _isMoving(false) {
+
+ debug("#1 _value = %d; _tileIndex = %d", _value, _tileIndex);
+ SetUpdateHandler(&SsScene2202PuzzleTile::update);
+ SetMessageHandler(&SsScene2202PuzzleTile::handleMessage);
+ debug("#2");
+ _spriteResource.load2(kSsScene2202PuzzleTileFileHashes2[_value]);
+ if (_tileIndex >= 0 && _tileIndex <= 2) {
+ createSurface(100, 128, 128);
+ } else if (_tileIndex >= 3 && _tileIndex <= 5) {
+ createSurface(300, 128, 128);
+ } else {
+ createSurface(500, 128, 128);
+ }
+ debug("#3");
+ _drawRect.x = -(_spriteResource.getDimensions().width / 2);
+ _drawRect.y = -(_spriteResource.getDimensions().height / 2);
+ _drawRect.width = _spriteResource.getDimensions().width;
+ _drawRect.height = _spriteResource.getDimensions().height;
+ _deltaRect = _drawRect;
+ _x = kSsScene2202PuzzleTilePoints[_tileIndex].x;
+ _y = kSsScene2202PuzzleTilePoints[_tileIndex].y;
+ processDelta();
+ _needRefresh = true;
+ StaticSprite::update();
+ _soundResource1.load(0x40958621);
+ _soundResource2.load(0x51108241);
+ debug("LOAD OK");
+}
+
+void SsScene2202PuzzleTile::update() {
+ handleSpriteUpdate();
+ StaticSprite::update();
+}
+
+uint32 SsScene2202PuzzleTile::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x1011:
+ if (!_isMoving && !getGlobalVar(0x404290D5)) {
+ _parentScene->sendMessage(0x2000, _tileIndex, this);
+ }
+ messageResult = 1;
+ break;
+ case 0x2001:
+ _isMoving = true;
+ moveTile(param.asInteger());
+ break;
+ }
+ return messageResult;
+}
+void SsScene2202PuzzleTile::suMoveTileX() {
+
+ bool done = false;
+
+ if (_counterDirection) {
+ if (_counter > 2)
+ _counter -= 2;
+ } else {
+ if (_counter < 20)
+ _counter += 2;
+ }
+
+ for (int16 i = 0; i < _counter; i++) {
+ _x += _xIncr;
+ _errValue += _yDelta;
+ if (_errValue >= _xDelta) {
+ _errValue -= _xDelta;
+ _y += _yIncr;
+ }
+ if (_x == _newX && _y == _newY) {
+ done = true;
+ break;
+ }
+ if (_x == _xFlagPos)
+ _counterDirection = true;
+ }
+
+ if (done) {
+ stopMoving();
+ }
+
+ processDelta();
+
+}
+
+void SsScene2202PuzzleTile::suMoveTileY() {
+
+ bool done = false;
+
+ if (_counterDirection) {
+ if (_counter > 2)
+ _counter -= 2;
+ } else {
+ if (_counter < 20)
+ _counter += 2;
+ }
+
+ for (int16 i = 0; i < _counter; i++) {
+ _y += _yIncr;
+ _errValue += _xDelta;
+ if (_errValue >= _yDelta) {
+ _errValue -= _yDelta;
+ _x += _xIncr;
+ }
+ if (_x == _newX && _y == _newY) {
+ done = true;
+ break;
+ }
+ if (_x == _xFlagPos)
+ _counterDirection = true;
+ }
+
+ if (done) {
+ stopMoving();
+ }
+
+ processDelta();
+
+}
+
+void SsScene2202PuzzleTile::moveTile(int16 newTileIndex) {
+
+ _spriteResource.load2(kSsScene2202PuzzleTileFileHashes1[_value]);
+ _drawRect.x = -(_spriteResource.getDimensions().width / 2);
+ _drawRect.y = -(_spriteResource.getDimensions().height / 2);
+ _drawRect.width = _spriteResource.getDimensions().width;
+ _drawRect.height = _spriteResource.getDimensions().height;
+ _needRefresh = true;
+
+ setSubVar(0x484498D0, _tileIndex, (uint32)-1);
+ setSubVar(0x484498D0, newTileIndex, (uint32)_value);
+
+ _tileIndex = newTileIndex;
+
+ _errValue = 0;
+ _counterDirection = false;
+ _counter = 0;
+
+ _newX = kSsScene2202PuzzleTilePoints[newTileIndex].x;
+ _newY = kSsScene2202PuzzleTilePoints[newTileIndex].y;
+
+ if (_x == _newX && _y == _newY)
+ return;
+
+ if (_x <= _newX) {
+ if (_y <= _newY) {
+ _xDelta = _newX - _x;
+ _yDelta = _newY - _y;
+ _xIncr = 1;
+ _yIncr = 1;
+ } else {
+ _xDelta = _newX - _x;
+ _yDelta = _y - _newY;
+ _xIncr = 1;
+ _yIncr = -1;
+ }
+ } else {
+ if (_y <= _newY) {
+ _xDelta = _x - _newX;
+ _yDelta = _newY - _y;
+ _xIncr = -1;
+ _yIncr = 1;
+ } else {
+ _xDelta = _x - _newX;
+ _yDelta = _y - _newY;
+ _xIncr = -1;
+ _yIncr = -1;
+ }
+ }
+
+ if (_xDelta > _yDelta) {
+ SetSpriteCallback(&SsScene2202PuzzleTile::suMoveTileX);
+ if (_xIncr > 0) {
+ if (_newX - _x >= 180)
+ _xFlagPos = _newX - 90;
+ else
+ _xFlagPos = _x + _newX / 2;
+ } else {
+ if (_x - _newX >= 180)
+ _xFlagPos = _x + 90;
+ else
+ _xFlagPos = _x / 2 + _newX;
+ }
+ _soundResource1.play();
+ } else {
+ SetSpriteCallback(&SsScene2202PuzzleTile::suMoveTileY);
+ if (_yIncr > 0) {
+ if (_newY - _y >= 180)
+ _xFlagPos = _newY - 90;
+ else
+ _xFlagPos = _y + _newY / 2;
+ } else {
+ if (_y - _newY >= 180)
+ _xFlagPos = _y + 90;
+ else
+ _xFlagPos = _y / 2 + _newY;
+ }
+ _soundResource2.play();
+ }
+
+}
+
+void SsScene2202PuzzleTile::stopMoving() {
+ _spriteResource.load2(kSsScene2202PuzzleTileFileHashes2[_value]);
+ _drawRect.x = -(_spriteResource.getDimensions().width / 2);
+ _drawRect.y = -(_spriteResource.getDimensions().height / 2);
+ _drawRect.width = _spriteResource.getDimensions().width;
+ _drawRect.height = _spriteResource.getDimensions().height;
+ _needRefresh = true;
+ SetSpriteCallback(NULL);
+ _isMoving = false;
+ _parentScene->sendMessage(0x2002, _tileIndex, this);
+}
+
+Scene2202::Scene2202(NeverhoodEngine *vm, Module *parentModule, int which)
+ : Scene(vm, parentModule, true), _soundResource1(vm), _soundResource2(vm),
+ _isSolved(false), _leaveScene(false), _isTileMoving(false), _movingTileSprite(NULL), _doneMovingTileSprite(NULL) {
+
+ Palette2 *palette2;
+
+ // TODO initScene2201Vars();
+ SetMessageHandler(&Scene2202::handleMessage);
+ SetUpdateHandler(&Scene2202::update);
+
+ _surfaceFlag = true;
+
+ _background = addBackground(new DirtyBackground(_vm, 0x08100A0C, 0, 0));
+ palette2 = new Palette2(_vm, 0x08100A0C);
+ _palette = palette2;
+ _palette->usePalette();
+ addEntity(palette2);
+ _mouseCursor = addSprite(new Mouse435(_vm, 0x00A08089, 20, 620));
+
+ //DEBUG!
+ for (uint32 index = 0; index < 9; index++)
+ setSubVar(0x484498D0, index, 7 - index);
+
+ for (uint32 index = 0; index < 9; index++) {
+ int16 value = (int16)getSubVar(0x484498D0, index);
+ if (value >= 0) {
+ Sprite *puzzleTileSprite = addSprite(new SsScene2202PuzzleTile(_vm, this, index, value));
+ _vm->_collisionMan->addSprite(puzzleTileSprite);
+ }
+ }
+
+ addSprite(new StaticSprite(_vm, 0x55C043B8, 200));
+ addSprite(new StaticSprite(_vm, 0x85500158, 400));
+ addSprite(new StaticSprite(_vm, 0x25547028, 600));
+
+ _soundResource1.load(0x68E25540);
+ _soundResource2.load(0x40400457);
+
+ // TODO Sound1ChList_addSoundResource(0x60400854, 0x8101A241, true);
+ // TODO Sound1ChList_playLooping(0x8101A241);
+
+}
+
+Scene2202::~Scene2202() {
+ // TODO Sound1ChList_sub_407AF0(0x60400854);
+}
+
+void Scene2202::update() {
+ Scene::update();
+
+ if (_leaveScene && !_soundResource2.isPlaying()) {
+ _parentModule->sendMessage(0x1009, 0, this);
+ }
+
+ if (_isSolved && !_soundResource1.isPlaying()) {
+ _soundResource2.play();
+ _isSolved = false;
+ _leaveScene = true;
+ }
+
+ if (_movingTileSprite && !_isTileMoving) {
+ int16 value = getFreeTileIndex(_movingTileIndex);
+ if (value != -1) {
+ setSurfacePriority(_movingTileSprite->getSurface(), 700);
+ _movingTileSprite->sendMessage(0x2001, value, this);
+ _movingTileSprite = NULL;
+ _isTileMoving = true;
+ }
+ }
+
+ if (_doneMovingTileSprite) {
+ setSurfacePriority(_doneMovingTileSprite->getSurface(), _surfacePriority);
+ _doneMovingTileSprite = NULL;
+ if (testIsSolved()) {
+ _soundResource1.play();
+ setGlobalVar(0x404290D5, 1);
+ _isSolved = true;
+ }
+ }
+
+}
+
+uint32 Scene2202::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ Scene::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x0001:
+ // TODO Debug stuff
+ if (param.asPoint().x <= 20 || param.asPoint().x >= 620) {
+ _parentModule->sendMessage(0x1009, 0, this);
+ }
+ break;
+ case 0x000D:
+ // TODO Debug stuff
+ break;
+ case 0x2000:
+ _movingTileIndex = (int16)param.asInteger();
+ _movingTileSprite = (Sprite*)sender;
+ break;
+ case 0x2002:
+ _isTileMoving = false;
+ _doneMovingTileSprite = (Sprite*)sender;
+ if (param.asInteger() >= 0 && param.asInteger() <= 2) {
+ _surfacePriority = 100;
+ } else if (param.asInteger() >= 3 && param.asInteger() <= 5) {
+ _surfacePriority = 300;
+ } else {
+ _surfacePriority = 500;
+ }
+ break;
+ }
+ return 0;
+}
+
+int16 Scene2202::getFreeTileIndex(int16 index) {
+ if (index >= 3 && (int16)getSubVar(0x484498D0, index - 3) == -1) {
+ return index - 3;
+ } else if (index <= 5 && (int16)getSubVar(0x484498D0, index + 3) == -1) {
+ return index + 3;
+ } else if (index != 0 && index != 3 && index != 6 && (int16)getSubVar(0x484498D0, index - 1) == -1) {
+ return index - 1;
+ } else if (index != 2 && index != 5 && index != 8 && (int16)getSubVar(0x484498D0, index + 1) == -1) {
+ return index + 1;
+ } else
+ return -1;
+}
+
+bool Scene2202::testIsSolved() {
+ return
+ getSubVar(0x484498D0, 0) == 0 &&
+ getSubVar(0x484498D0, 2) == 2 &&
+ getSubVar(0x484498D0, 3) == 3 &&
+ getSubVar(0x484498D0, 4) == 4 &&
+ getSubVar(0x484498D0, 5) == 5 &&
+ getSubVar(0x484498D0, 6) == 6 &&
+ getSubVar(0x484498D0, 8) == 7;
+}
+
} // End of namespace Neverhood
diff --git a/engines/neverhood/module2200.h b/engines/neverhood/module2200.h
index 5b14606c4c..d7f41d6f20 100644
--- a/engines/neverhood/module2200.h
+++ b/engines/neverhood/module2200.h
@@ -184,7 +184,6 @@ public:
Class444(NeverhoodEngine *vm, int pointIndex, int spriteIndex);
};
-
class Scene2201 : public Scene {
public:
Scene2201(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -201,6 +200,52 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
+class SsScene2202PuzzleTile : public StaticSprite {
+public:
+ SsScene2202PuzzleTile(NeverhoodEngine *vm, Scene *parentScene, int16 tileIndex, int16 value);
+protected:
+ Scene *_parentScene;
+ int16 _value;
+ int16 _tileIndex;
+ int16 _newX, _newY;
+ int16 _xDelta, _yDelta;
+ int16 _xIncr;
+ int16 _yIncr;
+ int16 _errValue;
+ int16 _counter;
+ int16 _xFlagPos;
+ bool _counterDirection;
+ bool _isMoving;
+ SoundResource _soundResource1;
+ SoundResource _soundResource2;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void suMoveTileX();
+ void suMoveTileY();
+ void moveTile(int16 newTileIndex);
+ void stopMoving();
+};
+
+class Scene2202 : public Scene {
+public:
+ Scene2202(NeverhoodEngine *vm, Module *parentModule, int which);
+ ~Scene2202();
+protected:
+ SoundResource _soundResource1;
+ SoundResource _soundResource2;
+ Sprite *_movingTileSprite;
+ Sprite *_doneMovingTileSprite;
+ bool _isTileMoving;
+ int16 _movingTileIndex;
+ int _surfacePriority;
+ bool _leaveScene;
+ bool _isSolved;
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ int16 getFreeTileIndex(int16 index);
+ bool testIsSolved();
+};
+
} // End of namespace Neverhood
#endif /* NEVERHOOD_MODULE2200_H */