diff options
author | Paul Gilbert | 2015-08-02 17:40:53 -0400 |
---|---|---|
committer | Paul Gilbert | 2015-08-02 17:40:53 -0400 |
commit | fd849ee58c8fdc3856bb199a0e97777581e60f7e (patch) | |
tree | f6f3cb70394e77c90434fca7a04daee4e4dafde4 | |
parent | 1ae250f53b3dbd09ebf71e9f6eedc1e8d28d2e28 (diff) | |
download | scummvm-rg350-fd849ee58c8fdc3856bb199a0e97777581e60f7e.tar.gz scummvm-rg350-fd849ee58c8fdc3856bb199a0e97777581e60f7e.tar.bz2 scummvm-rg350-fd849ee58c8fdc3856bb199a0e97777581e60f7e.zip |
SHERLOCK: RT: Refactoring and cleanup for Foolscap puzzle
-rw-r--r-- | engines/sherlock/talk.cpp | 1 | ||||
-rw-r--r-- | engines/sherlock/tattoo/widget_hangman.cpp | 394 | ||||
-rw-r--r-- | engines/sherlock/tattoo/widget_hangman.h | 40 | ||||
-rw-r--r-- | engines/sherlock/user_interface.h | 3 |
4 files changed, 254 insertions, 184 deletions
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp index e901280ee9..eddc508c65 100644 --- a/engines/sherlock/talk.cpp +++ b/engines/sherlock/talk.cpp @@ -928,6 +928,7 @@ int Talk::waitForMore(int delay) { events._released = true; } else { // See if there's been a button press + events.pollEventsAndWait(); events.setButtonState(); if (events.kbHit()) { diff --git a/engines/sherlock/tattoo/widget_hangman.cpp b/engines/sherlock/tattoo/widget_hangman.cpp index 28410636f3..f41c5e43f0 100644 --- a/engines/sherlock/tattoo/widget_hangman.cpp +++ b/engines/sherlock/tattoo/widget_hangman.cpp @@ -21,237 +21,271 @@ */ #include "sherlock/tattoo/widget_hangman.h" +#include "sherlock/tattoo/tattoo_fixed_text.h" +#include "sherlock/tattoo/tattoo_scene.h" +#include "sherlock/tattoo/tattoo_user_interface.h" #include "sherlock/tattoo/tattoo.h" namespace Sherlock { namespace Tattoo { +WidgetHangman::WidgetHangman(TattooEngine *vm) : WidgetBase(vm) { + for (int idx = 0; idx < 3; ++idx) + Common::fill(&_answers[idx][0], &_answers[idx][10], 0); + _images = nullptr; + _numWide = 0; + _spacing = 0; + _blinkFlag = false; + _blinkCounter = 0; + _lineNum = _charNum = 0; + _solved = false; +} + +WidgetHangman::~WidgetHangman() { + delete _images; +} + void WidgetHangman::show() { - Events &events = *_vm->_events; - Scene &scene = *_vm->_scene; Screen &screen = *_vm->_screen; - Talk &talk = *_vm->_talk; - char answers[3][10]; - Common::Point lines[3]; - const char *solutions[3]; - int numWide, spacing; - ImageFile *paper; - Common::Point cursorPos; - byte cursorColor = 254; - bool solved = false; - bool done = false; - bool flag = false; - size_t i = 0; + TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui; switch (_vm->getLanguage()) { case Common::FR_FRA: - lines[0] = Common::Point(34, 210); - lines[1] = Common::Point(72, 242); - lines[2] = Common::Point(34, 276); - numWide = 8; - spacing = 19; - paper = new ImageFile("paperf.vgs"); + _lines[0] = Common::Point(34, 210); + _lines[1] = Common::Point(72, 242); + _lines[2] = Common::Point(34, 276); + _numWide = 8; + _spacing = 19; + _images = new ImageFile("paperf.vgs"); break; case Common::DE_DEU: - lines[0] = Common::Point(44, 73); - lines[1] = Common::Point(56, 169); - lines[2] = Common::Point(47, 256); - numWide = 7; - spacing = 19; - paper = new ImageFile("paperg.vgs"); + _lines[0] = Common::Point(44, 73); + _lines[1] = Common::Point(56, 169); + _lines[2] = Common::Point(47, 256); + _numWide = 7; + _spacing = 19; + _images = new ImageFile("paperg.vgs"); break; default: // English - lines[0] = Common::Point(65, 84); - lines[1] = Common::Point(65, 159); - lines[2] = Common::Point(75, 234); - numWide = 5; - spacing = 20; - paper = new ImageFile("paper.vgs"); + _lines[0] = Common::Point(65, 84); + _lines[1] = Common::Point(65, 159); + _lines[2] = Common::Point(75, 234); + _numWide = 5; + _spacing = 20; + _images = new ImageFile("paper.vgs"); break; } - - ImageFrame &paperFrame = (*paper)[0]; - Common::Rect paperBounds(paperFrame._width, paperFrame._height); - paperBounds.moveTo((screen.w() - paperFrame._width) / 2, (screen.h() - paperFrame._height) / 2); - for (int line = 0; line<3; ++line) { - lines[line].x += paperBounds.left; - lines[line].y += paperBounds.top; - - for (i = 0; i <= (size_t)numWide; ++i) - answers[line][i] = 0; - } - - screen._backBuffer1.blitFrom(paperFrame, Common::Point(paperBounds.left + screen._currentScroll.x, 0)); + _solved = false; + _blinkFlag = false; + _blinkCounter = 0; + _lineNum = _charNum = 0; + _cursorPos = Common::Point(_lines[0].x + 8 - screen.widestChar() / 2, _lines[0].y - screen.fontHeight() - 2); + + // Set up window bounds + ImageFrame &paperFrame = (*_images)[0]; + _bounds = Common::Rect(paperFrame._width, paperFrame._height); + _bounds.moveTo(screen._currentScroll.x + (SHERLOCK_SCREEN_WIDTH - paperFrame._width) / 2, + (SHERLOCK_SCREEN_HEIGHT - paperFrame._height) / 2); + + // Clear answer data and set correct solution strings + for (int idx = 0; idx < 3; ++idx) + Common::fill(&_answers[idx][0], &_answers[idx][10], 0); + _solutions[0] = FIXED(Apply); + _solutions[1] = FIXED(Water); + _solutions[2] = FIXED(Heat); + + // Set up the window background + _surface.create(_bounds.width(), _bounds.height()); + _surface.blitFrom(paperFrame, Common::Point(0, 0)); // If they have already solved the puzzle, put the answer on the graphic if (_vm->readFlags(299)) { + Common::Point cursorPos; for (int line = 0; line < 3; ++line) { - cursorPos.y = lines[line].y - screen.fontHeight() - 2; + cursorPos.y = _lines[_lineNum].y - screen.fontHeight() - 2; - for (i = 0; i < strlen(solutions[line]); ++i) { - cursorPos.x = lines[line].x + 8 - screen.widestChar() / 2 + i * spacing; - screen.gPrint(Common::Point(cursorPos.x + screen.widestChar() / 2 - - screen.charWidth(solutions[line][i]) / 2, cursorPos.y), 0, "%c", solutions[line][i]); + for (uint idx = 0; idx < strlen(_solutions[_lineNum]); ++idx) { + cursorPos.x = _lines[_lineNum].x + 8 - screen.widestChar() / 2 + idx * _spacing; + screen.gPrint(Common::Point(cursorPos.x + screen.widestChar() / 2 - + screen.charWidth(_solutions[_lineNum][idx]) / 2, cursorPos.y), 0, "%c", _solutions[_lineNum][idx]); } } } - screen.slamRect(paperBounds); - cursorPos = Common::Point(lines[0].x + 8 - screen.widestChar() / 2, lines[0].y - screen.fontHeight() - 2); - int line = 0; + // Show the window + summonWindow(); + ui._menuMode = FOOLSCAP_MODE; +} + +void WidgetHangman::handleEvents() { + Events &events = *_vm->_events; + Screen &screen = *_vm->_screen; + TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui; + Common::Point mousePos = events.mousePos(); + byte cursorColor = 254; + + if (events._firstPress && !_bounds.contains(mousePos)) + _outsideMenu = true; // If they have not solved the puzzle, let them solve it here if (!_vm->readFlags(299)) { - do { - while (!events.kbHit()) { - // See if a key or a mouse button is pressed - events.pollEventsAndWait(); - events.setButtonState(); - - flag = !flag; - if (flag) { - screen._backBuffer1.fillRect(Common::Rect(cursorPos.x + screen._currentScroll.x, cursorPos.y, - cursorPos.x + screen.widestChar() + screen._currentScroll.x - 1, cursorPos.y + screen.fontHeight() - 1), cursorColor); - if (answers[line][i]) - screen.gPrint(Common::Point(cursorPos.x + screen.widestChar() / 2 - screen.charWidth(answers[line][i]) / 2, - cursorPos.y), 0, "%c", answers[line][i]); - screen.slamArea(cursorPos.x, cursorPos.y, screen.widestChar(), screen.fontHeight()); + if (!ui._keyState.keycode) { + if (--_blinkCounter < 0) { + _blinkCounter = 3; + _blinkFlag = !_blinkFlag; + + if (_blinkFlag) { + // Draw the caret + _surface.fillRect(Common::Rect(_cursorPos.x, _cursorPos.y, _cursorPos.x + screen.widestChar() - 1, + _cursorPos.y + screen.fontHeight() - 1), cursorColor); + + if (_answers[_lineNum][_charNum]) { + Common::String str = Common::String::format("%c", _answers[_lineNum][_charNum]); + _surface.writeString(str, Common::Point(_cursorPos.x + screen.widestChar() / 2 + - screen.charWidth(_answers[_lineNum][_charNum]) / 2, _cursorPos.y), 0); + } } else { - screen.setDisplayBounds(Common::Rect(cursorPos.x + screen._currentScroll.x, cursorPos.y, - cursorPos.x + screen.widestChar() + screen._currentScroll.x, cursorPos.y + screen.fontHeight())); - screen._backBuffer->blitFrom(paperFrame, Common::Point(paperBounds.left + screen._currentScroll.x, paperBounds.top)); - screen.resetDisplayBounds(); - - if (answers[line][i]) - screen.gPrint(Common::Point(cursorPos.x + screen.widestChar() / 2 - screen.charWidth(answers[line][i]) / 2, - cursorPos.y), 0, "%c", answers[line][i]); - screen.slamArea(cursorPos.x, cursorPos.y, screen.widestChar(), screen.fontHeight()); + // Restore background + restoreChar(); + + // Draw the character at that position if there is one + if (_answers[_lineNum][_charNum]) { + Common::String str = Common::String::format("%c", _answers[_lineNum][_charNum]); + _surface.writeString(str, Common::Point(_cursorPos.x + screen.widestChar() / 2 + - screen.charWidth(_answers[_lineNum][_charNum]) / 2, _cursorPos.y), 0); + } } - - if (!events.kbHit()) - events.wait(2); } + } else { + // Handle keyboard events + handleKeyboardEvents(); + } + } - if (events.kbHit()) { - Common::KeyState keyState = events.getKey(); + if ((events._released || events._rightReleased) && _outsideMenu && !_bounds.contains(mousePos)) { + // Clicked outside window to close it + events.clearEvents(); + close(); + } +} - if (((toupper(keyState.ascii) >= 'A') && (toupper(keyState.ascii) <= 'Z')) || - ((keyState.ascii >= 128) && ((keyState.ascii <= 168) || (keyState.ascii == 225)))) { - answers[line][i] = keyState.ascii; - keyState.keycode = Common::KEYCODE_RIGHT; - } +void WidgetHangman::handleKeyboardEvents() { + Screen &screen = *_vm->_screen; + TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui; + Common::KeyState keyState = ui._keyState; + + if (((toupper(keyState.ascii) >= 'A') && (toupper(keyState.ascii) <= 'Z')) || + ((keyState.ascii >= 128) && ((keyState.ascii <= 168) || (keyState.ascii == 225)))) { + // Visible key pressed, set it and set the keycode to move the caret to the right + _answers[_lineNum][_charNum] = keyState.ascii; + keyState.keycode = Common::KEYCODE_RIGHT; + } - screen.setDisplayBounds(Common::Rect(cursorPos.x + screen._currentScroll.x, cursorPos.y, - cursorPos.x + screen.widestChar() + screen._currentScroll.x, cursorPos.y + screen.fontHeight())); - screen._backBuffer->blitFrom(paperFrame, Common::Point(paperBounds.left + screen._currentScroll.x, paperBounds.top)); - screen.resetDisplayBounds(); - - if (answers[line][i]) - screen.gPrint(Common::Point(cursorPos.x + screen.widestChar() / 2 - screen.charWidth(answers[line][i]) / 2, - cursorPos.y), 0, "%c", answers[line][i]); - screen.slamArea(cursorPos.x, cursorPos.y, screen.widestChar(), screen.fontHeight()); - - switch (keyState.keycode) { - case Common::KEYCODE_ESCAPE: - done = true; - break; - - case Common::KEYCODE_UP: - if (line) { - line--; - if (i >= strlen(solutions[line])) - i = strlen(solutions[line]) - 1; - } - break; + // Restore background + restoreChar(); - case Common::KEYCODE_DOWN: - if (line < 2) { - ++line; - if (i >= strlen(solutions[line])) - i = strlen(solutions[line]) - 1; - } - break; - - case Common::KEYCODE_BACKSPACE: - case Common::KEYCODE_LEFT: - if (i) - --i; - else if (line) { - --line; - - i = strlen(solutions[line]) - 1; - } + if (_answers[_lineNum][_charNum]) { + Common::String str = Common::String::format("%c", _answers[_lineNum][_charNum]); + _surface.writeString(str, Common::Point(_cursorPos.x + screen.widestChar() / 2 + - screen.charWidth(_answers[_lineNum][_charNum]) / 2, _cursorPos.y), 0); + } - if (keyState.keycode == Common::KEYCODE_BACKSPACE) - answers[line][i] = ' '; - break; + switch (keyState.keycode) { + case Common::KEYCODE_ESCAPE: + close(); + break; - case Common::KEYCODE_RIGHT: - if (i < strlen(solutions[line]) - 1) - i++; - else if (line < 2) { - ++line; - i = 0; - } - break; + case Common::KEYCODE_UP: + if (_lineNum) { + --_lineNum; + if (_charNum >= (int)strlen(_solutions[_lineNum])) + _charNum = (int)strlen(_solutions[_lineNum]) - 1; + } + break; - case Common::KEYCODE_DELETE: - answers[line][i] = ' '; - break; + case Common::KEYCODE_DOWN: + if (_lineNum < 2) { + ++_lineNum; + if (_charNum >= (int)strlen(_solutions[_lineNum])) + _charNum = (int)strlen(_solutions[_lineNum]) - 1; + } + break; - default: - break; - } - } + case Common::KEYCODE_BACKSPACE: + case Common::KEYCODE_LEFT: + if (_charNum) + --_charNum; + else if (_lineNum) { + --_lineNum; - cursorPos.x = lines[line].x + 8 - screen.widestChar() / 2 + i * spacing; - cursorPos.y = lines[line].y - screen.fontHeight() - 2; + _charNum = strlen(_solutions[_lineNum]) - 1; + } - // See if all of their anwers are correct - if (!scumm_stricmp(answers[0], solutions[0]) && !scumm_stricmp(answers[1], solutions[1]) && - !scumm_stricmp(answers[2], solutions[2])) { - done = true; - solved = true; - } - } while (!done && !_vm->shouldQuit()); - } else { - // They have already solved the puzzle, so just display the solution and wait for a mouse or key click - do { - events.pollEventsAndWait(); - events.setButtonState(); - - if ((events.kbHit()) || (events._released) || (events._rightReleased)) { - done = true; - events.clearEvents(); - } - } while (!done && !_vm->shouldQuit()); + if (keyState.keycode == Common::KEYCODE_BACKSPACE) + _answers[_lineNum][_charNum] = ' '; + break; + + case Common::KEYCODE_RIGHT: + if (_charNum < (int)strlen(_solutions[_lineNum]) - 1) + ++_charNum; + else if (_lineNum < 2) { + ++_lineNum; + _charNum = 0; + } + break; + + case Common::KEYCODE_DELETE: + _answers[_lineNum][_charNum] = ' '; + break; + + default: + break; + } + + _cursorPos.x = _lines[_lineNum].x + 8 - screen.widestChar() / 2 + _charNum * _spacing; + _cursorPos.y = _lines[_lineNum].y - screen.fontHeight() - 2; + + // See if all of their anwers are correct + if (!scumm_stricmp(_answers[0], _solutions[0]) && !scumm_stricmp(_answers[1], _solutions[1]) + && !scumm_stricmp(_answers[2], _solutions[2])) { + _solved; + close(); } +} - delete paper; - screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(paperBounds.left + screen._currentScroll.x, paperBounds.top), - Common::Rect(paperBounds.left + screen._currentScroll.x, paperBounds.top, - paperBounds.right + screen._currentScroll.x, paperBounds.bottom)); - scene.doBgAnim(); +void WidgetHangman::restoreChar() { + Screen &screen = *_vm->_screen; + ImageFrame &bgFrame = (*_images)[0]; + _surface.blitFrom(bgFrame, _cursorPos, Common::Rect(_cursorPos.x, _cursorPos.y, + _cursorPos.x + screen.widestChar(), _cursorPos.y + screen.fontHeight())); +} - screen.slamArea(paperBounds.left + screen._currentScroll.x, paperBounds.top, - paperBounds.width(), paperBounds.height()); +void WidgetHangman::close() { + TattooScene &scene = *(TattooScene *)_vm->_scene; + Talk &talk = *_vm->_talk; + TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui; + delete _images; + _images = nullptr; + + // Close the window + banishWindow(); + ui._menuMode = scene._labTableScene ? LAB_MODE : STD_MODE; // Don't call the talk files if the puzzle has already been solved - if (_vm->readFlags(299)) - return; - - // If they solved the puzzle correctly, set the solved flag and run the appropriate talk scripts - if (solved) { - talk.talkTo("SLVE12S.TLK"); - talk.talkTo("WATS12X.TLK"); - _vm->setFlags(299); - } else { - talk.talkTo("HOLM12X.TLK"); + if (!_vm->readFlags(299)) { + // Run the appropriate script depending on whether or not they solved the puzzle correctly + if (_solved) { + talk.talkTo("SLVE12S.TLK"); + talk.talkTo("WATS12X.TLK"); + _vm->setFlags(299); + } else { + talk.talkTo("HOLM12X.TLK"); + } } } diff --git a/engines/sherlock/tattoo/widget_hangman.h b/engines/sherlock/tattoo/widget_hangman.h index daa598720a..c653f93c29 100644 --- a/engines/sherlock/tattoo/widget_hangman.h +++ b/engines/sherlock/tattoo/widget_hangman.h @@ -23,22 +23,56 @@ #ifndef SHERLOCK_TATTOO_HANGMAN_H #define SHERLOCK_TATTOO_HANGMAN_H +#include "sherlock/tattoo/widget_base.h" +#include "sherlock/image_file.h" + namespace Sherlock { namespace Tattoo { class TattooEngine; -class WidgetHangman { +class WidgetHangman: public WidgetBase { private: - TattooEngine *_vm; + ImageFile *_images; + Common::Point _lines[3]; + char _answers[3][10]; + const char *_solutions[3]; + int _numWide; + int _spacing; + Common::Point _cursorPos; + int _blinkCounter; + bool _blinkFlag; + int _lineNum, _charNum; + bool _solved; + + /** + * Handle keyboard events + */ + void handleKeyboardEvents(); + + /** + * Restore the background for the current line/horiz position + */ + void restoreChar(); public: - WidgetHangman(TattooEngine *vm) : _vm(vm) {} + WidgetHangman(TattooEngine *vm); + virtual ~WidgetHangman(); /** * Show the hangman puzzle */ void show(); + + /** + * Close the window + */ + void close(); + + /** + * Handle events whilst the widget is on-screen + */ + virtual void handleEvents(); }; } // End of namespace Tattoo diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h index b6734fb63a..799912ff2e 100644 --- a/engines/sherlock/user_interface.h +++ b/engines/sherlock/user_interface.h @@ -55,7 +55,8 @@ enum MenuMode { MESSAGE_MODE = 21, VERB_MODE = 22, OPTION_MODE = 23, - QUIT_MODE = 24 + QUIT_MODE = 24, + FOOLSCAP_MODE = 25 }; class UserInterface { |