From ec511705ce96d80d4e2a36054769c211448e8ec8 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Thu, 11 Feb 2021 20:47:46 -0500 Subject: Added choice prompts "A presses" are also no longer special values in the lines list, but are rather a field on the MessageLine object. --- res/scripts/common.lua | 8 +++++ res/scripts/script0001.lua | 10 +++++- res/sfx/horizontal_menu.wav | Bin 0 -> 52864 bytes src/input_system.cpp | 8 +++++ src/message_system.cpp | 82 +++++++++++++++++++++++++++++++------------- src/message_system.h | 26 ++++++++++---- src/renderer.cpp | 28 +++++++++++---- src/script_system.cpp | 4 ++- 8 files changed, 127 insertions(+), 39 deletions(-) create mode 100644 res/sfx/horizontal_menu.wav diff --git a/res/scripts/common.lua b/res/scripts/common.lua index b540548..2023e63 100644 --- a/res/scripts/common.lua +++ b/res/scripts/common.lua @@ -36,6 +36,14 @@ function DisplayMessage(msg, name, type) message():displayMessage(msg, name, type) end +function ShowChoice(one, two) + message():showChoice(one, two) +end + +function GetChoiceSelection() + return message():getChoiceSelection() +end + function WaitForEndOfMessage() while (message().isMessageActive) do coroutine.yield() diff --git a/res/scripts/script0001.lua b/res/scripts/script0001.lua index e5078f2..077e809 100644 --- a/res/scripts/script0001.lua +++ b/res/scripts/script0001.lua @@ -3,11 +3,19 @@ function script0001() SetAnimation("boney", "barking") local barkingNoise = LoopSound("barking_at_hallucination.wav") - DisplayMessage("Lucas. It's me, Flint. Your father.\n\fI found Claus. He's here. After three years I've finally found your brother.\n\fLook at me when I'm talking to you, Lucas.\n\fWhen Claus gets home, we won't need you anymore.\nYou're nothing compared to him.", "Flint", SpeakerType.MAN) + DisplayMessage("Lucas. It's me, Flint. Your father.\n\fI found Claus. He's here. After three years I've finally found your brother.\n\fAre you ready to see him again?", "Flint", SpeakerType.MAN) + ShowChoice("Yes", "No") WaitForEndOfMessage() SetAnimation("boney", "crouch") StopSound(barkingNoise) PlaySound("boney_growl.wav") + + if GetChoiceSelection() == 0 then + DisplayMessage("I can hear the tremor in your voice, Lucas.\n\fLies are little games a mouth plays while the person attached withers away slowly.\n\fClaus is coming, whether you like it or not.\nWill you be able to look him in the eye?", "Flint", SpeakerType.MAN) + else + DisplayMessage("Look at me when I'm talking to you, Lucas.\n\fWhen Claus gets home, we won't need you anymore.\nYou're nothing compared to him.", "Flint", SpeakerType.MAN) + end + HideCutsceneBars() end diff --git a/res/sfx/horizontal_menu.wav b/res/sfx/horizontal_menu.wav new file mode 100644 index 0000000..cf9595d Binary files /dev/null and b/res/sfx/horizontal_menu.wav differ diff --git a/src/input_system.cpp b/src/input_system.cpp index 5158724..6ee442a 100644 --- a/src/input_system.cpp +++ b/src/input_system.cpp @@ -73,6 +73,14 @@ void InputSystem::tick(double dt) { game_.getSystem().runScript("default"); } } + } else if (e.key.keysym.sym == SDLK_LEFT) { + if (game_.getSystem().isChoiceActive()) { + game_.getSystem().selectFirstChoice(); + } + } else if (e.key.keysym.sym == SDLK_RIGHT) { + if (game_.getSystem().isChoiceActive()) { + game_.getSystem().selectSecondChoice(); + } } } else if (e.type == SDL_KEYUP && (e.key.keysym.sym == SDLK_LSHIFT || e.key.keysym.sym == SDLK_RSHIFT)) { for (int spriteId : game_.getSprites()) { diff --git a/src/message_system.cpp b/src/message_system.cpp index a200abc..a969427 100644 --- a/src/message_system.cpp +++ b/src/message_system.cpp @@ -39,10 +39,16 @@ void MessageSystem::tick(double dt) { } } - line.charsRevealed += CHARS_TO_REVEAL; - if (line.charsRevealed > line.text.size()) { + if (line.isChoice) { line.charsRevealed = line.text.size(); + choiceSelection_ = 0; + } else { + line.charsRevealed += CHARS_TO_REVEAL; + if (line.charsRevealed > line.text.size()) { + line.charsRevealed = line.text.size(); + } } + advancedChars = true; break; } @@ -50,14 +56,14 @@ void MessageSystem::tick(double dt) { if (!advancedChars) { // If both lines are totally revealed, see if we can scroll up a line. - // This is doable as long as the next line isn't the sentinel value that - // means an A press is required. - if (!lines_.empty() && lines_.front() != "\f") { + // This is doable as long as the last currently visible line doesn't + // have the flag that means an A press is required. + if (!lines_.empty() && !linesToShow_.back().pause) { if (linesToShow_.size() == 2) { linesToShow_.pop_front(); } - linesToShow_.push_back(MessageLine { .text = lines_.front() }); + linesToShow_.push_back(lines_.front()); lines_.pop_front(); } else { showNextArrow_ = true; @@ -113,8 +119,8 @@ void MessageSystem::displayMessage(std::string_view msg, std::string speakerName text.erase(0, 1); shouldAddBlank = false; - if (lines_.empty() || lines_.back() != "\f") { - lines_.push_back("\f"); + if (!lines_.empty()) { + lines_.back().pause = true; } } @@ -139,13 +145,13 @@ void MessageSystem::displayMessage(std::string_view msg, std::string speakerName } if (nextWidth > MESSAGE_TEXT_WIDTH) { - lines_.push_back(curLine); + lines_.push_back({.text = curLine}); curLine = word; curWidth = wordWidth + game_.getFont().getCharacterWidth(' '); if (shouldAddBlank) { shouldAddBlank = false; - lines_.push_back("\f"); + lines_.back().pause = true; } else { shouldAddBlank = true; } @@ -160,52 +166,66 @@ void MessageSystem::displayMessage(std::string_view msg, std::string speakerName firstWord = false; } - lines_.push_back(curLine); + lines_.push_back({.text = curLine}); if (shouldAddBlank) { shouldAddBlank = false; - lines_.push_back("\f"); + lines_.back().pause = true; } else { shouldAddBlank = true; } } - if (lines_.empty() || lines_.back() != "\f") { - lines_.push_back("\f"); + if (!lines_.empty()) { + lines_.back().pause = true; } if (linesToShow_.empty()) { - linesToShow_.push_back(MessageLine { .text = lines_.front() }); + linesToShow_.push_back(lines_.front()); lines_.pop_front(); - if (lines_.front() != "\f") { - linesToShow_.push_back(MessageLine { .text = lines_.front() }); + if (!linesToShow_.back().pause) { + linesToShow_.push_back(lines_.front()); lines_.pop_front(); } } } +void MessageSystem::showChoice(std::string choice1, std::string choice2) { + MessageLine line; + line.text = std::string(8, ' ') + choice1 + std::string(11, ' ') + choice2; + line.pause = true; + line.isChoice = true; + line.choicePos[0] = 8; + line.choicePos[1] = 8 + 11 + choice1.size(); + + lines_.push_back(line); +} + void MessageSystem::advanceText() { + // Cutscene must be active. if (barsState_ != BarsState::Open) { return; } + if (linesToShow_.empty()) { + return; + } + // We can only advance if all visible lines are fully revealed. for (const MessageLine& line : linesToShow_) { if (line.charsRevealed != line.text.size()) { return; } } - if (lines_.empty()) { - linesToShow_.clear(); + // If the last visible line doesn't have a pause, then the cutscene + // will automatically progress without us doing anything. + if (!linesToShow_.back().pause) { return; } - if (lines_.front() != "\f") { - return; - } - - lines_.pop_front(); + // Clear the current pause. + linesToShow_.back().pause = false; showNextArrow_ = false; if (lines_.empty()) { @@ -215,6 +235,20 @@ void MessageSystem::advanceText() { } } +void MessageSystem::selectFirstChoice() { + if (isChoiceActive() && choiceSelection_ != 0) { + choiceSelection_ = 0; + game_.getMixer().playSound("../res/sfx/horizontal_menu.wav"); + } +} + +void MessageSystem::selectSecondChoice() { + if (isChoiceActive() && choiceSelection_ != 1) { + choiceSelection_ = 1; + game_.getMixer().playSound("../res/sfx/horizontal_menu.wav"); + } +} + double MessageSystem::getCutsceneBarsProgress() const { switch (barsState_) { case BarsState::Closed: return 0.0; diff --git a/src/message_system.h b/src/message_system.h index 155f9c6..ea27f14 100644 --- a/src/message_system.h +++ b/src/message_system.h @@ -18,6 +18,14 @@ enum class SpeakerType { Nonhuman }; +struct MessageLine { + std::string text; + int charsRevealed = 0; + bool pause = false; + bool isChoice = false; + int choicePos[2] = {-1, -1}; +}; + class MessageSystem : public System { public: @@ -41,17 +49,18 @@ public: std::string speakerName = "", SpeakerType speakerType = SpeakerType::None); + void showChoice(std::string choice1, std::string choice2); + void advanceText(); + void selectFirstChoice(); + + void selectSecondChoice(); + // Info double getCutsceneBarsProgress() const; - struct MessageLine { - std::string text; - int charsRevealed = 0; - }; - const std::list& getLines() const { return linesToShow_; } bool isMessageActive() const { return !linesToShow_.empty(); } @@ -62,6 +71,10 @@ public: int getNextArrowBob() const { return nextArrowBobPos_; } + bool isChoiceActive() const { return isMessageActive() && linesToShow_.back().isChoice; } + + int getChoiceSelection() const { return choiceSelection_; } + private: enum class BarsState { @@ -77,13 +90,14 @@ private: double length_ = 1000.0/8; SpeakerType speaker_ = SpeakerType::None; std::string speakerName_; - std::list lines_; + std::list lines_; std::list linesToShow_; Timer textAdvTimer_ { 15 }; bool showNextArrow_ = false; int nextArrowBobPos_ = 0; bool nextArrowBobDown_ = true; Timer nextArrowBobTimer_ { 125 }; + int choiceSelection_ = 0; }; #endif /* end of include guard: MESSAGE_SYSTEM_H_DE10D011 */ diff --git a/src/renderer.cpp b/src/renderer.cpp index db5daed..0c70ef5 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -194,7 +194,7 @@ void Renderer::render(Game& game) { } int lineIndex = 0; - for (const MessageSystem::MessageLine& line : game.getSystem().getLines()) { + for (const MessageLine& line : game.getSystem().getLines()) { if (messageLines_[lineIndex].line != line.text) { renderMessageLine(messageLines_[lineIndex], line.text, game); } @@ -223,13 +223,27 @@ void Renderer::render(Game& game) { advMsgArrowTex_ = loadImageFromFile("../res/advance_text_arrow.png"); } - SDL_Rect destRect { - 216, - 138 + game.getSystem().getNextArrowBob(), - 16, - 16 }; + if (game.getSystem().isChoiceActive()) { + int selection = game.getSystem().getChoiceSelection(); + int charIndex = game.getSystem().getLines().back().choicePos[selection]; + int baseX = messageLines_[1].charIndexToWidth[charIndex]; - SDL_RenderCopy(ren_.get(), textures_.at(advMsgArrowTex_).get(), nullptr, &destRect); + SDL_Rect destRect { + 18 + baseX - game.getSystem().getNextArrowBob()-16+3, + 141, + 16, + 16}; + + SDL_RenderCopyEx(ren_.get(), textures_.at(advMsgArrowTex_).get(), nullptr, &destRect, -90, nullptr, SDL_FLIP_NONE); + } else { + SDL_Rect destRect { + 216, + 138 + game.getSystem().getNextArrowBob(), + 16, + 16 }; + + SDL_RenderCopy(ren_.get(), textures_.at(advMsgArrowTex_).get(), nullptr, &destRect); + } } } } diff --git a/src/script_system.cpp b/src/script_system.cpp index 0fa0c1b..21d4090 100644 --- a/src/script_system.cpp +++ b/src/script_system.cpp @@ -21,8 +21,10 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { engine_.new_usertype( "message", "displayMessage", &MessageSystem::displayMessage, + "showChoice", &MessageSystem::showChoice, "hideCutsceneBars", &MessageSystem::hideCutsceneBars, - "isMessageActive", sol::property(&MessageSystem::isMessageActive)); + "isMessageActive", sol::property(&MessageSystem::isMessageActive), + "getChoiceSelection", &MessageSystem::getChoiceSelection); engine_.new_usertype( "animation", -- cgit 1.4.1