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. --- src/input_system.cpp | 8 +++++ src/message_system.cpp | 82 +++++++++++++++++++++++++++++++++++--------------- src/message_system.h | 26 ++++++++++++---- src/renderer.cpp | 28 ++++++++++++----- src/script_system.cpp | 4 ++- 5 files changed, 110 insertions(+), 38 deletions(-) (limited to 'src') 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