diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/animation_system.cpp | 2 | ||||
-rw-r--r-- | src/behaviour_system.cpp | 2 | ||||
-rw-r--r-- | src/camera_system.cpp | 2 | ||||
-rw-r--r-- | src/character_system.cpp | 2 | ||||
-rw-r--r-- | src/effect_system.cpp | 3 | ||||
-rw-r--r-- | src/game.h | 7 | ||||
-rw-r--r-- | src/input_system.cpp | 44 | ||||
-rw-r--r-- | src/input_system.h | 7 | ||||
-rw-r--r-- | src/message_system.cpp | 2 | ||||
-rw-r--r-- | src/renderer.cpp | 61 | ||||
-rw-r--r-- | src/renderer.h | 6 | ||||
-rw-r--r-- | src/script_system.cpp | 10 | ||||
-rw-r--r-- | src/script_system.h | 2 |
14 files changed, 150 insertions, 2 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index b3994b2..f42260e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -16,6 +16,8 @@ find_package(SDL2 REQUIRED) | |||
16 | find_package(SDL2_image REQUIRED) | 16 | find_package(SDL2_image REQUIRED) |
17 | find_package(SDL2_mixer REQUIRED) | 17 | find_package(SDL2_mixer REQUIRED) |
18 | 18 | ||
19 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DTANETANE_DEBUG") | ||
20 | |||
19 | set(ALL_LIBS | 21 | set(ALL_LIBS |
20 | ${SDL2_LIBRARY} | 22 | ${SDL2_LIBRARY} |
21 | ${SDL2_IMAGE_LIBRARIES} | 23 | ${SDL2_IMAGE_LIBRARIES} |
diff --git a/src/animation_system.cpp b/src/animation_system.cpp index c43d0ca..d23eae2 100644 --- a/src/animation_system.cpp +++ b/src/animation_system.cpp | |||
@@ -91,6 +91,8 @@ void AnimationSystem::initSprite(int spriteId, std::string_view filename) { | |||
91 | } | 91 | } |
92 | 92 | ||
93 | void AnimationSystem::tick(double dt) { | 93 | void AnimationSystem::tick(double dt) { |
94 | if (game_.isGameplayPaused()) return; | ||
95 | |||
94 | animTimer_.accumulate(dt); | 96 | animTimer_.accumulate(dt); |
95 | while (animTimer_.step()) { | 97 | while (animTimer_.step()) { |
96 | for (Sprite& sprite : game_.getSprites() | game_.spriteView()) { | 98 | for (Sprite& sprite : game_.getSprites() | game_.spriteView()) { |
diff --git a/src/behaviour_system.cpp b/src/behaviour_system.cpp index 6cd0b52..2d46205 100644 --- a/src/behaviour_system.cpp +++ b/src/behaviour_system.cpp | |||
@@ -5,6 +5,8 @@ | |||
5 | #include "direction.h" | 5 | #include "direction.h" |
6 | 6 | ||
7 | void BehaviourSystem::tick(double dt) { | 7 | void BehaviourSystem::tick(double dt) { |
8 | if (game_.isGameplayPaused()) return; | ||
9 | |||
8 | timer_.accumulate(dt); | 10 | timer_.accumulate(dt); |
9 | while (timer_.step()) { | 11 | while (timer_.step()) { |
10 | for (int spriteId : game_.getSprites()) { | 12 | for (int spriteId : game_.getSprites()) { |
diff --git a/src/camera_system.cpp b/src/camera_system.cpp index c46b9dd..0ef3c36 100644 --- a/src/camera_system.cpp +++ b/src/camera_system.cpp | |||
@@ -4,6 +4,8 @@ | |||
4 | #include "map.h" | 4 | #include "map.h" |
5 | 5 | ||
6 | void CameraSystem::tick(double dt) { | 6 | void CameraSystem::tick(double dt) { |
7 | if (game_.isGameplayPaused()) return; | ||
8 | |||
7 | if (!locked_ && followingSprite_ != -1) { | 9 | if (!locked_ && followingSprite_ != -1) { |
8 | const Sprite& follow = game_.getSprite(followingSprite_); | 10 | const Sprite& follow = game_.getSprite(followingSprite_); |
9 | 11 | ||
diff --git a/src/character_system.cpp b/src/character_system.cpp index 7b628b0..6e15eac 100644 --- a/src/character_system.cpp +++ b/src/character_system.cpp | |||
@@ -91,6 +91,8 @@ void CharacterSystem::stopDirecting(int spriteId) { | |||
91 | } | 91 | } |
92 | 92 | ||
93 | void CharacterSystem::tick(double dt) { | 93 | void CharacterSystem::tick(double dt) { |
94 | if (game_.isGameplayPaused()) return; | ||
95 | |||
94 | inputTimer_.accumulate(dt); | 96 | inputTimer_.accumulate(dt); |
95 | while (inputTimer_.step()) { | 97 | while (inputTimer_.step()) { |
96 | for (int spriteId : game_.getSprites()) { | 98 | for (int spriteId : game_.getSprites()) { |
diff --git a/src/effect_system.cpp b/src/effect_system.cpp index 74fc8f3..aeccebb 100644 --- a/src/effect_system.cpp +++ b/src/effect_system.cpp | |||
@@ -1,6 +1,9 @@ | |||
1 | #include "effect_system.h" | 1 | #include "effect_system.h" |
2 | #include "game.h" | ||
2 | 3 | ||
3 | void EffectSystem::tick(double dt) { | 4 | void EffectSystem::tick(double dt) { |
5 | if (game_.isGameplayPaused()) return; | ||
6 | |||
4 | if (screenFade_ != screenFadeDest_) { | 7 | if (screenFade_ != screenFadeDest_) { |
5 | screenFadeThus_ += dt; | 8 | screenFadeThus_ += dt; |
6 | if (screenFadeThus_ >= screenFadeLength_) { | 9 | if (screenFadeThus_ >= screenFadeLength_) { |
diff --git a/src/game.h b/src/game.h index 72dd337..756ce70 100644 --- a/src/game.h +++ b/src/game.h | |||
@@ -86,6 +86,12 @@ public: | |||
86 | 86 | ||
87 | std::mt19937& getRng() { return *rng_; } | 87 | std::mt19937& getRng() { return *rng_; } |
88 | 88 | ||
89 | void pauseGameplay() { paused_ = true; } | ||
90 | |||
91 | void unpauseGameplay() { paused_ = false; } | ||
92 | |||
93 | bool isGameplayPaused() const { return paused_; } | ||
94 | |||
89 | private: | 95 | private: |
90 | 96 | ||
91 | Mixer mixer_; | 97 | Mixer mixer_; |
@@ -101,6 +107,7 @@ private: | |||
101 | std::unique_ptr<Map> map_; | 107 | std::unique_ptr<Map> map_; |
102 | Font font_; | 108 | Font font_; |
103 | std::mt19937* rng_; | 109 | std::mt19937* rng_; |
110 | bool paused_ = false; | ||
104 | }; | 111 | }; |
105 | 112 | ||
106 | #endif /* end of include guard: GAME_H_E6F1396E */ | 113 | #endif /* end of include guard: GAME_H_E6F1396E */ |
diff --git a/src/input_system.cpp b/src/input_system.cpp index 43c59dd..1b5b56b 100644 --- a/src/input_system.cpp +++ b/src/input_system.cpp | |||
@@ -16,12 +16,42 @@ struct Input { | |||
16 | void InputSystem::tick(double dt) { | 16 | void InputSystem::tick(double dt) { |
17 | SDL_Event e; | 17 | SDL_Event e; |
18 | while (SDL_PollEvent(&e)) { | 18 | while (SDL_PollEvent(&e)) { |
19 | if (e.type == SDL_QUIT || (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)) { | 19 | if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE) { |
20 | if (debugConsole_) { | ||
21 | debugConsole_ = false; | ||
22 | game_.unpauseGameplay(); | ||
23 | SDL_StopTextInput(); | ||
24 | debugText_.clear(); | ||
25 | } else { | ||
26 | game_.quit(); | ||
27 | } | ||
28 | } else if (e.type == SDL_QUIT) { | ||
20 | game_.quit(); | 29 | game_.quit(); |
21 | 30 | ||
22 | return; | 31 | return; |
32 | } else if (e.type == SDL_TEXTINPUT) { | ||
33 | debugText_.append(e.text.text); | ||
23 | } else if (e.type == SDL_KEYDOWN) { | 34 | } else if (e.type == SDL_KEYDOWN) { |
24 | if (e.key.keysym.sym == SDLK_LSHIFT || e.key.keysym.sym == SDLK_RSHIFT) { | 35 | if (e.key.keysym.sym == SDLK_BACKQUOTE) { |
36 | #ifdef TANETANE_DEBUG | ||
37 | if (!debugConsole_) { | ||
38 | debugConsole_ = true; | ||
39 | game_.pauseGameplay(); | ||
40 | SDL_StartTextInput(); | ||
41 | debugText_.clear(); | ||
42 | } | ||
43 | #endif | ||
44 | } else if (debugConsole_ && e.key.keysym.sym == SDLK_RETURN) { | ||
45 | game_.getSystem<ScriptSystem>().runDebugScript(debugText_); | ||
46 | debugText_.clear(); | ||
47 | } else if (debugConsole_ && e.key.keysym.sym == SDLK_BACKSPACE) { | ||
48 | // Make sure to keep the backtick/heart. | ||
49 | if (!debugText_.empty()) { | ||
50 | debugText_.pop_back(); | ||
51 | } | ||
52 | } else if (e.key.keysym.sym == SDLK_LSHIFT || e.key.keysym.sym == SDLK_RSHIFT) { | ||
53 | if (game_.isGameplayPaused()) continue; | ||
54 | |||
25 | for (int spriteId : game_.getSprites()) { | 55 | for (int spriteId : game_.getSprites()) { |
26 | Sprite& sprite = game_.getSprite(spriteId); | 56 | Sprite& sprite = game_.getSprite(spriteId); |
27 | if (sprite.controllable) { | 57 | if (sprite.controllable) { |
@@ -29,6 +59,8 @@ void InputSystem::tick(double dt) { | |||
29 | } | 59 | } |
30 | } | 60 | } |
31 | } else if (e.key.keysym.sym == SDLK_SPACE) { | 61 | } else if (e.key.keysym.sym == SDLK_SPACE) { |
62 | if (game_.isGameplayPaused()) continue; | ||
63 | |||
32 | // If there is text on screen, try to advance it. | 64 | // If there is text on screen, try to advance it. |
33 | if (game_.getSystem<MessageSystem>().getCutsceneBarsProgress() != 0.0) { | 65 | if (game_.getSystem<MessageSystem>().getCutsceneBarsProgress() != 0.0) { |
34 | game_.getSystem<MessageSystem>().advanceText(); | 66 | game_.getSystem<MessageSystem>().advanceText(); |
@@ -75,15 +107,21 @@ void InputSystem::tick(double dt) { | |||
75 | } | 107 | } |
76 | } | 108 | } |
77 | } else if (e.key.keysym.sym == SDLK_LEFT) { | 109 | } else if (e.key.keysym.sym == SDLK_LEFT) { |
110 | if (game_.isGameplayPaused()) continue; | ||
111 | |||
78 | if (game_.getSystem<MessageSystem>().isChoiceActive()) { | 112 | if (game_.getSystem<MessageSystem>().isChoiceActive()) { |
79 | game_.getSystem<MessageSystem>().selectFirstChoice(); | 113 | game_.getSystem<MessageSystem>().selectFirstChoice(); |
80 | } | 114 | } |
81 | } else if (e.key.keysym.sym == SDLK_RIGHT) { | 115 | } else if (e.key.keysym.sym == SDLK_RIGHT) { |
116 | if (game_.isGameplayPaused()) continue; | ||
117 | |||
82 | if (game_.getSystem<MessageSystem>().isChoiceActive()) { | 118 | if (game_.getSystem<MessageSystem>().isChoiceActive()) { |
83 | game_.getSystem<MessageSystem>().selectSecondChoice(); | 119 | game_.getSystem<MessageSystem>().selectSecondChoice(); |
84 | } | 120 | } |
85 | } | 121 | } |
86 | } else if (e.type == SDL_KEYUP && (e.key.keysym.sym == SDLK_LSHIFT || e.key.keysym.sym == SDLK_RSHIFT)) { | 122 | } else if (e.type == SDL_KEYUP && (e.key.keysym.sym == SDLK_LSHIFT || e.key.keysym.sym == SDLK_RSHIFT)) { |
123 | if (game_.isGameplayPaused()) continue; | ||
124 | |||
87 | for (int spriteId : game_.getSprites()) { | 125 | for (int spriteId : game_.getSprites()) { |
88 | Sprite& sprite = game_.getSprite(spriteId); | 126 | Sprite& sprite = game_.getSprite(spriteId); |
89 | if (sprite.controllable) { | 127 | if (sprite.controllable) { |
@@ -93,6 +131,8 @@ void InputSystem::tick(double dt) { | |||
93 | } | 131 | } |
94 | } | 132 | } |
95 | 133 | ||
134 | if (game_.isGameplayPaused()) return; | ||
135 | |||
96 | Input keystate; | 136 | Input keystate; |
97 | const Uint8* state = SDL_GetKeyboardState(NULL); | 137 | const Uint8* state = SDL_GetKeyboardState(NULL); |
98 | keystate.left = state[SDL_SCANCODE_LEFT]; | 138 | keystate.left = state[SDL_SCANCODE_LEFT]; |
diff --git a/src/input_system.h b/src/input_system.h index 4e5bb22..a7757b8 100644 --- a/src/input_system.h +++ b/src/input_system.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef INPUT_SYSTEM_H_47764575 | 1 | #ifndef INPUT_SYSTEM_H_47764575 |
2 | #define INPUT_SYSTEM_H_47764575 | 2 | #define INPUT_SYSTEM_H_47764575 |
3 | 3 | ||
4 | #include <string> | ||
4 | #include "system.h" | 5 | #include "system.h" |
5 | 6 | ||
6 | class Game; | 7 | class Game; |
@@ -14,9 +15,15 @@ public: | |||
14 | 15 | ||
15 | void tick(double dt) override; | 16 | void tick(double dt) override; |
16 | 17 | ||
18 | bool isDebugConsoleOpen() const { return debugConsole_; } | ||
19 | |||
20 | const std::string& getDebugText() const { return debugText_; } | ||
21 | |||
17 | private: | 22 | private: |
18 | 23 | ||
19 | Game& game_; | 24 | Game& game_; |
25 | bool debugConsole_ = false; | ||
26 | std::string debugText_; | ||
20 | }; | 27 | }; |
21 | 28 | ||
22 | #endif /* end of include guard: INPUT_SYSTEM_H_47764575 */ | 29 | #endif /* end of include guard: INPUT_SYSTEM_H_47764575 */ |
diff --git a/src/message_system.cpp b/src/message_system.cpp index 32ee847..1447f1e 100644 --- a/src/message_system.cpp +++ b/src/message_system.cpp | |||
@@ -6,6 +6,8 @@ const int CHARS_TO_REVEAL = 1; | |||
6 | const int CHARS_PER_BEEP = 8; | 6 | const int CHARS_PER_BEEP = 8; |
7 | 7 | ||
8 | void MessageSystem::tick(double dt) { | 8 | void MessageSystem::tick(double dt) { |
9 | if (game_.isGameplayPaused()) return; | ||
10 | |||
9 | if (barsState_ == BarsState::Opening || barsState_ == BarsState::Closing) { | 11 | if (barsState_ == BarsState::Opening || barsState_ == BarsState::Closing) { |
10 | accum_ += dt; | 12 | accum_ += dt; |
11 | 13 | ||
diff --git a/src/renderer.cpp b/src/renderer.cpp index 5aeb232..f8b2482 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp | |||
@@ -7,6 +7,7 @@ | |||
7 | #include "camera_system.h" | 7 | #include "camera_system.h" |
8 | #include "message_system.h" | 8 | #include "message_system.h" |
9 | #include "effect_system.h" | 9 | #include "effect_system.h" |
10 | #include "input_system.h" | ||
10 | 11 | ||
11 | Renderer::Renderer() { | 12 | Renderer::Renderer() { |
12 | win_ = window_ptr( | 13 | win_ = window_ptr( |
@@ -333,6 +334,61 @@ void Renderer::render(Game& game) { | |||
333 | SDL_RenderFillRect(ren_.get(), nullptr); | 334 | SDL_RenderFillRect(ren_.get(), nullptr); |
334 | } | 335 | } |
335 | 336 | ||
337 | if (game.getSystem<InputSystem>().isDebugConsoleOpen()) { | ||
338 | // Not sure why I'm supposed to copy the cached texture to the screen | ||
339 | // BEFORE rendering it, but we get flickering if we don't, so. | ||
340 | SDL_RenderCopy(ren_.get(), debugConsoleTex_.get(), nullptr, &debugDestRect_); | ||
341 | |||
342 | if (!debugConsoleTex_ || cachedDebugText_ != game.getSystem<InputSystem>().getDebugText()) { | ||
343 | cachedDebugText_ = game.getSystem<InputSystem>().getDebugText(); | ||
344 | |||
345 | std::vector<texture_ptr> textLines; | ||
346 | std::string remaining = "`" + cachedDebugText_; | ||
347 | |||
348 | while (!remaining.empty()) { | ||
349 | MessageCache output; | ||
350 | renderMessageLine(output, remaining, game); | ||
351 | textLines.push_back(std::move(output.renderedTex)); | ||
352 | remaining = output.overflow; | ||
353 | |||
354 | if (!remaining.empty()) { | ||
355 | remaining = " " + remaining; | ||
356 | } | ||
357 | } | ||
358 | |||
359 | int height = 16 * textLines.size() + 4 + 4; | ||
360 | |||
361 | debugConsoleTex_.reset( | ||
362 | SDL_CreateTexture( | ||
363 | ren_.get(), | ||
364 | SDL_PIXELFORMAT_RGBA8888, | ||
365 | SDL_TEXTUREACCESS_TARGET, | ||
366 | CANVAS_WIDTH, | ||
367 | height)); | ||
368 | |||
369 | SDL_SetRenderTarget(ren_.get(), debugConsoleTex_.get()); | ||
370 | SDL_SetTextureBlendMode(debugConsoleTex_.get(), SDL_BLENDMODE_BLEND); | ||
371 | SDL_SetRenderDrawBlendMode(ren_.get(), SDL_BLENDMODE_BLEND); | ||
372 | SDL_SetRenderDrawColor(ren_.get(), 30, 0, 110, 127); | ||
373 | //SDL_RenderFillRect(ren_.get(), nullptr); | ||
374 | SDL_RenderClear(ren_.get()); | ||
375 | |||
376 | for (int i=0; i<textLines.size(); i++) { | ||
377 | SDL_Rect destRect { | ||
378 | 18, | ||
379 | 4 + 16 * i, | ||
380 | MESSAGE_TEXT_WIDTH, | ||
381 | game.getFont().getCharacterHeight() }; | ||
382 | |||
383 | SDL_RenderCopy(ren_.get(), textLines[i].get(), nullptr, &destRect); | ||
384 | } | ||
385 | |||
386 | SDL_SetRenderTarget(ren_.get(), nullptr); | ||
387 | |||
388 | debugDestRect_ = SDL_Rect { 0, 0, CANVAS_WIDTH, height }; | ||
389 | } | ||
390 | } | ||
391 | |||
336 | SDL_SetRenderTarget(ren_.get(), nullptr); | 392 | SDL_SetRenderTarget(ren_.get(), nullptr); |
337 | SDL_RenderCopy(ren_.get(), cameraTex.get(), nullptr, nullptr); | 393 | SDL_RenderCopy(ren_.get(), cameraTex.get(), nullptr, nullptr); |
338 | SDL_RenderPresent(ren_.get()); | 394 | SDL_RenderPresent(ren_.get()); |
@@ -383,6 +439,11 @@ void Renderer::renderMessageLine(MessageCache& line, const std::string& text, Ga | |||
383 | 439 | ||
384 | for (int i=0; i<line.line.size(); i++) { | 440 | for (int i=0; i<line.line.size(); i++) { |
385 | if (line.line[i] != ' ') { | 441 | if (line.line[i] != ' ') { |
442 | if (length + game.getFont().getCharacterWidth(line.line[i]) > MESSAGE_TEXT_WIDTH) { | ||
443 | line.overflow = line.line.substr(i); | ||
444 | break; | ||
445 | } | ||
446 | |||
386 | vec2i charLoc = game.getFont().getCharacterLocation(line.line[i]); | 447 | vec2i charLoc = game.getFont().getCharacterLocation(line.line[i]); |
387 | vec2i charSize = game.getFont().getCharacterSize(line.line[i]); | 448 | vec2i charSize = game.getFont().getCharacterSize(line.line[i]); |
388 | SDL_Rect srcRect { charLoc.x(), charLoc.y(), charSize.w(), charSize.h() }; | 449 | SDL_Rect srcRect { charLoc.x(), charLoc.y(), charSize.w(), charSize.h() }; |
diff --git a/src/renderer.h b/src/renderer.h index 17dc038..489a7ec 100644 --- a/src/renderer.h +++ b/src/renderer.h | |||
@@ -152,6 +152,7 @@ private: | |||
152 | texture_ptr renderedTex; | 152 | texture_ptr renderedTex; |
153 | std::vector<int> charIndexToWidth; | 153 | std::vector<int> charIndexToWidth; |
154 | std::string line; | 154 | std::string line; |
155 | std::string overflow; | ||
155 | }; | 156 | }; |
156 | 157 | ||
157 | void renderMessageLine(MessageCache& line, const std::string& text, Game& game); | 158 | void renderMessageLine(MessageCache& line, const std::string& text, Game& game); |
@@ -161,6 +162,11 @@ private: | |||
161 | MessageCache speakerHeaderLine_; | 162 | MessageCache speakerHeaderLine_; |
162 | int advMsgArrowTex_ = -1; | 163 | int advMsgArrowTex_ = -1; |
163 | int choiceArrowTex_ = -1; | 164 | int choiceArrowTex_ = -1; |
165 | |||
166 | // Debug console | ||
167 | texture_ptr debugConsoleTex_; | ||
168 | std::string cachedDebugText_; | ||
169 | SDL_Rect debugDestRect_; | ||
164 | }; | 170 | }; |
165 | 171 | ||
166 | #endif /* end of include guard: RENDERER_H_6A58EC30 */ | 172 | #endif /* end of include guard: RENDERER_H_6A58EC30 */ |
diff --git a/src/script_system.cpp b/src/script_system.cpp index 3293753..14d247e 100644 --- a/src/script_system.cpp +++ b/src/script_system.cpp | |||
@@ -190,6 +190,8 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { | |||
190 | } | 190 | } |
191 | 191 | ||
192 | void ScriptSystem::tick(double dt) { | 192 | void ScriptSystem::tick(double dt) { |
193 | if (game_.isGameplayPaused()) return; | ||
194 | |||
193 | if (callable_ && *callable_) { | 195 | if (callable_ && *callable_) { |
194 | auto result = (*callable_)(dt); | 196 | auto result = (*callable_)(dt); |
195 | if (!result.valid()) { | 197 | if (!result.valid()) { |
@@ -228,3 +230,11 @@ void ScriptSystem::runScript(std::string mapName, std::string scriptName) { | |||
228 | runner_.reset(); | 230 | runner_.reset(); |
229 | } | 231 | } |
230 | } | 232 | } |
233 | |||
234 | void ScriptSystem::runDebugScript(std::string script) { | ||
235 | auto result = engine_.script(script); | ||
236 | if (!result.valid()) { | ||
237 | sol::error e = result; | ||
238 | std::cout << e.what() << std::endl; | ||
239 | } | ||
240 | } | ||
diff --git a/src/script_system.h b/src/script_system.h index 9c901b7..686415c 100644 --- a/src/script_system.h +++ b/src/script_system.h | |||
@@ -20,6 +20,8 @@ public: | |||
20 | 20 | ||
21 | void runScript(std::string mapName, std::string scriptName); | 21 | void runScript(std::string mapName, std::string scriptName); |
22 | 22 | ||
23 | void runDebugScript(std::string script); | ||
24 | |||
23 | private: | 25 | private: |
24 | 26 | ||
25 | Game& game_; | 27 | Game& game_; |