diff options
| author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2021-02-11 20:47:46 -0500 |
|---|---|---|
| committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2021-02-11 20:47:46 -0500 |
| commit | ec511705ce96d80d4e2a36054769c211448e8ec8 (patch) | |
| tree | e0a70671430a84472024d54b934df3248924ec4d /src | |
| parent | d9be54853910c2086013846661e0dc4a8603c20e (diff) | |
| download | tanetane-ec511705ce96d80d4e2a36054769c211448e8ec8.tar.gz tanetane-ec511705ce96d80d4e2a36054769c211448e8ec8.tar.bz2 tanetane-ec511705ce96d80d4e2a36054769c211448e8ec8.zip | |
Added choice prompts
"A presses" are also no longer special values in the lines list, but are rather a field on the MessageLine object.
Diffstat (limited to 'src')
| -rw-r--r-- | src/input_system.cpp | 8 | ||||
| -rw-r--r-- | src/message_system.cpp | 82 | ||||
| -rw-r--r-- | src/message_system.h | 26 | ||||
| -rw-r--r-- | src/renderer.cpp | 28 | ||||
| -rw-r--r-- | src/script_system.cpp | 4 |
5 files changed, 110 insertions, 38 deletions
| 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) { | |||
| 73 | game_.getSystem<ScriptSystem>().runScript("default"); | 73 | game_.getSystem<ScriptSystem>().runScript("default"); |
| 74 | } | 74 | } |
| 75 | } | 75 | } |
| 76 | } else if (e.key.keysym.sym == SDLK_LEFT) { | ||
| 77 | if (game_.getSystem<MessageSystem>().isChoiceActive()) { | ||
| 78 | game_.getSystem<MessageSystem>().selectFirstChoice(); | ||
| 79 | } | ||
| 80 | } else if (e.key.keysym.sym == SDLK_RIGHT) { | ||
| 81 | if (game_.getSystem<MessageSystem>().isChoiceActive()) { | ||
| 82 | game_.getSystem<MessageSystem>().selectSecondChoice(); | ||
| 83 | } | ||
| 76 | } | 84 | } |
| 77 | } else if (e.type == SDL_KEYUP && (e.key.keysym.sym == SDLK_LSHIFT || e.key.keysym.sym == SDLK_RSHIFT)) { | 85 | } else if (e.type == SDL_KEYUP && (e.key.keysym.sym == SDLK_LSHIFT || e.key.keysym.sym == SDLK_RSHIFT)) { |
| 78 | for (int spriteId : game_.getSprites()) { | 86 | 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) { | |||
| 39 | } | 39 | } |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | line.charsRevealed += CHARS_TO_REVEAL; | 42 | if (line.isChoice) { |
| 43 | if (line.charsRevealed > line.text.size()) { | ||
| 44 | line.charsRevealed = line.text.size(); | 43 | line.charsRevealed = line.text.size(); |
| 44 | choiceSelection_ = 0; | ||
| 45 | } else { | ||
| 46 | line.charsRevealed += CHARS_TO_REVEAL; | ||
| 47 | if (line.charsRevealed > line.text.size()) { | ||
| 48 | line.charsRevealed = line.text.size(); | ||
| 49 | } | ||
| 45 | } | 50 | } |
| 51 | |||
| 46 | advancedChars = true; | 52 | advancedChars = true; |
| 47 | break; | 53 | break; |
| 48 | } | 54 | } |
| @@ -50,14 +56,14 @@ void MessageSystem::tick(double dt) { | |||
| 50 | 56 | ||
| 51 | if (!advancedChars) { | 57 | if (!advancedChars) { |
| 52 | // If both lines are totally revealed, see if we can scroll up a line. | 58 | // If both lines are totally revealed, see if we can scroll up a line. |
| 53 | // This is doable as long as the next line isn't the sentinel value that | 59 | // This is doable as long as the last currently visible line doesn't |
| 54 | // means an A press is required. | 60 | // have the flag that means an A press is required. |
| 55 | if (!lines_.empty() && lines_.front() != "\f") { | 61 | if (!lines_.empty() && !linesToShow_.back().pause) { |
| 56 | if (linesToShow_.size() == 2) { | 62 | if (linesToShow_.size() == 2) { |
| 57 | linesToShow_.pop_front(); | 63 | linesToShow_.pop_front(); |
| 58 | } | 64 | } |
| 59 | 65 | ||
| 60 | linesToShow_.push_back(MessageLine { .text = lines_.front() }); | 66 | linesToShow_.push_back(lines_.front()); |
| 61 | lines_.pop_front(); | 67 | lines_.pop_front(); |
| 62 | } else { | 68 | } else { |
| 63 | showNextArrow_ = true; | 69 | showNextArrow_ = true; |
| @@ -113,8 +119,8 @@ void MessageSystem::displayMessage(std::string_view msg, std::string speakerName | |||
| 113 | text.erase(0, 1); | 119 | text.erase(0, 1); |
| 114 | shouldAddBlank = false; | 120 | shouldAddBlank = false; |
| 115 | 121 | ||
| 116 | if (lines_.empty() || lines_.back() != "\f") { | 122 | if (!lines_.empty()) { |
| 117 | lines_.push_back("\f"); | 123 | lines_.back().pause = true; |
| 118 | } | 124 | } |
| 119 | } | 125 | } |
| 120 | 126 | ||
| @@ -139,13 +145,13 @@ void MessageSystem::displayMessage(std::string_view msg, std::string speakerName | |||
| 139 | } | 145 | } |
| 140 | 146 | ||
| 141 | if (nextWidth > MESSAGE_TEXT_WIDTH) { | 147 | if (nextWidth > MESSAGE_TEXT_WIDTH) { |
| 142 | lines_.push_back(curLine); | 148 | lines_.push_back({.text = curLine}); |
| 143 | curLine = word; | 149 | curLine = word; |
| 144 | curWidth = wordWidth + game_.getFont().getCharacterWidth(' '); | 150 | curWidth = wordWidth + game_.getFont().getCharacterWidth(' '); |
| 145 | 151 | ||
| 146 | if (shouldAddBlank) { | 152 | if (shouldAddBlank) { |
| 147 | shouldAddBlank = false; | 153 | shouldAddBlank = false; |
| 148 | lines_.push_back("\f"); | 154 | lines_.back().pause = true; |
| 149 | } else { | 155 | } else { |
| 150 | shouldAddBlank = true; | 156 | shouldAddBlank = true; |
| 151 | } | 157 | } |
| @@ -160,52 +166,66 @@ void MessageSystem::displayMessage(std::string_view msg, std::string speakerName | |||
| 160 | firstWord = false; | 166 | firstWord = false; |
| 161 | } | 167 | } |
| 162 | 168 | ||
| 163 | lines_.push_back(curLine); | 169 | lines_.push_back({.text = curLine}); |
| 164 | 170 | ||
| 165 | if (shouldAddBlank) { | 171 | if (shouldAddBlank) { |
| 166 | shouldAddBlank = false; | 172 | shouldAddBlank = false; |
| 167 | lines_.push_back("\f"); | 173 | lines_.back().pause = true; |
| 168 | } else { | 174 | } else { |
| 169 | shouldAddBlank = true; | 175 | shouldAddBlank = true; |
| 170 | } | 176 | } |
| 171 | } | 177 | } |
| 172 | 178 | ||
| 173 | if (lines_.empty() || lines_.back() != "\f") { | 179 | if (!lines_.empty()) { |
| 174 | lines_.push_back("\f"); | 180 | lines_.back().pause = true; |
| 175 | } | 181 | } |
| 176 | 182 | ||
| 177 | if (linesToShow_.empty()) { | 183 | if (linesToShow_.empty()) { |
| 178 | linesToShow_.push_back(MessageLine { .text = lines_.front() }); | 184 | linesToShow_.push_back(lines_.front()); |
| 179 | lines_.pop_front(); | 185 | lines_.pop_front(); |
| 180 | 186 | ||
| 181 | if (lines_.front() != "\f") { | 187 | if (!linesToShow_.back().pause) { |
| 182 | linesToShow_.push_back(MessageLine { .text = lines_.front() }); | 188 | linesToShow_.push_back(lines_.front()); |
| 183 | lines_.pop_front(); | 189 | lines_.pop_front(); |
| 184 | } | 190 | } |
| 185 | } | 191 | } |
| 186 | } | 192 | } |
| 187 | 193 | ||
| 194 | void MessageSystem::showChoice(std::string choice1, std::string choice2) { | ||
| 195 | MessageLine line; | ||
| 196 | line.text = std::string(8, ' ') + choice1 + std::string(11, ' ') + choice2; | ||
| 197 | line.pause = true; | ||
| 198 | line.isChoice = true; | ||
| 199 | line.choicePos[0] = 8; | ||
| 200 | line.choicePos[1] = 8 + 11 + choice1.size(); | ||
| 201 | |||
| 202 | lines_.push_back(line); | ||
| 203 | } | ||
| 204 | |||
| 188 | void MessageSystem::advanceText() { | 205 | void MessageSystem::advanceText() { |
| 206 | // Cutscene must be active. | ||
| 189 | if (barsState_ != BarsState::Open) { | 207 | if (barsState_ != BarsState::Open) { |
| 190 | return; | 208 | return; |
| 191 | } | 209 | } |
| 210 | if (linesToShow_.empty()) { | ||
| 211 | return; | ||
| 212 | } | ||
| 192 | 213 | ||
| 214 | // We can only advance if all visible lines are fully revealed. | ||
| 193 | for (const MessageLine& line : linesToShow_) { | 215 | for (const MessageLine& line : linesToShow_) { |
| 194 | if (line.charsRevealed != line.text.size()) { | 216 | if (line.charsRevealed != line.text.size()) { |
| 195 | return; | 217 | return; |
| 196 | } | 218 | } |
| 197 | } | 219 | } |
| 198 | 220 | ||
| 199 | if (lines_.empty()) { | 221 | // If the last visible line doesn't have a pause, then the cutscene |
| 200 | linesToShow_.clear(); | 222 | // will automatically progress without us doing anything. |
| 223 | if (!linesToShow_.back().pause) { | ||
| 201 | return; | 224 | return; |
| 202 | } | 225 | } |
| 203 | 226 | ||
| 204 | if (lines_.front() != "\f") { | 227 | // Clear the current pause. |
| 205 | return; | 228 | linesToShow_.back().pause = false; |
| 206 | } | ||
| 207 | |||
| 208 | lines_.pop_front(); | ||
| 209 | showNextArrow_ = false; | 229 | showNextArrow_ = false; |
| 210 | 230 | ||
| 211 | if (lines_.empty()) { | 231 | if (lines_.empty()) { |
| @@ -215,6 +235,20 @@ void MessageSystem::advanceText() { | |||
| 215 | } | 235 | } |
| 216 | } | 236 | } |
| 217 | 237 | ||
| 238 | void MessageSystem::selectFirstChoice() { | ||
| 239 | if (isChoiceActive() && choiceSelection_ != 0) { | ||
| 240 | choiceSelection_ = 0; | ||
| 241 | game_.getMixer().playSound("../res/sfx/horizontal_menu.wav"); | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | void MessageSystem::selectSecondChoice() { | ||
| 246 | if (isChoiceActive() && choiceSelection_ != 1) { | ||
| 247 | choiceSelection_ = 1; | ||
| 248 | game_.getMixer().playSound("../res/sfx/horizontal_menu.wav"); | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 218 | double MessageSystem::getCutsceneBarsProgress() const { | 252 | double MessageSystem::getCutsceneBarsProgress() const { |
| 219 | switch (barsState_) { | 253 | switch (barsState_) { |
| 220 | case BarsState::Closed: return 0.0; | 254 | 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 { | |||
| 18 | Nonhuman | 18 | Nonhuman |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | struct MessageLine { | ||
| 22 | std::string text; | ||
| 23 | int charsRevealed = 0; | ||
| 24 | bool pause = false; | ||
| 25 | bool isChoice = false; | ||
| 26 | int choicePos[2] = {-1, -1}; | ||
| 27 | }; | ||
| 28 | |||
| 21 | class MessageSystem : public System { | 29 | class MessageSystem : public System { |
| 22 | public: | 30 | public: |
| 23 | 31 | ||
| @@ -41,17 +49,18 @@ public: | |||
| 41 | std::string speakerName = "", | 49 | std::string speakerName = "", |
| 42 | SpeakerType speakerType = SpeakerType::None); | 50 | SpeakerType speakerType = SpeakerType::None); |
| 43 | 51 | ||
| 52 | void showChoice(std::string choice1, std::string choice2); | ||
| 53 | |||
| 44 | void advanceText(); | 54 | void advanceText(); |
| 45 | 55 | ||
| 56 | void selectFirstChoice(); | ||
| 57 | |||
| 58 | void selectSecondChoice(); | ||
| 59 | |||
| 46 | // Info | 60 | // Info |
| 47 | 61 | ||
| 48 | double getCutsceneBarsProgress() const; | 62 | double getCutsceneBarsProgress() const; |
| 49 | 63 | ||
| 50 | struct MessageLine { | ||
| 51 | std::string text; | ||
| 52 | int charsRevealed = 0; | ||
| 53 | }; | ||
| 54 | |||
| 55 | const std::list<MessageLine>& getLines() const { return linesToShow_; } | 64 | const std::list<MessageLine>& getLines() const { return linesToShow_; } |
| 56 | 65 | ||
| 57 | bool isMessageActive() const { return !linesToShow_.empty(); } | 66 | bool isMessageActive() const { return !linesToShow_.empty(); } |
| @@ -62,6 +71,10 @@ public: | |||
| 62 | 71 | ||
| 63 | int getNextArrowBob() const { return nextArrowBobPos_; } | 72 | int getNextArrowBob() const { return nextArrowBobPos_; } |
| 64 | 73 | ||
| 74 | bool isChoiceActive() const { return isMessageActive() && linesToShow_.back().isChoice; } | ||
| 75 | |||
| 76 | int getChoiceSelection() const { return choiceSelection_; } | ||
| 77 | |||
| 65 | private: | 78 | private: |
| 66 | 79 | ||
| 67 | enum class BarsState { | 80 | enum class BarsState { |
| @@ -77,13 +90,14 @@ private: | |||
| 77 | double length_ = 1000.0/8; | 90 | double length_ = 1000.0/8; |
| 78 | SpeakerType speaker_ = SpeakerType::None; | 91 | SpeakerType speaker_ = SpeakerType::None; |
| 79 | std::string speakerName_; | 92 | std::string speakerName_; |
| 80 | std::list<std::string> lines_; | 93 | std::list<MessageLine> lines_; |
| 81 | std::list<MessageLine> linesToShow_; | 94 | std::list<MessageLine> linesToShow_; |
| 82 | Timer textAdvTimer_ { 15 }; | 95 | Timer textAdvTimer_ { 15 }; |
| 83 | bool showNextArrow_ = false; | 96 | bool showNextArrow_ = false; |
| 84 | int nextArrowBobPos_ = 0; | 97 | int nextArrowBobPos_ = 0; |
| 85 | bool nextArrowBobDown_ = true; | 98 | bool nextArrowBobDown_ = true; |
| 86 | Timer nextArrowBobTimer_ { 125 }; | 99 | Timer nextArrowBobTimer_ { 125 }; |
| 100 | int choiceSelection_ = 0; | ||
| 87 | }; | 101 | }; |
| 88 | 102 | ||
| 89 | #endif /* end of include guard: MESSAGE_SYSTEM_H_DE10D011 */ | 103 | #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) { | |||
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | int lineIndex = 0; | 196 | int lineIndex = 0; |
| 197 | for (const MessageSystem::MessageLine& line : game.getSystem<MessageSystem>().getLines()) { | 197 | for (const MessageLine& line : game.getSystem<MessageSystem>().getLines()) { |
| 198 | if (messageLines_[lineIndex].line != line.text) { | 198 | if (messageLines_[lineIndex].line != line.text) { |
| 199 | renderMessageLine(messageLines_[lineIndex], line.text, game); | 199 | renderMessageLine(messageLines_[lineIndex], line.text, game); |
| 200 | } | 200 | } |
| @@ -223,13 +223,27 @@ void Renderer::render(Game& game) { | |||
| 223 | advMsgArrowTex_ = loadImageFromFile("../res/advance_text_arrow.png"); | 223 | advMsgArrowTex_ = loadImageFromFile("../res/advance_text_arrow.png"); |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | SDL_Rect destRect { | 226 | if (game.getSystem<MessageSystem>().isChoiceActive()) { |
| 227 | 216, | 227 | int selection = game.getSystem<MessageSystem>().getChoiceSelection(); |
| 228 | 138 + game.getSystem<MessageSystem>().getNextArrowBob(), | 228 | int charIndex = game.getSystem<MessageSystem>().getLines().back().choicePos[selection]; |
| 229 | 16, | 229 | int baseX = messageLines_[1].charIndexToWidth[charIndex]; |
| 230 | 16 }; | ||
| 231 | 230 | ||
| 232 | SDL_RenderCopy(ren_.get(), textures_.at(advMsgArrowTex_).get(), nullptr, &destRect); | 231 | SDL_Rect destRect { |
| 232 | 18 + baseX - game.getSystem<MessageSystem>().getNextArrowBob()-16+3, | ||
| 233 | 141, | ||
| 234 | 16, | ||
| 235 | 16}; | ||
| 236 | |||
| 237 | SDL_RenderCopyEx(ren_.get(), textures_.at(advMsgArrowTex_).get(), nullptr, &destRect, -90, nullptr, SDL_FLIP_NONE); | ||
| 238 | } else { | ||
| 239 | SDL_Rect destRect { | ||
| 240 | 216, | ||
| 241 | 138 + game.getSystem<MessageSystem>().getNextArrowBob(), | ||
| 242 | 16, | ||
| 243 | 16 }; | ||
| 244 | |||
| 245 | SDL_RenderCopy(ren_.get(), textures_.at(advMsgArrowTex_).get(), nullptr, &destRect); | ||
| 246 | } | ||
| 233 | } | 247 | } |
| 234 | } | 248 | } |
| 235 | } | 249 | } |
| 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) { | |||
| 21 | engine_.new_usertype<MessageSystem>( | 21 | engine_.new_usertype<MessageSystem>( |
| 22 | "message", | 22 | "message", |
| 23 | "displayMessage", &MessageSystem::displayMessage, | 23 | "displayMessage", &MessageSystem::displayMessage, |
| 24 | "showChoice", &MessageSystem::showChoice, | ||
| 24 | "hideCutsceneBars", &MessageSystem::hideCutsceneBars, | 25 | "hideCutsceneBars", &MessageSystem::hideCutsceneBars, |
| 25 | "isMessageActive", sol::property(&MessageSystem::isMessageActive)); | 26 | "isMessageActive", sol::property(&MessageSystem::isMessageActive), |
| 27 | "getChoiceSelection", &MessageSystem::getChoiceSelection); | ||
| 26 | 28 | ||
| 27 | engine_.new_usertype<AnimationSystem>( | 29 | engine_.new_usertype<AnimationSystem>( |
| 28 | "animation", | 30 | "animation", |
