summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2021-02-04 20:45:18 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2021-02-04 20:45:18 -0500
commit871943d6a90bdb92b3cc495d4d927199611f8c6b (patch)
tree9be125438747f7370cfa56e3f3e42f8c68982852
parent138e0a8f83e82c6109bfc387ac7417d4f41711b4 (diff)
downloadtanetane-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.
-rw-r--r--CMakeLists.txt1
-rw-r--r--res/font.pngbin0 -> 2445 bytes
-rw-r--r--res/font.txt96
-rw-r--r--res/speaking_boy.wavbin0 -> 8460 bytes
-rw-r--r--res/speaking_girl.wavbin0 -> 7672 bytes
-rw-r--r--res/speaking_man.wavbin0 -> 9536 bytes
-rw-r--r--res/speaking_nonhuman.wavbin0 -> 12316 bytes
-rw-r--r--res/speaking_woman.wavbin0 -> 8384 bytes
-rw-r--r--src/consts.h2
-rw-r--r--src/font.cpp63
-rw-r--r--src/font.h33
-rw-r--r--src/game.h8
-rw-r--r--src/input_system.cpp9
-rw-r--r--src/main.cpp3
-rw-r--r--src/message_system.cpp153
-rw-r--r--src/message_system.h28
-rw-r--r--src/renderer.cpp71
-rw-r--r--src/renderer.h11
18 files changed, 474 insertions, 4 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 36acd0b..5626362 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -37,6 +37,7 @@ add_executable(tanetane
37 src/mixer.cpp 37 src/mixer.cpp
38 src/game.cpp 38 src/game.cpp
39 src/map.cpp 39 src/map.cpp
40 src/font.cpp
40 src/transform_system.cpp 41 src/transform_system.cpp
41 src/camera_system.cpp 42 src/camera_system.cpp
42 src/animation_system.cpp 43 src/animation_system.cpp
diff --git a/res/font.png b/res/font.png new file mode 100644 index 0000000..aacca94 --- /dev/null +++ b/res/font.png
Binary files differ
diff --git a/res/font.txt b/res/font.txt new file mode 100644 index 0000000..a089e8c --- /dev/null +++ b/res/font.txt
@@ -0,0 +1,96 @@
1../res/font.png
290 characters
310 characters per row
412x12 tile size
58 baseline
6
7! 1
8" 3
9# 5
10$ 5
11% 9
12& 7
13' 2
14( 3
15) 3
16* 3
17+ 5
18, 2
19- 3
20. 1
21/ 4
220 4
231 2
242 4
253 4
264 5
275 4
286 4
297 4
308 4
319 4
32: 1
33; 2
34< 4
35= 5
36> 4
37? 4
38@ 7
39A 6
40B 5
41C 5
42D 5
43E 4
44F 4
45G 5
46H 5
47I 1
48J 4
49K 5
50L 4
51M 7
52N 5
53O 5
54P 5
55Q 5
56R 5
57S 5
58T 5
59U 5
60V 6
61W 7
62X 5
63Y 5
64Z 4
65[ 2
66~ 6
67] 2
68^ 3
69_ 2
70` 0
71a 5
72b 4
73c 4
74d 4
75e 4
76f 3
77g 4
78h 4
79i 1
80j 2
81k 4
82l 1
83m 7
84n 4
85o 4
86p 4
87q 4
88r 3
89s 4
90t 3
91u 4
92v 5
93w 7
94x 4
95y 4
96z 4 \ No newline at end of file
diff --git a/res/speaking_boy.wav b/res/speaking_boy.wav new file mode 100644 index 0000000..78c5a95 --- /dev/null +++ b/res/speaking_boy.wav
Binary files differ
diff --git a/res/speaking_girl.wav b/res/speaking_girl.wav new file mode 100644 index 0000000..67365d3 --- /dev/null +++ b/res/speaking_girl.wav
Binary files differ
diff --git a/res/speaking_man.wav b/res/speaking_man.wav new file mode 100644 index 0000000..0a0f56d --- /dev/null +++ b/res/speaking_man.wav
Binary files differ
diff --git a/res/speaking_nonhuman.wav b/res/speaking_nonhuman.wav new file mode 100644 index 0000000..098ab53 --- /dev/null +++ b/res/speaking_nonhuman.wav
Binary files differ
diff --git a/res/speaking_woman.wav b/res/speaking_woman.wav new file mode 100644 index 0000000..6ae42bd --- /dev/null +++ b/res/speaking_woman.wav
Binary files differ
diff --git a/src/consts.h b/src/consts.h index 5ef2c21..12b9e8f 100644 --- a/src/consts.h +++ b/src/consts.h
@@ -10,4 +10,6 @@ const int CANVAS_HEIGHT = 160;
10const int MOVEMENT_SPEED = 2; 10const int MOVEMENT_SPEED = 2;
11const int PARTY_FRAME_DELAY = 10;// / MOVEMENT_SPEED; 11const int PARTY_FRAME_DELAY = 10;// / MOVEMENT_SPEED;
12 12
13const int MESSAGE_TEXT_WIDTH = 196;
14
13#endif /* end of include guard: CONSTS_H_9561E49C */ 15#endif /* end of include guard: CONSTS_H_9561E49C */
diff --git a/src/font.cpp b/src/font.cpp new file mode 100644 index 0000000..cfaad24 --- /dev/null +++ b/src/font.cpp
@@ -0,0 +1,63 @@
1#include "font.h"
2#include <fstream>
3#include <iostream>
4#include "renderer.h"
5
6inline int charToIndex(char ch) {
7 return static_cast<int>(ch) - static_cast<int>('!');
8}
9
10Font::Font(std::string_view filename, Renderer& renderer) {
11 std::ifstream fontfile(filename.data());
12 if (!fontfile.is_open()) {
13 throw std::invalid_argument("Can't find font file: " + std::string(filename));
14 }
15
16 std::string imagefilename;
17 fontfile >> imagefilename;
18 textureId_ = renderer.loadImageFromFile(imagefilename);
19
20 std::string line;
21 char ch;
22
23 int numChars;
24 fontfile >> numChars;
25 std::getline(fontfile, line); // characters
26
27 fontfile >> columns_;
28 std::getline(fontfile, line); // characters per row
29
30 fontfile >> tileSize_.x();
31 fontfile >> ch; // x
32 fontfile >> tileSize_.y();
33 std::getline(fontfile, line); // tile size
34
35 std::getline(fontfile, line); // ignore the baseline location
36 std::getline(fontfile, line); // blank
37
38 for (int i=0; i<numChars; i++) {
39 fontfile >> ch; // the character
40
41 int width;
42 fontfile >> width;
43
44 widths_.push_back(width);
45 }
46}
47
48vec2i Font::getCharacterLocation(char ch) const {
49 int index = charToIndex(ch);
50 return (vec2i { index % columns_, index / columns_ }) * tileSize_;
51}
52
53vec2i Font::getCharacterSize(char ch) const {
54 int index = charToIndex(ch);
55 return { widths_.at(index), tileSize_.h() };
56}
57
58int Font::getCharacterWidth(char ch) const {
59 if (ch == ' ') {
60 return 3;
61 }
62 return widths_.at(charToIndex(ch));
63}
diff --git a/src/font.h b/src/font.h new file mode 100644 index 0000000..fd24830 --- /dev/null +++ b/src/font.h
@@ -0,0 +1,33 @@
1#ifndef FONT_H_C80183A7
2#define FONT_H_C80183A7
3
4#include <string_view>
5#include <vector>
6#include "vector.h"
7
8class Renderer;
9
10class Font {
11public:
12
13 Font(std::string_view filename, Renderer& renderer);
14
15 int getTextureId() const { return textureId_; }
16
17 vec2i getCharacterLocation(char ch) const;
18
19 vec2i getCharacterSize(char ch) const;
20
21 int getCharacterWidth(char ch) const;
22
23 int getCharacterHeight() const { return tileSize_.h(); }
24
25private:
26
27 int textureId_;
28 int columns_;
29 vec2i tileSize_;
30 std::vector<int> widths_;
31};
32
33#endif /* end of include guard: FONT_H_C80183A7 */
diff --git a/src/game.h b/src/game.h index 36398bc..2f1149d 100644 --- a/src/game.h +++ b/src/game.h
@@ -11,10 +11,15 @@
11#include "consts.h" 11#include "consts.h"
12#include "system.h" 12#include "system.h"
13#include "mixer.h" 13#include "mixer.h"
14#include "font.h"
15
16class Renderer;
14 17
15class Game { 18class Game {
16public: 19public:
17 20
21 explicit Game(Renderer& renderer) : font_("../res/font.txt", renderer) {}
22
18 Mixer& getMixer() { return mixer_; } 23 Mixer& getMixer() { return mixer_; }
19 24
20 bool shouldQuit() const { return shouldQuit_; } 25 bool shouldQuit() const { return shouldQuit_; }
@@ -68,6 +73,8 @@ public:
68 73
69 const Map& getMap() const { return *map_; } 74 const Map& getMap() const { return *map_; }
70 75
76 const Font& getFont() const { return font_; }
77
71private: 78private:
72 79
73 Mixer mixer_; 80 Mixer mixer_;
@@ -79,6 +86,7 @@ private:
79 std::vector<int> spriteIds_; 86 std::vector<int> spriteIds_;
80 std::vector<Sprite> sprites_; 87 std::vector<Sprite> sprites_;
81 std::unique_ptr<Map> map_; 88 std::unique_ptr<Map> map_;
89 Font font_;
82}; 90};
83 91
84#endif /* end of include guard: GAME_H_E6F1396E */ 92#endif /* end of include guard: GAME_H_E6F1396E */
diff --git a/src/input_system.cpp b/src/input_system.cpp index 7bd605c..a0acc5e 100644 --- a/src/input_system.cpp +++ b/src/input_system.cpp
@@ -27,11 +27,16 @@ void InputSystem::tick(double dt) {
27 } 27 }
28 } else if (e.key.keysym.sym == SDLK_a) { 28 } else if (e.key.keysym.sym == SDLK_a) {
29 // TODO: Remove this, it's just for testing. 29 // TODO: Remove this, it's just for testing.
30 if (game_.getSystem<MessageSystem>().getCutsceneBarsProgress() == 1.0) { 30 /*if (game_.getSystem<MessageSystem>().getCutsceneBarsProgress() == 1.0) {
31 game_.getSystem<MessageSystem>().hideCutsceneBars(); 31 game_.getSystem<MessageSystem>().hideCutsceneBars();
32 } else { 32 } else {
33 game_.getSystem<MessageSystem>().displayCutsceneBars(); 33 game_.getSystem<MessageSystem>().displayCutsceneBars();
34 } 34 }*/
35 //game_.getSystem<MessageSystem>().displayMessage("Some people always try to avoid fighting when there are enemies around. You know the type, right? They use the dash ability to zoom right by. I guess you could say they're followers of \"peace at any price\".", SpeakerType::Woman);
36 game_.getSystem<MessageSystem>().displayMessage("Go to sleep.\nIn the absolute darkness.\nDon't do aaaanything.\nDon't see anyone.\nJust sleep.\nIt'll be oh, so much fun......!\nOhohohoho!", SpeakerType::Woman);
37 } else if (e.key.keysym.sym == SDLK_b) {
38 // TODO: Remove this, it's just for testing.
39 game_.getSystem<MessageSystem>().advanceText();
35 } 40 }
36 } else if (e.type == SDL_KEYUP && (e.key.keysym.sym == SDLK_LSHIFT || e.key.keysym.sym == SDLK_RSHIFT)) { 41 } else if (e.type == SDL_KEYUP && (e.key.keysym.sym == SDLK_LSHIFT || e.key.keysym.sym == SDLK_RSHIFT)) {
37 for (int spriteId : game_.getSprites()) { 42 for (int spriteId : game_.getSprites()) {
diff --git a/src/main.cpp b/src/main.cpp index 6674c0c..935fc78 100644 --- a/src/main.cpp +++ b/src/main.cpp
@@ -4,7 +4,6 @@
4#include "game.h" 4#include "game.h"
5#include "timer.h" 5#include "timer.h"
6#include "map.h" 6#include "map.h"
7#include "mixer.h"
8#include "transform_system.h" 7#include "transform_system.h"
9#include "camera_system.h" 8#include "camera_system.h"
10#include "animation_system.h" 9#include "animation_system.h"
@@ -13,7 +12,7 @@
13#include "message_system.h" 12#include "message_system.h"
14 13
15void loop(Renderer& renderer) { 14void loop(Renderer& renderer) {
16 Game game; 15 Game game(renderer);
17 game.emplaceSystem<TransformSystem>(); 16 game.emplaceSystem<TransformSystem>();
18 game.emplaceSystem<InputSystem>(); 17 game.emplaceSystem<InputSystem>();
19 game.emplaceSystem<CharacterSystem>(); 18 game.emplaceSystem<CharacterSystem>();
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
5const int CHARS_TO_REVEAL = 1;
6const int CHARS_PER_BEEP = 10;
2 7
3void MessageSystem::tick(double dt) { 8void 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
79void 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
153void 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
27double MessageSystem::getCutsceneBarsProgress() const { 180double MessageSystem::getCutsceneBarsProgress() const {
28 switch (barsState_) { 181 switch (barsState_) {
29 case BarsState::Closed: return 0.0; 182 case BarsState::Closed: return 0.0;
diff --git a/src/message_system.h b/src/message_system.h index 4dd0166..153805a 100644 --- a/src/message_system.h +++ b/src/message_system.h
@@ -1,10 +1,23 @@
1#ifndef MESSAGE_SYSTEM_H_DE10D011 1#ifndef MESSAGE_SYSTEM_H_DE10D011
2#define MESSAGE_SYSTEM_H_DE10D011 2#define MESSAGE_SYSTEM_H_DE10D011
3 3
4#include <list>
5#include <string_view>
6#include <string>
4#include "system.h" 7#include "system.h"
8#include "timer.h"
5 9
6class Game; 10class Game;
7 11
12enum class SpeakerType {
13 None,
14 Man,
15 Woman,
16 Boy,
17 Girl,
18 Nonhuman
19};
20
8class MessageSystem : public System { 21class MessageSystem : public System {
9public: 22public:
10 23
@@ -20,10 +33,21 @@ public:
20 33
21 void hideCutsceneBars(); 34 void hideCutsceneBars();
22 35
36 void displayMessage(std::string_view msg, SpeakerType speaker);
37
38 void advanceText();
39
23 // Info 40 // Info
24 41
25 double getCutsceneBarsProgress() const; 42 double getCutsceneBarsProgress() const;
26 43
44 struct MessageLine {
45 std::string text;
46 int charsRevealed = 0;
47 };
48
49 const std::list<MessageLine>& getLines() const { return linesToShow_; }
50
27private: 51private:
28 52
29 enum class BarsState { 53 enum class BarsState {
@@ -37,6 +61,10 @@ private:
37 BarsState barsState_ = BarsState::Closed; 61 BarsState barsState_ = BarsState::Closed;
38 double accum_ = 0.0; 62 double accum_ = 0.0;
39 double length_ = 1000.0/8; 63 double length_ = 1000.0/8;
64 SpeakerType speaker_ = SpeakerType::None;
65 std::list<std::string> lines_;
66 std::list<MessageLine> linesToShow_;
67 Timer textAdvTimer_ { 10 };
40}; 68};
41 69
42#endif /* end of include guard: MESSAGE_SYSTEM_H_DE10D011 */ 70#endif /* end of include guard: MESSAGE_SYSTEM_H_DE10D011 */
diff --git a/src/renderer.cpp b/src/renderer.cpp index 2c6cf5c..b22c316 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp
@@ -1,4 +1,5 @@
1#include "renderer.h" 1#include "renderer.h"
2#include <iostream>
2#include "consts.h" 3#include "consts.h"
3#include "game.h" 4#include "game.h"
4#include "map.h" 5#include "map.h"
@@ -153,6 +154,33 @@ void Renderer::render(Game& game) {
153 int bottomBarHeight = 36.0 * game.getSystem<MessageSystem>().getCutsceneBarsProgress(); 154 int bottomBarHeight = 36.0 * game.getSystem<MessageSystem>().getCutsceneBarsProgress();
154 SDL_Rect bottomBar { 0, CANVAS_HEIGHT - bottomBarHeight, CANVAS_WIDTH, bottomBarHeight }; 155 SDL_Rect bottomBar { 0, CANVAS_HEIGHT - bottomBarHeight, CANVAS_WIDTH, bottomBarHeight };
155 SDL_RenderFillRect(ren_.get(), &bottomBar); 156 SDL_RenderFillRect(ren_.get(), &bottomBar);
157
158 if (game.getSystem<MessageSystem>().getCutsceneBarsProgress() == 1.0 &&
159 !game.getSystem<MessageSystem>().getLines().empty()) {
160 int lineIndex = 0;
161 for (const MessageSystem::MessageLine& line : game.getSystem<MessageSystem>().getLines()) {
162 if (messageLines_[lineIndex].line != line.text) {
163 renderMessageLine(lineIndex, line.text, game);
164 }
165
166 // 18x, 127y1, 143y2
167 if (line.charsRevealed > 0) {
168 SDL_Rect srcRect {
169 0, 0, messageLines_[lineIndex].charIndexToWidth[line.charsRevealed],
170 game.getFont().getCharacterHeight()
171 };
172 SDL_Rect destRect {
173 18,
174 127 + 16 * lineIndex,
175 srcRect.w,
176 srcRect.h };
177
178 SDL_RenderCopy(ren_.get(), messageLines_[lineIndex].renderedTex.get(), &srcRect, &destRect);
179 }
180
181 lineIndex++;
182 }
183 }
156 } 184 }
157 185
158 SDL_SetRenderTarget(ren_.get(), nullptr); 186 SDL_SetRenderTarget(ren_.get(), nullptr);
@@ -175,3 +203,46 @@ int Renderer::loadImageFromFile(std::string_view filename) {
175 203
176 return texId; 204 return texId;
177} 205}
206
207void Renderer::renderMessageLine(int lineIndex, const std::string& text, Game& game) {
208 MessageCache& line = messageLines_[lineIndex];
209 line.line = text;
210
211 line.renderedTex.reset(
212 SDL_CreateTexture(
213 ren_.get(),
214 SDL_PIXELFORMAT_RGBA8888,
215 SDL_TEXTUREACCESS_TARGET,
216 MESSAGE_TEXT_WIDTH,
217 game.getFont().getCharacterHeight()));
218
219 SDL_SetTextureBlendMode(line.renderedTex.get(), SDL_BLENDMODE_BLEND);
220
221 SDL_SetRenderTarget(ren_.get(), line.renderedTex.get());
222 SDL_SetRenderDrawBlendMode(ren_.get(), SDL_BLENDMODE_BLEND);
223 SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 0);
224 SDL_RenderClear(ren_.get());
225
226 line.charIndexToWidth.clear();
227 line.charIndexToWidth.push_back(0);
228
229 int length = 0;
230
231 for (int i=0; i<line.line.size(); i++) {
232 if (line.line[i] != ' ') {
233 vec2i charLoc = game.getFont().getCharacterLocation(line.line[i]);
234 vec2i charSize = game.getFont().getCharacterSize(line.line[i]);
235 SDL_Rect srcRect { charLoc.x(), charLoc.y(), charSize.w(), charSize.h() };
236 SDL_Rect destRect { length, 0, charSize.w(), charSize.h() };
237
238 SDL_RenderCopy(ren_.get(), textures_.at(game.getFont().getTextureId()).get(), &srcRect, &destRect);
239
240 length++;
241 }
242
243 length += game.getFont().getCharacterWidth(line.line[i]);
244 line.charIndexToWidth.push_back(length);
245 }
246
247 line.charIndexToWidth.back()--;
248}
diff --git a/src/renderer.h b/src/renderer.h index 71c4ade..fd6f707 100644 --- a/src/renderer.h +++ b/src/renderer.h
@@ -6,6 +6,7 @@
6#include <stdexcept> 6#include <stdexcept>
7#include <memory> 7#include <memory>
8#include <string_view> 8#include <string_view>
9#include <string>
9#include <vector> 10#include <vector>
10 11
11class Game; 12class Game;
@@ -124,6 +125,8 @@ private:
124 125
125 texture_ptr renderMapLayer(const Map& map, int layer); 126 texture_ptr renderMapLayer(const Map& map, int layer);
126 127
128 void renderMessageLine(int lineIndex, const std::string& text, Game& game);
129
127 sdl_wrapper sdl_; 130 sdl_wrapper sdl_;
128 img_wrapper img_; 131 img_wrapper img_;
129 window_ptr win_; 132 window_ptr win_;
@@ -132,6 +135,14 @@ private:
132 std::vector<texture_ptr> textures_; 135 std::vector<texture_ptr> textures_;
133 texture_ptr renLay0_; 136 texture_ptr renLay0_;
134 texture_ptr renLay1_; 137 texture_ptr renLay1_;
138
139 struct MessageCache {
140 texture_ptr renderedTex;
141 std::vector<int> charIndexToWidth;
142 std::string line;
143 };
144
145 MessageCache messageLines_[2];
135}; 146};
136 147
137#endif /* end of include guard: RENDERER_H_6A58EC30 */ 148#endif /* end of include guard: RENDERER_H_6A58EC30 */