diff options
| author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2021-02-04 20:45:18 -0500 |
|---|---|---|
| committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2021-02-04 20:45:18 -0500 |
| commit | 871943d6a90bdb92b3cc495d4d927199611f8c6b (patch) | |
| tree | 9be125438747f7370cfa56e3f3e42f8c68982852 /src/message_system.cpp | |
| parent | 138e0a8f83e82c6109bfc387ac7417d4f41711b4 (diff) | |
| download | tanetane-871943d6a90bdb92b3cc495d4d927199611f8c6b.tar.gz tanetane-871943d6a90bdb92b3cc495d4d927199611f8c6b.tar.bz2 tanetane-871943d6a90bdb92b3cc495d4d927199611f8c6b.zip | |
Added text boxes
Text now reveals itself and scrolls! Yay! It even plays speaker beeps. TODO: the arror indicating an A press is needed. Bullets on lines that need bullets. The header that says who the speaker is, if relevant.
Diffstat (limited to 'src/message_system.cpp')
| -rw-r--r-- | src/message_system.cpp | 153 |
1 files changed, 153 insertions, 0 deletions
| diff --git a/src/message_system.cpp b/src/message_system.cpp index 71e8a5a..5abb4b3 100644 --- a/src/message_system.cpp +++ b/src/message_system.cpp | |||
| @@ -1,4 +1,9 @@ | |||
| 1 | #include "message_system.h" | 1 | #include "message_system.h" |
| 2 | #include "game.h" | ||
| 3 | #include "util.h" | ||
| 4 | |||
| 5 | const int CHARS_TO_REVEAL = 1; | ||
| 6 | const int CHARS_PER_BEEP = 10; | ||
| 2 | 7 | ||
| 3 | void MessageSystem::tick(double dt) { | 8 | void MessageSystem::tick(double dt) { |
| 4 | if (barsState_ == BarsState::Opening || barsState_ == BarsState::Closing) { | 9 | if (barsState_ == BarsState::Opening || barsState_ == BarsState::Closing) { |
| @@ -11,6 +16,53 @@ void MessageSystem::tick(double dt) { | |||
| 11 | barsState_ = BarsState::Closed; | 16 | barsState_ = BarsState::Closed; |
| 12 | } | 17 | } |
| 13 | } | 18 | } |
| 19 | } else if (barsState_ == BarsState::Open) { | ||
| 20 | if (!linesToShow_.empty()) { | ||
| 21 | textAdvTimer_.accumulate(dt); | ||
| 22 | while (textAdvTimer_.step()) { | ||
| 23 | // Try to advance text on the first line that isn't totally revealed yet. | ||
| 24 | bool advancedChars = false; | ||
| 25 | for (MessageLine& line : linesToShow_) { | ||
| 26 | if (line.charsRevealed < line.text.size()) { | ||
| 27 | // Every so often play a beep. | ||
| 28 | if (line.charsRevealed % CHARS_PER_BEEP == 0) { | ||
| 29 | if (speaker_ == SpeakerType::Man) { | ||
| 30 | game_.getMixer().playSound("../res/speaking_man.wav"); | ||
| 31 | } else if (speaker_ == SpeakerType::Woman) { | ||
| 32 | game_.getMixer().playSound("../res/speaking_woman.wav"); | ||
| 33 | } else if (speaker_ == SpeakerType::Boy) { | ||
| 34 | game_.getMixer().playSound("../res/speaking_boy.wav"); | ||
| 35 | } else if (speaker_ == SpeakerType::Girl) { | ||
| 36 | game_.getMixer().playSound("../res/speaking_girl.wav"); | ||
| 37 | } else if (speaker_ == SpeakerType::Nonhuman) { | ||
| 38 | game_.getMixer().playSound("../res/speaking_nonhuman.wav"); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | line.charsRevealed += CHARS_TO_REVEAL; | ||
| 43 | if (line.charsRevealed > line.text.size()) { | ||
| 44 | line.charsRevealed = line.text.size(); | ||
| 45 | } | ||
| 46 | advancedChars = true; | ||
| 47 | break; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | if (!advancedChars) { | ||
| 52 | // 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 | ||
| 54 | // means an A press is required. | ||
| 55 | if (!lines_.empty() && lines_.front() != "\n") { | ||
| 56 | if (linesToShow_.size() == 2) { | ||
| 57 | linesToShow_.pop_front(); | ||
| 58 | } | ||
| 59 | |||
| 60 | linesToShow_.push_back(MessageLine { .text = lines_.front() }); | ||
| 61 | lines_.pop_front(); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | } | ||
| 65 | } | ||
| 14 | } | 66 | } |
| 15 | } | 67 | } |
| 16 | 68 | ||
| @@ -24,6 +76,107 @@ void MessageSystem::hideCutsceneBars() { | |||
| 24 | barsState_ = BarsState::Closing; | 76 | barsState_ = BarsState::Closing; |
| 25 | } | 77 | } |
| 26 | 78 | ||
| 79 | void MessageSystem::displayMessage(std::string_view msg, SpeakerType speaker) { | ||
| 80 | if (!(barsState_ == BarsState::Opening || barsState_ == BarsState::Open)) { | ||
| 81 | displayCutsceneBars(); | ||
| 82 | } | ||
| 83 | |||
| 84 | speaker_ = speaker; | ||
| 85 | |||
| 86 | auto lineChunks = splitStr<std::list<std::string>>(std::string(msg), "\n"); | ||
| 87 | for (const std::string& text : lineChunks) { | ||
| 88 | auto words = splitStr<std::list<std::string>>(text, " "); | ||
| 89 | |||
| 90 | std::string curLine; | ||
| 91 | int curWidth = 0; | ||
| 92 | bool firstWord = true; | ||
| 93 | bool shouldAddBlank = false; | ||
| 94 | |||
| 95 | // I'm gonna be frank and admit it: I'm not gonna take hyphenation into | ||
| 96 | // consideration. Please don't write any words that are wider than the | ||
| 97 | // textbox. | ||
| 98 | for (const std::string& word : words) { | ||
| 99 | int wordWidth = 0; | ||
| 100 | bool firstChar = true; | ||
| 101 | for (int i=0; i<word.size(); i++) { | ||
| 102 | if (firstChar) { | ||
| 103 | firstChar = false; | ||
| 104 | } else { | ||
| 105 | wordWidth++; | ||
| 106 | } | ||
| 107 | |||
| 108 | wordWidth += game_.getFont().getCharacterWidth(word[i]); | ||
| 109 | } | ||
| 110 | |||
| 111 | int nextWidth = curWidth + wordWidth; | ||
| 112 | if (!firstWord) { | ||
| 113 | nextWidth += game_.getFont().getCharacterWidth(' '); | ||
| 114 | } | ||
| 115 | |||
| 116 | if (nextWidth > MESSAGE_TEXT_WIDTH) { | ||
| 117 | lines_.push_back(curLine); | ||
| 118 | curLine = word; | ||
| 119 | curWidth = wordWidth + game_.getFont().getCharacterWidth(' '); | ||
| 120 | |||
| 121 | if (shouldAddBlank) { | ||
| 122 | shouldAddBlank = false; | ||
| 123 | lines_.push_back("\n"); | ||
| 124 | } else { | ||
| 125 | shouldAddBlank = true; | ||
| 126 | } | ||
| 127 | } else { | ||
| 128 | curWidth = nextWidth; | ||
| 129 | if (!firstWord) { | ||
| 130 | curLine.append(" "); | ||
| 131 | } | ||
| 132 | curLine.append(word); | ||
| 133 | } | ||
| 134 | |||
| 135 | firstWord = false; | ||
| 136 | } | ||
| 137 | |||
| 138 | lines_.push_back(curLine); | ||
| 139 | lines_.push_back("\n"); | ||
| 140 | } | ||
| 141 | |||
| 142 | if (linesToShow_.empty()) { | ||
| 143 | linesToShow_.push_back(MessageLine { .text = lines_.front() }); | ||
| 144 | lines_.pop_front(); | ||
| 145 | |||
| 146 | if (lines_.front() != "\n") { | ||
| 147 | linesToShow_.push_back(MessageLine { .text = lines_.front() }); | ||
| 148 | lines_.pop_front(); | ||
| 149 | } | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | void MessageSystem::advanceText() { | ||
| 154 | if (barsState_ != BarsState::Open) { | ||
| 155 | return; | ||
| 156 | } | ||
| 157 | |||
| 158 | for (const MessageLine& line : linesToShow_) { | ||
| 159 | if (line.charsRevealed != line.text.size()) { | ||
| 160 | return; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | if (lines_.empty()) { | ||
| 165 | linesToShow_.clear(); | ||
| 166 | return; | ||
| 167 | } | ||
| 168 | |||
| 169 | if (lines_.front() != "\n") { | ||
| 170 | return; | ||
| 171 | } | ||
| 172 | |||
| 173 | lines_.pop_front(); | ||
| 174 | |||
| 175 | if (lines_.empty()) { | ||
| 176 | linesToShow_.clear(); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 27 | double MessageSystem::getCutsceneBarsProgress() const { | 180 | double MessageSystem::getCutsceneBarsProgress() const { |
| 28 | switch (barsState_) { | 181 | switch (barsState_) { |
| 29 | case BarsState::Closed: return 0.0; | 182 | case BarsState::Closed: return 0.0; |
