summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2021-02-11 20:47:46 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2021-02-11 20:47:46 -0500
commitec511705ce96d80d4e2a36054769c211448e8ec8 (patch)
treee0a70671430a84472024d54b934df3248924ec4d
parentd9be54853910c2086013846661e0dc4a8603c20e (diff)
downloadtanetane-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.
-rw-r--r--res/scripts/common.lua8
-rw-r--r--res/scripts/script0001.lua10
-rw-r--r--res/sfx/horizontal_menu.wavbin0 -> 52864 bytes
-rw-r--r--src/input_system.cpp8
-rw-r--r--src/message_system.cpp82
-rw-r--r--src/message_system.h26
-rw-r--r--src/renderer.cpp28
-rw-r--r--src/script_system.cpp4
8 files changed, 127 insertions, 39 deletions
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)
36 message():displayMessage(msg, name, type) 36 message():displayMessage(msg, name, type)
37end 37end
38 38
39function ShowChoice(one, two)
40 message():showChoice(one, two)
41end
42
43function GetChoiceSelection()
44 return message():getChoiceSelection()
45end
46
39function WaitForEndOfMessage() 47function WaitForEndOfMessage()
40 while (message().isMessageActive) do 48 while (message().isMessageActive) do
41 coroutine.yield() 49 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()
3 SetAnimation("boney", "barking") 3 SetAnimation("boney", "barking")
4 local barkingNoise = LoopSound("barking_at_hallucination.wav") 4 local barkingNoise = LoopSound("barking_at_hallucination.wav")
5 5
6 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) 6 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)
7 ShowChoice("Yes", "No")
7 WaitForEndOfMessage() 8 WaitForEndOfMessage()
8 9
9 SetAnimation("boney", "crouch") 10 SetAnimation("boney", "crouch")
10 StopSound(barkingNoise) 11 StopSound(barkingNoise)
11 PlaySound("boney_growl.wav") 12 PlaySound("boney_growl.wav")
13
14 if GetChoiceSelection() == 0 then
15 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)
16 else
17 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)
18 end
19
12 HideCutsceneBars() 20 HideCutsceneBars()
13end 21end
diff --git a/res/sfx/horizontal_menu.wav b/res/sfx/horizontal_menu.wav new file mode 100644 index 0000000..cf9595d --- /dev/null +++ b/res/sfx/horizontal_menu.wav
Binary files 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) {
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
194void 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
188void MessageSystem::advanceText() { 205void 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
238void MessageSystem::selectFirstChoice() {
239 if (isChoiceActive() && choiceSelection_ != 0) {
240 choiceSelection_ = 0;
241 game_.getMixer().playSound("../res/sfx/horizontal_menu.wav");
242 }
243}
244
245void MessageSystem::selectSecondChoice() {
246 if (isChoiceActive() && choiceSelection_ != 1) {
247 choiceSelection_ = 1;
248 game_.getMixer().playSound("../res/sfx/horizontal_menu.wav");
249 }
250}
251
218double MessageSystem::getCutsceneBarsProgress() const { 252double 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
21struct 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
21class MessageSystem : public System { 29class MessageSystem : public System {
22public: 30public:
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
65private: 78private:
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",