]> git.seodisparate.com - RockPaperScissorsDuel/commitdiff
WIP game logic handling drawing state
authorStephen Seo <seo.disparate@gmail.com>
Mon, 2 Jan 2023 08:54:17 +0000 (17:54 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Mon, 2 Jan 2023 08:54:17 +0000 (17:54 +0900)
src/constants.h
src/game.cc
src/game.h

index bc6b8e044bad850be12c38af0575ebd5ba03a6e2..0707fa031aaef8548ab802b572387b4c06fe083b 100644 (file)
@@ -16,4 +16,6 @@ constexpr int ICON_MAX_WIDTH = 100;
 
 constexpr float READY_TIMER_MAX = 1.0F;
 
+constexpr float RESULTS_TIMER_MAX = 1.0F;
+
 #endif
index d91d1fdba4fabedeb9329e698a8b3fff418a6b88..e7f992a6b70954b21dbd5021dfa9fe21d4f2cf4d 100644 (file)
@@ -2,6 +2,7 @@
 
 // standard library includes
 #include <cstring>
+#include <iostream>
 
 // third party includes
 #include <raylib.h>
@@ -18,6 +19,10 @@ Game::Game()
   picked[0] = 0;
   picked[1] = 0;
   picked[2] = 0;
+
+  opponentPicked[0] = 0;
+  opponentPicked[1] = 0;
+  opponentPicked[2] = 0;
 }
 
 void Game::update_state(const char *playerOne, const char *playerTwo,
@@ -25,11 +30,18 @@ void Game::update_state(const char *playerOne, const char *playerTwo,
                         char first_second, char first_third, char second_first,
                         char second_second, char second_third, bool first_ready,
                         bool second_ready, int pos) {
+  // TODO handle changing choices from r/p/s to w/l and etc.
   if (playerOne) {
     this->playerOne = playerOne;
+    opponentPicked[0] = second_first;
+    opponentPicked[1] = second_second;
+    opponentPicked[2] = second_third;
   }
   if (playerTwo) {
     this->playerTwo = playerTwo;
+    opponentPicked[0] = first_first;
+    opponentPicked[1] = first_second;
+    opponentPicked[2] = first_third;
   }
 
   if (std::strcmp(currentPlayer, "undefined") == 0) {
@@ -50,6 +62,24 @@ void Game::update_state(const char *playerOne, const char *playerTwo,
   if (flags.test(0) && flags.test(3) && first_ready && second_ready) {
     flags.reset(3);
     flags.set(4);
+  } else if (flags.test(0) && flags.test(4) && first_first == 0 &&
+             first_second == 0 && first_third == 0 && second_first == 0 &&
+             second_second == 0 && second_third == 0) {
+    flags.reset(0);
+    flags.reset(1);
+    flags.reset(3);
+    flags.reset(4);
+    flags.reset(5);
+    flags.reset(6);
+    flags.reset(7);
+    flags.reset(8);
+
+    readyTimer = 0;
+    resultsTimer = 0;
+
+    picked[0] = 0;
+    picked[1] = 0;
+    picked[2] = 0;
   }
 }
 
@@ -69,14 +99,14 @@ void Game::update_impl() {
     flags.flip(1);
   }
 
-  if (IsMouseButtonPressed(0)) {
+  if (IsMouseButtonPressed(0) && !flags.test(0)) {
     int triple_single_width = GetScreenWidth() / 3.0F + 0.5F;
     if (triple_single_width > ICON_MAX_WIDTH) {
       triple_single_width = ICON_MAX_WIDTH;
     }
 
     // selected Rock
-    if (GetTouchX() >= 0 && GetTouchX() <= triple_single_width &&
+    if (GetTouchX() >= 0 && GetTouchX() <= GetScreenWidth() / 3 &&
         GetTouchY() >= GetScreenHeight() - triple_single_width &&
         GetTouchY() <= GetScreenHeight()) {
       bool set_picked = false;
@@ -92,8 +122,8 @@ void Game::update_impl() {
       }
     }
     // selected Paper
-    else if (GetTouchX() >= triple_single_width &&
-             GetTouchX() <= triple_single_width * 2 &&
+    else if (GetTouchX() >= GetScreenWidth() / 3 &&
+             GetTouchX() <= GetScreenWidth() * 2 / 3 &&
              GetTouchY() >= GetScreenHeight() - triple_single_width &&
              GetTouchY() <= GetScreenHeight()) {
       bool set_picked = false;
@@ -109,7 +139,7 @@ void Game::update_impl() {
       }
     }
     // selected Scissors
-    else if (GetTouchX() >= triple_single_width * 2 &&
+    else if (GetTouchX() >= GetScreenWidth() * 2 / 3 &&
              GetTouchX() <= GetScreenWidth() &&
              GetTouchY() >= GetScreenHeight() - triple_single_width &&
              GetTouchY() <= GetScreenHeight()) {
@@ -126,20 +156,20 @@ void Game::update_impl() {
       }
     }
     // selected Slot 0
-    else if (GetTouchX() >= 0 && GetTouchX() <= triple_single_width &&
+    else if (GetTouchX() >= 0 && GetTouchX() <= GetScreenWidth() / 3 &&
              GetTouchY() >= GetScreenHeight() - triple_single_width * 2 &&
              GetTouchY() <= GetScreenHeight() - triple_single_width) {
       picked[0] = 0;
     }
     // selected Slot 1
-    else if (GetTouchX() >= triple_single_width &&
-             GetTouchX() <= triple_single_width * 2 &&
+    else if (GetTouchX() >= GetScreenWidth() / 3 &&
+             GetTouchX() <= GetScreenWidth() * 2 / 3 &&
              GetTouchY() >= GetScreenHeight() - triple_single_width * 2 &&
              GetTouchY() <= GetScreenHeight() - triple_single_width) {
       picked[1] = 0;
     }
     // selected Slot 2
-    else if (GetTouchX() >= triple_single_width * 2 &&
+    else if (GetTouchX() >= GetScreenWidth() * 2 / 3 &&
              GetTouchX() <= GetScreenWidth() &&
              GetTouchY() >= GetScreenHeight() - triple_single_width * 2 &&
              GetTouchY() <= GetScreenHeight() - triple_single_width) {
@@ -160,13 +190,38 @@ void Game::update_impl() {
 
   if (picked[0] != 0 && picked[1] != 0 && picked[2] != 0) {
     if (flags.test(0)) {
-      status = "Waiting...";
+      if (flags.test(4)) {
+        status.clear();
+      } else {
+        status = "Waiting...";
+      }
     } else {
       status = "Hit Ready!";
     }
   } else {
     status = "Pick Moves!";
   }
+
+  if (flags.test(0) && !flags.test(3) && flags.test(4)) {
+    // updates for result animations
+
+    if (flags.test(5)) {
+      flags.reset(5);
+      resultsTimer = RESULTS_TIMER_MAX;
+    }
+
+    resultsTimer -= GetFrameTime();
+    if (resultsTimer <= 0) {
+      resultsTimer = RESULTS_TIMER_MAX;
+      if (!flags.test(6)) {
+        flags.set(6);
+      } else if (!flags.test(7)) {
+        flags.set(7);
+      } else if (!flags.test(8)) {
+        flags.set(8);
+      }
+    }
+  }
 }
 
 void Game::draw_impl() {
@@ -188,6 +243,45 @@ void Game::draw_impl() {
     }
 
     if (flags.test(0)) {
+      float ratio = 1.0F - resultsTimer / RESULTS_TIMER_MAX;
+      if (!flags.test(6)) {
+        if (ratio < 1.0F) {
+          draw_choice(0, opponentPicked[0], 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, opponentPicked[0], false, triple_single_width);
+        }
+      } else {
+        draw_choice(0, opponentPicked[0], false, triple_single_width);
+      }
+
+      if (!flags.test(7)) {
+        if (ratio < 1.0F) {
+          draw_choice(0, opponentPicked[1], 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, opponentPicked[1], false, triple_single_width);
+        }
+      } else {
+        draw_choice(0, opponentPicked[1], false, triple_single_width);
+      }
+
+      if (!flags.test(8)) {
+        if (ratio < 1.0F) {
+          draw_choice(0, opponentPicked[2], 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, opponentPicked[2], false, triple_single_width);
+        }
+      } else {
+        draw_choice(0, opponentPicked[2], false, triple_single_width);
+      }
     } else {
       unsigned char value = 0;
       if (flags.test(1)) {
@@ -233,69 +327,127 @@ void Game::draw_impl() {
                     {200, 200, 200, 255});
 
       for (unsigned int i = 0; i < 3; ++i) {
-        float x = 0;
-        if (i == 1) {
-          x = (GetScreenWidth() - triple_single_width) / 2.0F;
-        } else if (i == 2) {
-          x = GetScreenWidth() - triple_single_width;
-        }
-        switch (picked[i]) {
-        case 0:
-          break;
-        case 'r':
-          DrawTexturePro(
-              spriteSheet.value(),
-              {ROCK_DIMS[0], ROCK_DIMS[1], ROCK_DIMS[2], ROCK_DIMS[3]},
-              {x, (float)GetScreenHeight() - triple_single_width * 2.0F,
-               triple_single_width, triple_single_width},
-              {0.0F, 0.0F}, 0.0F, WHITE);
-          break;
-        case 'p':
-          DrawTexturePro(
-              spriteSheet.value(),
-              {PAPER_DIMS[0], PAPER_DIMS[1], PAPER_DIMS[2], PAPER_DIMS[3]},
-              {x, (float)GetScreenHeight() - triple_single_width * 2.0F,
-               triple_single_width, triple_single_width},
-              {0.0F, 0.0F}, 0.0F, WHITE);
-          break;
-        case 's':
-          DrawTexturePro(spriteSheet.value(),
-                         {SCISSORS_DIMS[0], SCISSORS_DIMS[1], SCISSORS_DIMS[2],
-                          SCISSORS_DIMS[3]},
-                         {x,
-                          (float)GetScreenHeight() - triple_single_width * 2.0F,
-                          triple_single_width, triple_single_width},
-                         {0.0F, 0.0F}, 0.0F, WHITE);
-          break;
-        default:
-          break;
-        }
+        draw_choice(i, picked[i], true,
+                    (float)GetScreenHeight() - triple_single_width * 2.0F);
       }
 
       DrawRectangle(0, GetScreenHeight() - triple_single_width,
                     GetScreenWidth(), triple_single_width,
                     {127, 127, 127, 255});
-      DrawTexturePro(spriteSheet.value(),
-                     {ROCK_DIMS[0], ROCK_DIMS[1], ROCK_DIMS[2], ROCK_DIMS[3]},
-                     {0.0F, (float)GetScreenHeight() - triple_single_width,
-                      triple_single_width, triple_single_width},
-                     {0.0F, 0.0F}, 0.0F, WHITE);
-      DrawTexturePro(
-          spriteSheet.value(),
-          {PAPER_DIMS[0], PAPER_DIMS[1], PAPER_DIMS[2], PAPER_DIMS[3]},
-          {(GetScreenWidth() - triple_single_width) / 2.0F,
-           (float)GetScreenHeight() - triple_single_width, triple_single_width,
-           triple_single_width},
-          {0.0F, 0.0F}, 0.0F, WHITE);
-      DrawTexturePro(spriteSheet.value(),
-                     {SCISSORS_DIMS[0], SCISSORS_DIMS[1], SCISSORS_DIMS[2],
-                      SCISSORS_DIMS[3]},
-                     {GetScreenWidth() - triple_single_width,
-                      (float)GetScreenHeight() - triple_single_width,
-                      triple_single_width, triple_single_width},
-                     {0.0F, 0.0F}, 0.0F, WHITE);
+      draw_choice(0, 'r', true, (float)GetScreenHeight() - triple_single_width);
+      draw_choice(1, 'p', true, (float)GetScreenHeight() - triple_single_width);
+      draw_choice(2, 's', true, (float)GetScreenHeight() - triple_single_width);
     }
   }
   DrawText(status.c_str(), 0, 0, 20, RAYWHITE);
   EndDrawing();
 }
+
+void Game::draw_choice(const unsigned int idx, const char choice,
+                       const bool using_triple, const float y,
+                       const Color color) {
+  if (!spriteSheet.has_value()) {
+    return;
+  }
+  float x = 0.0F;
+  float width = ICON_MAX_WIDTH;
+  draw_helper_coord(&x, &width, idx, using_triple);
+
+  switch (choice) {
+  case 'r':
+    DrawTexturePro(spriteSheet.value(),
+                   {ROCK_DIMS[0], ROCK_DIMS[1], ROCK_DIMS[2], ROCK_DIMS[3]},
+                   {x, y, width, width}, {0.0F, 0.0F}, 0.0F, color);
+    break;
+  case 'p':
+    DrawTexturePro(spriteSheet.value(),
+                   {PAPER_DIMS[0], PAPER_DIMS[1], PAPER_DIMS[2], PAPER_DIMS[3]},
+                   {x, y, width, width}, {0.0F, 0.0F}, 0.0F, color);
+    break;
+  case 's':
+    DrawTexturePro(spriteSheet.value(),
+                   {SCISSORS_DIMS[0], SCISSORS_DIMS[1], SCISSORS_DIMS[2],
+                    SCISSORS_DIMS[3]},
+                   {x, y, width, width}, {0.0F, 0.0F}, 0.0F, color);
+    break;
+  case '?':
+    DrawTexturePro(spriteSheet.value(),
+                   {QUESTIONMARK_DIMS[0], QUESTIONMARK_DIMS[1],
+                    QUESTIONMARK_DIMS[2], QUESTIONMARK_DIMS[3]},
+                   {x, y, width, width}, {0.0F, 0.0F}, 0.0F, color);
+    break;
+  default:
+    // Should never happen.
+    std::cerr << "WARNING: Invalid choice passed to draw_choice()!"
+              << std::endl;
+    break;
+  }
+}
+
+void Game::draw_qm(const unsigned int idx, const bool using_triple,
+                   const float y, const Color color) {
+  if (!spriteSheet.has_value()) {
+    return;
+  }
+  float x = 0.0F;
+  float width = ICON_MAX_WIDTH;
+  draw_helper_coord(&x, &width, idx, using_triple);
+
+  DrawTexturePro(spriteSheet.value(),
+                 {QUESTIONMARK_DIMS[0], QUESTIONMARK_DIMS[1],
+                  QUESTIONMARK_DIMS[2], QUESTIONMARK_DIMS[3]},
+                 {x, y, width, width}, {0.0F, 0.0F}, 0.0F, color);
+}
+
+void Game::draw_helper_coord(float *x, float *width, const unsigned int idx,
+                             const bool using_triple) {
+  if (x) {
+    *x = 0.0F;
+    *width = ICON_MAX_WIDTH;
+    if (using_triple) {
+      *width = GetScreenWidth() / 3.0F;
+      if (*width > ICON_MAX_WIDTH) {
+        *width = ICON_MAX_WIDTH;
+      }
+
+      switch (idx) {
+      case 0:
+        *x = 0.0F;
+        break;
+      case 1:
+        *x = (GetScreenWidth() - *width) / 2.0F;
+        break;
+      case 2:
+        *x = GetScreenWidth() - *width;
+        break;
+      default:
+        // Should never happen
+        std::cerr << "WARNING: Invalid idx passed to draw_helper_coord()!"
+                  << std::endl;
+        return;
+      }
+    } else {
+      *width = GetScreenWidth() / 5.0F;
+      if (*width > ICON_MAX_WIDTH) {
+        *width = ICON_MAX_WIDTH;
+      }
+
+      switch (idx) {
+      case 0:
+        *x = (GetScreenWidth() - *width * 4.0F) / 2.0F;
+        break;
+      case 1:
+        *x = (GetScreenWidth() - *width * 3.0F) / 2.0F;
+        break;
+      case 2:
+        *x = (GetScreenWidth() - *width * 2.0F) / 2.0F;
+        break;
+      default:
+        // Should never happen.
+        std::cerr << "WARNING: Invalid idx passed to draw_helper_coord()!"
+                  << std::endl;
+        return;
+      }
+    }
+  }
+}
index dd3ecf0baeb36d68f286e5d24a6d122ef5ced5b1..53732241dc0961daabd8c20bdbb3824973080b46 100644 (file)
@@ -25,22 +25,37 @@ private:
   void update_impl();
   void draw_impl();
 
+  void draw_choice(const unsigned int idx, const char choice,
+                   const bool using_triple, const float y,
+                   const Color color = WHITE);
+  void draw_qm(const unsigned int idx, const bool using_triple, const float y,
+               const Color color = WHITE);
+
+  void draw_helper_coord(float *x, float *width, const unsigned int idx,
+                         const bool using_triple);
+
   std::optional<Texture2D> spriteSheet;
   std::string playerOne;
   std::string playerTwo;
   std::string status;
   /*
-   * 0 - ready flag
+   * 0 - ready flag (ready to submit moves)
    * 1 - readyTimer fade to gray (fade to black otherwise)
    * 2 - is spectator
    * 3 - ready flag dirty
    * 4 - animating results
+   * 5 - animating dirty
+   * 6 - revealed first moves
+   * 7 - revealed second moves
+   * 8 - revealed third moves
    */
   std::bitset<32> flags;
   float readyTimer;
+  float resultsTimer;
   int prevPos;
   int cachedPos;
   char picked[3];
+  char opponentPicked[3];
   bool isPlayerOne;
 };