From d1e26006c9b855693430747f52815be00e6998c3 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Wed, 4 Jan 2023 13:55:25 +0900 Subject: [PATCH] Impl spectator view, refactorings/fixes --- src/constants.h | 2 + src/game.cc | 232 +++++++++++++++++++++++++++++++++--------------- src/game.h | 6 +- src/helpers.cc | 16 ++++ src/helpers.h | 4 +- src/main.cc | 3 +- 6 files changed, 190 insertions(+), 73 deletions(-) diff --git a/src/constants.h b/src/constants.h index 5c0cc33..31f2869 100644 --- a/src/constants.h +++ b/src/constants.h @@ -22,4 +22,6 @@ constexpr float SCORE_CHANGE_TIMER_MAX = 1.0F; constexpr float REQUEST_TIMER_MAX = 3.0F; +constexpr int DEFAULT_STATUS_TEXT_SIZE = 30; + #endif diff --git a/src/game.cc b/src/game.cc index a4dc25f..8c0e775 100644 --- a/src/game.cc +++ b/src/game.cc @@ -13,10 +13,10 @@ #include "helpers.h" Game::Game() - : spriteSheet(std::nullopt), status("Unknown status"), prevTime(0.0), - readyTimer(0.0F), resultsTimer(RESULTS_TIMER_MAX), - scoreChangeTimer(SCORE_CHANGE_TIMER_MAX), requestTimer(REQUEST_TIMER_MAX), - prevPos(0), cachedPos(0) { + : spriteSheet(std::nullopt), status("Unknown status"), readyTimer(0.0F), + resultsTimer(RESULTS_TIMER_MAX), scoreChangeTimer(SCORE_CHANGE_TIMER_MAX), + requestTimer(REQUEST_TIMER_MAX), prevPos(0), cachedPos(0), + statusSize(DEFAULT_STATUS_TEXT_SIZE) { spriteSheet = LoadTexture("resources/rockpaperscissorsSpriteSheet.png"); picked[0] = 0; @@ -86,12 +86,30 @@ void Game::update_state(const char *playerOne, const char *playerTwo, if (std::strcmp(currentPlayer, "undefined") == 0) { status = "Watching a Game..."; + statusSize = Helpers::getFitableSize( + status.c_str(), DEFAULT_STATUS_TEXT_SIZE, GetScreenWidth()); flags.set(2); + if (Helpers::isValidChoice(first_first) && + Helpers::isValidChoice(first_second) && + Helpers::isValidChoice(first_third)) { + picked[0] = first_first; + picked[1] = first_second; + picked[2] = first_third; + } + if (Helpers::isValidChoice(second_first) && + Helpers::isValidChoice(second_second) && + Helpers::isValidChoice(second_third)) { + opponentPicked[0] = second_first; + opponentPicked[1] = second_second; + opponentPicked[2] = second_third; + } } else if (std::strcmp(currentPlayer, playerOne) == 0) { } else if (std::strcmp(currentPlayer, playerTwo) == 0) { } else { // This should never happen. status = "unknown player"; + statusSize = Helpers::getFitableSize( + status.c_str(), DEFAULT_STATUS_TEXT_SIZE, GetScreenWidth()); } if (cachedPos != pos) { @@ -105,22 +123,18 @@ void Game::do_update() { draw_impl(); } -void Game::update_impl() { - if (flags.test(2)) { - return; - } - - float dt = 0.0F; - { - double timeNow = GetTime(); - dt = timeNow - prevTime; - prevTime = timeNow; - } +void Game::screen_size_changed() { flags.set(13); } - readyTimer -= dt; - if (readyTimer <= 0.0F) { - readyTimer = READY_TIMER_MAX; - flags.flip(1); +void Game::update_impl() { + const float dt = GetFrameTime(); + + if (flags.test(13)) { + flags.reset(13); + statusSize = + !status.empty() + ? Helpers::getFitableSize(status.c_str(), DEFAULT_STATUS_TEXT_SIZE, + GetScreenWidth()) + : DEFAULT_STATUS_TEXT_SIZE; } if (prevPos != cachedPos) { @@ -131,6 +145,65 @@ void Game::update_impl() { } } + if (flags.test(2)) { + if (!flags.test(4) && Helpers::isValidChoice(picked[0]) && + Helpers::isValidChoice(picked[1]) && + Helpers::isValidChoice(picked[2]) && + Helpers::isValidChoice(opponentPicked[0]) && + Helpers::isValidChoice(opponentPicked[1]) && + Helpers::isValidChoice(opponentPicked[2])) { + flags.set(4); + flags.set(5); + resultsTimer = RESULTS_TIMER_MAX; + } else if (flags.test(4)) { + resultsTimer -= dt; + if (resultsTimer <= 0.0F) { + resultsTimer = RESULTS_TIMER_MAX; + if (!flags.test(6)) { + flags.set(6); + flags.set(9); + } else if (!flags.test(7)) { + flags.set(7); + flags.set(9); + } else if (!flags.test(8)) { + flags.set(8); + flags.set(9); + } else { + flags.reset(4); + flags.reset(5); + flags.reset(6); + flags.reset(7); + flags.reset(8); + flags.reset(9); + flags.reset(10); + flags.reset(11); + picked[0] = '?'; + picked[1] = '?'; + picked[2] = '?'; + opponentPicked[0] = '?'; + opponentPicked[1] = '?'; + opponentPicked[2] = '?'; + } + } + } + + if (IsMouseButtonPressed(0)) { + // TODO DEBUG + // if (GetTouchX() >= 0 && GetTouchX() <= 100 && GetTouchY() >= 0 && + // GetTouchY() <= 100) { + // std::clog << "flags: " << flags.to_string().substr(32 - 14) + // << std::endl; + //} + } + return; + } + + readyTimer -= dt; + if (readyTimer <= 0.0F) { + readyTimer = READY_TIMER_MAX; + flags.flip(1); + } + if (IsMouseButtonPressed(0) && !flags.test(0)) { int triple_single_width = GetScreenWidth() / 3.0F + 0.5F; if (triple_single_width > ICON_MAX_WIDTH) { @@ -224,14 +297,21 @@ void Game::update_impl() { if (flags.test(0)) { if (flags.test(4)) { status.clear(); + statusSize = DEFAULT_STATUS_TEXT_SIZE; } else { status = "Waiting..."; + statusSize = Helpers::getFitableSize( + status.c_str(), DEFAULT_STATUS_TEXT_SIZE, GetScreenWidth()); } } else { status = "Hit Ready!"; + statusSize = Helpers::getFitableSize( + status.c_str(), DEFAULT_STATUS_TEXT_SIZE, GetScreenWidth()); } } else { status = "Pick Moves!"; + statusSize = Helpers::getFitableSize( + status.c_str(), DEFAULT_STATUS_TEXT_SIZE, GetScreenWidth()); } if (flags.test(0) && flags.test(3) && flags.test(10) && flags.test(11)) { @@ -324,7 +404,18 @@ void Game::draw_impl() { BeginDrawing(); ClearBackground(BLACK); draw_score(); - DrawText(status.c_str(), 0, 20, 30, RAYWHITE); + DrawText(status.c_str(), 0, 20, statusSize, RAYWHITE); + + if (flags.test(4)) { + if (flags.test(5)) { + flags.reset(5); + } + + float triple_single_width = GetScreenWidth() / 3.0F; + draw_reveal_choices(opponentPicked, triple_single_width); + draw_reveal_choices(picked, triple_single_width * 2.0F); + } + EndDrawing(); return; } @@ -342,55 +433,7 @@ void Game::draw_impl() { draw_choice(0, picked[0], false, triple_single_width * 2.0F, WHITE); draw_choice(1, picked[1], false, triple_single_width * 2.0F, WHITE); draw_choice(2, picked[2], false, triple_single_width * 2.0F, WHITE); - float ratio = 1.0F - resultsTimer / RESULTS_TIMER_MAX; - char otherPicked = - Helpers::isValidChoice(opponentPicked[0]) ? opponentPicked[0] : '?'; - if (!flags.test(6)) { - if (ratio < 1.0F) { - draw_choice(0, otherPicked, false, triple_single_width, - {255, 255, 255, (unsigned char)(ratio * 255.0F)}); - draw_qm(0, false, triple_single_width, - {255, 255, 255, (unsigned char)((1.0F - ratio) * 255.0f)}); - } else { - draw_choice(0, otherPicked, false, triple_single_width); - } - } else { - draw_choice(0, otherPicked, false, triple_single_width); - } - - otherPicked = - Helpers::isValidChoice(opponentPicked[1]) ? opponentPicked[1] : '?'; - if (!flags.test(7)) { - if (!flags.test(6)) { - draw_qm(1, false, triple_single_width, WHITE); - } else if (ratio < 1.0F) { - draw_choice(1, otherPicked, false, triple_single_width, - {255, 255, 255, (unsigned char)(ratio * 255.0F)}); - draw_qm(1, false, triple_single_width, - {255, 255, 255, (unsigned char)((1.0F - ratio) * 255.0f)}); - } else { - draw_choice(1, otherPicked, false, triple_single_width); - } - } else { - draw_choice(1, otherPicked, false, triple_single_width); - } - - otherPicked = - Helpers::isValidChoice(opponentPicked[2]) ? opponentPicked[2] : '?'; - if (!flags.test(8)) { - if (!flags.test(7)) { - draw_qm(2, false, triple_single_width, WHITE); - } else if (ratio < 1.0F) { - draw_choice(2, otherPicked, false, triple_single_width, - {255, 255, 255, (unsigned char)(ratio * 255.0F)}); - draw_qm(2, false, triple_single_width, - {255, 255, 255, (unsigned char)((1.0F - ratio) * 255.0f)}); - } else { - draw_choice(2, otherPicked, false, triple_single_width); - } - } else { - draw_choice(2, otherPicked, false, triple_single_width); - } + draw_reveal_choices(opponentPicked, triple_single_width); } else { // flags.test(0) unsigned char value = 0; if (flags.test(1)) { @@ -451,7 +494,7 @@ void Game::draw_impl() { } } draw_score(); - DrawText(status.c_str(), 0, 20, 20, RAYWHITE); + DrawText(status.c_str(), 0, 20, statusSize, RAYWHITE); EndDrawing(); } @@ -593,3 +636,52 @@ void Game::draw_score() const { DrawText(&buf[3], 0, 0, 20, WHITE); } } + +void Game::draw_reveal_choices(const char p[3], const float y) { + float ratio = 1.0F - resultsTimer / RESULTS_TIMER_MAX; + char otherPicked = Helpers::isValidChoice(p[0]) ? p[0] : '?'; + if (!flags.test(6)) { + if (ratio < 1.0F) { + draw_choice(0, otherPicked, false, y, + {255, 255, 255, (unsigned char)(ratio * 255.0F)}); + draw_qm(0, false, y, + {255, 255, 255, (unsigned char)((1.0F - ratio) * 255.0f)}); + } else { + draw_choice(0, otherPicked, false, y); + } + } else { + draw_choice(0, otherPicked, false, y); + } + + otherPicked = Helpers::isValidChoice(p[1]) ? p[1] : '?'; + if (!flags.test(7)) { + if (!flags.test(6)) { + draw_qm(1, false, y, WHITE); + } else if (ratio < 1.0F) { + draw_choice(1, otherPicked, false, y, + {255, 255, 255, (unsigned char)(ratio * 255.0F)}); + draw_qm(1, false, y, + {255, 255, 255, (unsigned char)((1.0F - ratio) * 255.0f)}); + } else { + draw_choice(1, otherPicked, false, y); + } + } else { + draw_choice(1, otherPicked, false, y); + } + + otherPicked = Helpers::isValidChoice(p[2]) ? p[2] : '?'; + if (!flags.test(8)) { + if (!flags.test(7)) { + draw_qm(2, false, y, WHITE); + } else if (ratio < 1.0F) { + draw_choice(2, otherPicked, false, y, + {255, 255, 255, (unsigned char)(ratio * 255.0F)}); + draw_qm(2, false, y, + {255, 255, 255, (unsigned char)((1.0F - ratio) * 255.0f)}); + } else { + draw_choice(2, otherPicked, false, y); + } + } else { + draw_choice(2, otherPicked, false, y); + } +} diff --git a/src/game.h b/src/game.h index 4c49997..f95fa41 100644 --- a/src/game.h +++ b/src/game.h @@ -21,6 +21,8 @@ public: void do_update(); + void screen_size_changed(); + private: void update_impl(); void draw_impl(); @@ -38,12 +40,12 @@ private: bool is_opponent_choices_set() const; void draw_score() const; + void draw_reveal_choices(const char p[3], const float y); std::optional spriteSheet; std::string playerOne; std::string playerTwo; std::string status; - double prevTime; /* * 0 - ready flag (ready to submit moves) * 1 - readyTimer fade to gray (fade to black otherwise) @@ -58,6 +60,7 @@ private: * 10 - first ready * 11 - second ready * 12 - ready state dirty + * 13 - screen size changed */ std::bitset<32> flags; float readyTimer; @@ -66,6 +69,7 @@ private: float requestTimer; int prevPos; int cachedPos; + int statusSize; char picked[3]; char opponentPicked[3]; bool isPlayerOne; diff --git a/src/helpers.cc b/src/helpers.cc index d8c277e..0d9a9de 100644 --- a/src/helpers.cc +++ b/src/helpers.cc @@ -1,5 +1,21 @@ #include "helpers.h" +// third party includes +#include + bool Helpers::isValidChoice(char choice) { return choice == 'r' || choice == 'p' || choice == 's'; } + +int Helpers::getFitableSize(const char *text, const int default_size, + const int width) { + int size = default_size; + while (MeasureText(text, size) > width) { + --size; + if (size <= 8) { + break; + } + } + + return size; +} diff --git a/src/helpers.h b/src/helpers.h index 9dcc0ce..a98027e 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -4,7 +4,9 @@ namespace Helpers { extern bool isValidChoice(char choice); +extern int getFitableSize(const char *text, const int default_size, + const int width); -} +} // namespace Helpers #endif diff --git a/src/main.cc b/src/main.cc index f0ecff5..eddd6f6 100644 --- a/src/main.cc +++ b/src/main.cc @@ -39,6 +39,7 @@ EM_BOOL resize_event_callback(int event_type, const EmscriptenUiEvent *event, void *ud) { if (event_type == EMSCRIPTEN_EVENT_RESIZE) { SetWindowSize(call_js_get_canvas_width(), call_js_get_canvas_height()); + ((Game *)ud)->screen_size_changed(); } return false; } @@ -61,7 +62,7 @@ int main() { SetWindowSize(call_js_get_canvas_width(), call_js_get_canvas_height()); - emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, false, + emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, &game, false, resize_event_callback); emscripten_set_main_loop_arg(game_update, &game, 0, 1); -- 2.49.0