]> git.seodisparate.com - RockPaperScissorsDuel/commitdiff
Add spritesheet, impl "set-up" before round
authorStephen Seo <seo.disparate@gmail.com>
Mon, 2 Jan 2023 07:51:10 +0000 (16:51 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Mon, 2 Jan 2023 07:51:10 +0000 (16:51 +0900)
resources/rockpaperscissorsSpriteSheet.png [new file with mode: 0644]
src/constants.h
src/ems.cc
src/ems.h
src/game.cc
src/game.h
wasm_build/Makefile
wasm_build/logic.js

diff --git a/resources/rockpaperscissorsSpriteSheet.png b/resources/rockpaperscissorsSpriteSheet.png
new file mode 100644 (file)
index 0000000..ad23d8c
Binary files /dev/null and b/resources/rockpaperscissorsSpriteSheet.png differ
index 56151e0de7ecace04a038772da4f00d1d7a0745b..bc6b8e044bad850be12c38af0575ebd5ba03a6e2 100644 (file)
@@ -4,4 +4,16 @@
 constexpr int DEFAULT_SCREEN_WIDTH = 500;
 constexpr int DEFAULT_SCREEN_HEIGHT = 800;
 
+constexpr int ROCK_DIMS[4] = {0, 0, 32, 32};
+constexpr int PAPER_DIMS[4] = {32, 0, 32, 32};
+constexpr int SCISSORS_DIMS[4] = {64, 0, 32, 32};
+constexpr int READY_DIMS[4] = {0, 32, 192, 56};
+constexpr int QUESTIONMARK_DIMS[4] = {0, 88, 40, 56};
+constexpr int EXCLAMATIONMARKS_DIMS[4] = {40, 88, 32, 56};
+constexpr int OK_DIMS[4] = {72, 88, 80, 56};
+
+constexpr int ICON_MAX_WIDTH = 100;
+
+constexpr float READY_TIMER_MAX = 1.0F;
+
 #endif
index 7dd77741111e8f09c127a80b5b0b82ca19c54728..975a2c2d08e99fda59f889c5c35fa958e75aa63d 100644 (file)
@@ -4,7 +4,7 @@
 #include <emscripten.h>
 #include <emscripten/html5.h>
 
-EM_JS(void, js_set_ready, (), { Rune.actions.set_ready(); });
+EM_JS(void, js_set_ready, (), { Rune.actions.set_ready("unused"); });
 
 EM_JS(void, js_set_choices,
       (const char *first, const char *second, const char *third), {
index 9218531cec862d8583f8d6bca1f646d4db3826d0..41209dbaf270519328587a7310d40bc16dc0377d 100644 (file)
--- a/src/ems.h
+++ b/src/ems.h
@@ -2,7 +2,8 @@
 #define ROCK_PAPER_SCISSORS_DUEL_EMSCRIPTEN_H_
 
 extern void call_js_set_ready();
-extern void call_js_set_choices(const char *first, const char *second, const char *third);
+extern void call_js_set_choices(const char *first, const char *second,
+                                const char *third);
 extern int call_js_get_canvas_width();
 extern int call_js_get_canvas_height();
 
index 438c9c5c1a68537ad9414eb8a6145a1b31bf9954..d91d1fdba4fabedeb9329e698a8b3fff418a6b88 100644 (file)
@@ -6,7 +6,19 @@
 // third party includes
 #include <raylib.h>
 
-Game::Game() : status("Unknown status"), prevPos(0), cachedPos(0) {}
+// local includes
+#include "constants.h"
+#include "ems.h"
+
+Game::Game()
+    : spriteSheet(std::nullopt), status("Unknown status"), readyTimer(0.0F),
+      prevPos(0), cachedPos(0) {
+  spriteSheet = LoadTexture("resources/rockpaperscissorsSpriteSheet.png");
+
+  picked[0] = 0;
+  picked[1] = 0;
+  picked[2] = 0;
+}
 
 void Game::update_state(const char *playerOne, const char *playerTwo,
                         const char *currentPlayer, char first_first,
@@ -21,12 +33,12 @@ void Game::update_state(const char *playerOne, const char *playerTwo,
   }
 
   if (std::strcmp(currentPlayer, "undefined") == 0) {
-    status = "spectator";
+    status = "Watching a Game...";
+    flags.set(2);
   } else if (std::strcmp(currentPlayer, playerOne) == 0) {
-    status = "player one";
   } else if (std::strcmp(currentPlayer, playerTwo) == 0) {
-    status = "player two";
   } else {
+    // This should never happen.
     status = "unknown player";
   }
 
@@ -34,6 +46,11 @@ void Game::update_state(const char *playerOne, const char *playerTwo,
     prevPos = cachedPos;
     cachedPos = pos;
   }
+
+  if (flags.test(0) && flags.test(3) && first_ready && second_ready) {
+    flags.reset(3);
+    flags.set(4);
+  }
 }
 
 void Game::do_update() {
@@ -41,12 +58,244 @@ void Game::do_update() {
   draw_impl();
 }
 
-void Game::update_impl() {}
+void Game::update_impl() {
+  if (flags.test(2)) {
+    return;
+  }
+
+  readyTimer -= GetFrameTime();
+  if (readyTimer <= 0.0F) {
+    readyTimer = READY_TIMER_MAX;
+    flags.flip(1);
+  }
+
+  if (IsMouseButtonPressed(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 &&
+        GetTouchY() >= GetScreenHeight() - triple_single_width &&
+        GetTouchY() <= GetScreenHeight()) {
+      bool set_picked = false;
+      for (unsigned int i = 0; i < 3; ++i) {
+        if (picked[i] == 0) {
+          picked[i] = 'r';
+          set_picked = true;
+          break;
+        }
+      }
+      if (!set_picked) {
+        picked[2] = 'r';
+      }
+    }
+    // selected Paper
+    else if (GetTouchX() >= triple_single_width &&
+             GetTouchX() <= triple_single_width * 2 &&
+             GetTouchY() >= GetScreenHeight() - triple_single_width &&
+             GetTouchY() <= GetScreenHeight()) {
+      bool set_picked = false;
+      for (unsigned int i = 0; i < 3; ++i) {
+        if (picked[i] == 0) {
+          picked[i] = 'p';
+          set_picked = true;
+          break;
+        }
+      }
+      if (!set_picked) {
+        picked[2] = 'p';
+      }
+    }
+    // selected Scissors
+    else if (GetTouchX() >= triple_single_width * 2 &&
+             GetTouchX() <= GetScreenWidth() &&
+             GetTouchY() >= GetScreenHeight() - triple_single_width &&
+             GetTouchY() <= GetScreenHeight()) {
+      bool set_picked = false;
+      for (unsigned int i = 0; i < 3; ++i) {
+        if (picked[i] == 0) {
+          picked[i] = 's';
+          set_picked = true;
+          break;
+        }
+      }
+      if (!set_picked) {
+        picked[2] = 's';
+      }
+    }
+    // selected Slot 0
+    else if (GetTouchX() >= 0 && GetTouchX() <= triple_single_width &&
+             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 &&
+             GetTouchY() >= GetScreenHeight() - triple_single_width * 2 &&
+             GetTouchY() <= GetScreenHeight() - triple_single_width) {
+      picked[1] = 0;
+    }
+    // selected Slot 2
+    else if (GetTouchX() >= triple_single_width * 2 &&
+             GetTouchX() <= GetScreenWidth() &&
+             GetTouchY() >= GetScreenHeight() - triple_single_width * 2 &&
+             GetTouchY() <= GetScreenHeight() - triple_single_width) {
+      picked[2] = 0;
+    }
+    // selected Ready
+    else if (GetTouchX() >= 0 && GetTouchX() <= GetScreenWidth() &&
+             GetTouchY() >= GetScreenHeight() - triple_single_width * 3 &&
+             GetTouchY() <= GetScreenHeight() - triple_single_width * 2) {
+      if (picked[0] != 0 && picked[1] != 0 && picked[2] != 0 &&
+          !flags.test(0)) {
+        call_js_set_ready();
+        flags.set(0);
+        flags.set(3);
+      }
+    }
+  }
+
+  if (picked[0] != 0 && picked[1] != 0 && picked[2] != 0) {
+    if (flags.test(0)) {
+      status = "Waiting...";
+    } else {
+      status = "Hit Ready!";
+    }
+  } else {
+    status = "Pick Moves!";
+  }
+}
 
 void Game::draw_impl() {
+  if (flags.test(2)) {
+    BeginDrawing();
+    ClearBackground(BLACK);
+    DrawText(status.c_str(), 0, 0, 30, RAYWHITE);
+    EndDrawing();
+    return;
+  }
+
   BeginDrawing();
   ClearBackground(BLACK);
-  DrawText("Testing...", 100, 100, 30, RAYWHITE);
-  DrawText(status.c_str(), 0, 200, 30, RAYWHITE);
+  if (spriteSheet.has_value()) {
+    float fifth_width = GetScreenWidth() / 5.0F;
+    float triple_single_width = GetScreenWidth() / 3.0F;
+    if (triple_single_width > (float)ICON_MAX_WIDTH) {
+      triple_single_width = ICON_MAX_WIDTH;
+    }
+
+    if (flags.test(0)) {
+    } else {
+      unsigned char value = 0;
+      if (flags.test(1)) {
+        // fade ready bg to gray
+        value = (1.0F - readyTimer / READY_TIMER_MAX) * 127.0F;
+      } else {
+        // fade ready bg to black
+        value = (readyTimer / READY_TIMER_MAX) * 127.0F;
+      }
+      DrawRectangle(0, GetScreenHeight() - triple_single_width * 3.0F,
+                    GetScreenWidth(), triple_single_width,
+                    {value, value, value, 255});
+
+      DrawTexturePro(
+          spriteSheet.value(),
+          {READY_DIMS[0], READY_DIMS[1], READY_DIMS[2], READY_DIMS[3]},
+          {0, GetScreenHeight() - triple_single_width * 3.0F,
+           GetScreenWidth() - fifth_width, triple_single_width},
+          {0.0F, 0.0F}, 0.0F, WHITE);
+
+      if (flags.test(0)) {
+        // is ready
+        DrawTexturePro(spriteSheet.value(),
+                       {EXCLAMATIONMARKS_DIMS[0], EXCLAMATIONMARKS_DIMS[1],
+                        EXCLAMATIONMARKS_DIMS[2], EXCLAMATIONMARKS_DIMS[3]},
+                       {GetScreenWidth() - fifth_width,
+                        GetScreenHeight() - triple_single_width * 3.0F,
+                        fifth_width, triple_single_width},
+                       {0.0F, 0.0F}, 0.0F, WHITE);
+      } else {
+        // not ready yet
+        DrawTexturePro(spriteSheet.value(),
+                       {QUESTIONMARK_DIMS[0], QUESTIONMARK_DIMS[1],
+                        QUESTIONMARK_DIMS[2], QUESTIONMARK_DIMS[3]},
+                       {GetScreenWidth() - fifth_width,
+                        GetScreenHeight() - triple_single_width * 3.0F,
+                        fifth_width, triple_single_width},
+                       {0.0F, 0.0F}, 0.0F, WHITE);
+      }
+
+      DrawRectangle(0, GetScreenHeight() - triple_single_width * 2.0F,
+                    GetScreenWidth(), triple_single_width,
+                    {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;
+        }
+      }
+
+      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);
+    }
+  }
+  DrawText(status.c_str(), 0, 0, 20, RAYWHITE);
   EndDrawing();
 }
index 969b3ce37eed5fac32bca3b053b9b70b246fe010..dd3ecf0baeb36d68f286e5d24a6d122ef5ced5b1 100644 (file)
@@ -1,31 +1,47 @@
 #ifndef ROCK_PAPER_SCISSORS_DUEL_GAME_H_
 #define ROCK_PAPER_SCISSORS_DUEL_GAME_H_
 
+// standard library includes
+#include <bitset>
+#include <optional>
 #include <string>
 
+// third party includes
+#include <raylib.h>
+
 class Game {
 public:
   Game();
 
-  void update_state(const char *playerOne, const char *playerTwo, const char *currentPlayer,
-               char first_first, char first_second, char first_third,
-               char second_first, char second_second, char second_third,
-               bool first_ready, bool second_ready, int pos);
+  void update_state(const char *playerOne, const char *playerTwo,
+                    const char *currentPlayer, char first_first,
+                    char first_second, char first_third, char second_first,
+                    char second_second, char second_third, bool first_ready,
+                    bool second_ready, int pos);
 
   void do_update();
 
 private:
-
   void update_impl();
   void draw_impl();
 
+  std::optional<Texture2D> spriteSheet;
   std::string playerOne;
   std::string playerTwo;
   std::string status;
+  /*
+   * 0 - ready flag
+   * 1 - readyTimer fade to gray (fade to black otherwise)
+   * 2 - is spectator
+   * 3 - ready flag dirty
+   * 4 - animating results
+   */
+  std::bitset<32> flags;
+  float readyTimer;
   int prevPos;
   int cachedPos;
+  char picked[3];
   bool isPlayerOne;
-
 };
 
 #endif
index 91a6807407245eb82911175e6d2e4695ada2fcd8..8ff9c62ab9a2e3a946df02bb23b2af26c5bf8047 100644 (file)
@@ -10,7 +10,9 @@ SOURCES = \
                ../src/game.cc
 
 HEADERS = \
-               ../src/constants.h
+               ../src/constants.h \
+               ../src/ems.h \
+               ../src/game.h
 
 CXX = source ${HOME}/git/emsdk/emsdk_env.sh && em++
 
@@ -18,12 +20,13 @@ OUTDIR = outdir
 
 all: | format ${OUTDIR} ${OUTDIR}/rock_paper_scissors_duel.html ${OUTDIR}/index.html ${OUTDIR}/logic.js ${OUTDIR}/client.js
 
-${OUTDIR}/rock_paper_scissors_duel.html: ${SOURCES} ${HEADERS} client.js logic.js
+${OUTDIR}/rock_paper_scissors_duel.html: ${SOURCES} ${HEADERS} ${OUTDIR}/client.js ${OUTDIR}/logic.js
        ${CXX} -o ${OUTDIR}/rock_paper_scissors_duel.html \
                -s USE_GLFW=3 -I../wasm_includes -L../wasm_libs -lraylib \
                --shell-file custom_shell.html \
                -sEXPORTED_FUNCTIONS=_main,_game_visual_update \
                -sEXPORTED_RUNTIME_METHODS=ccall \
+               --preload-file ../resources \
                ${OTHER_FLAGS} \
                ${SOURCES}
 
index d9c2ad91c476fe7966ca2f07ee97801e84b0007a..d7250e3efd117cb10b43f31881f2a27699d2704e 100644 (file)
@@ -111,7 +111,7 @@ Rune.initLogic({
                 }
             }
         },
-        set_ready: ({ game, playerId }) => {
+        set_ready: (unused, { game, playerId }) => {
             let is_first = game.player1 === playerId;
 
             if (is_first) {