]> git.seodisparate.com - RockPaperScissorsDuel/commitdiff
Impl QuestionMark classes with their "animations"
authorStephen Seo <seo.disparate@gmail.com>
Fri, 13 Jan 2023 06:58:03 +0000 (15:58 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Fri, 13 Jan 2023 06:58:03 +0000 (15:58 +0900)
Also added some 3D helper objects.

13 files changed:
CMakeLists.txt
src/3d/obj.cc [new file with mode: 0644]
src/3d/obj.h [new file with mode: 0644]
src/3d/qm.cc [new file with mode: 0644]
src/3d/qm.h [new file with mode: 0644]
src/3d/v3.cc [new file with mode: 0644]
src/3d/v3.h [new file with mode: 0644]
src/3d/v3_conv.cc [new file with mode: 0644]
src/3d/v3_conv.h [new file with mode: 0644]
src/3d_renderer.cc
src/3d_renderer.h
src/constants.h
wasm_build/Makefile

index 826a9187b1638e68b6e3914fba80d859053b1f79..dcae071a0c7edf3d43f0f1061bb0c0d613eb18f6 100644 (file)
@@ -21,6 +21,10 @@ set(RPSDuelNative_SOURCES
     "${CMAKE_CURRENT_SOURCE_DIR}/src/helpers.cc"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/3d_renderer.cc"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/constants.cc"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/obj.cc"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/v3.cc"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/v3_conv.cc"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/qm.cc"
 )
 
 set(RPSDuelNative_HEADERS
@@ -30,6 +34,10 @@ set(RPSDuelNative_HEADERS
     "${CMAKE_CURRENT_SOURCE_DIR}/src/game_renderer.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/basic_renderer.h"
     "${CMAKE_CURRENT_SOURCE_DIR}/src/3d_renderer.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/obj.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/v3.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/v3_conv.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/qm.h"
 )
 
 add_executable(RPSDuelNative ${RPSDuelNative_SOURCES})
diff --git a/src/3d/obj.cc b/src/3d/obj.cc
new file mode 100644 (file)
index 0000000..a5110a1
--- /dev/null
@@ -0,0 +1,34 @@
+#include "obj.h"
+
+Object3D::Object3D(Model *model)
+    : pos{0.0F, 0.0F, 0.0F}, color{255, 255, 255, 255}, model(model) {}
+
+Object3D::~Object3D() {}
+
+const V3 &Object3D::get_pos() const { return pos; }
+
+void Object3D::set_pos(const V3 &pos) { this->pos = pos; }
+
+void Object3D::set_pos(V3 &&pos) { this->pos = std::forward<V3>(pos); }
+
+void Object3D::set_pos_x(float x) { pos[0] = x; }
+
+void Object3D::set_pos_y(float y) { pos[1] = y; }
+
+void Object3D::set_pos_z(float z) { pos[2] = z; }
+
+const VC4 &Object3D::get_color() const { return color; }
+
+void Object3D::set_color(const VC4 &color) { this->color = color; }
+
+void Object3D::set_color(VC4 &&color) {
+  this->color = std::forward<VC4>(color);
+}
+
+void Object3D::set_color_r(unsigned char r) { color[0] = r; }
+
+void Object3D::set_color_g(unsigned char g) { color[1] = g; }
+
+void Object3D::set_color_b(unsigned char b) { color[2] = b; }
+
+void Object3D::set_color_a(unsigned char a) { color[3] = a; }
diff --git a/src/3d/obj.h b/src/3d/obj.h
new file mode 100644 (file)
index 0000000..46e1527
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef ROCK_PAPER_SCISSORS_3D_OBJECT_BASE_H_
+#define ROCK_PAPER_SCISSORS_3D_OBJECT_BASE_H_
+
+// local includes
+#include "v3.h"
+
+// forward declarations
+struct Model;
+
+class Object3D {
+ public:
+  Object3D(Model *model);
+  virtual ~Object3D();
+
+  virtual void update(float dt) = 0;
+  virtual void draw() = 0;
+
+  const V3 &get_pos() const;
+  void set_pos(const V3 &pos);
+  void set_pos(V3 &&pos);
+  void set_pos_x(float x);
+  void set_pos_y(float y);
+  void set_pos_z(float z);
+
+  const VC4 &get_color() const;
+  void set_color(const VC4 &color);
+  void set_color(VC4 &&color);
+  void set_color_r(unsigned char r);
+  void set_color_g(unsigned char g);
+  void set_color_b(unsigned char b);
+  void set_color_a(unsigned char a);
+
+ protected:
+  V3 pos;
+  VC4 color;
+  Model *model;
+};
+
+#endif
diff --git a/src/3d/qm.cc b/src/3d/qm.cc
new file mode 100644 (file)
index 0000000..1601754
--- /dev/null
@@ -0,0 +1,80 @@
+#include "qm.h"
+
+#ifdef __EMSCRIPTEN__
+#include "../ems.h"
+#else
+#include <random>
+#endif
+
+// standard library includes
+#include <cmath>
+
+// local includes
+#include "../constants.h"
+#include "v3_conv.h"
+
+QuestionMark::QuestionMark(Model *m)
+    : Object3D(m)
+#ifndef __EMSCRIPTEN__
+      ,
+      re(std::random_device{}())
+#endif
+{
+  randomize_timer_values();
+}
+
+QuestionMark::~QuestionMark() {}
+
+void QuestionMark::update(float dt) {
+  angle_timer -= dt;
+  if (angle_timer <= 0.0F) {
+#ifdef __EMSCRIPTEN__
+    angle_timer_max =
+        QM_ANGLE_TIMER_MAX + QM_ANGLE_TIMER_VARIANCE * call_js_get_random();
+#else
+    angle_timer_max = QM_ANGLE_TIMER_MAX +
+                      QM_ANGLE_TIMER_VARIANCE *
+                          std::uniform_real_distribution<float>(0.0F, 1.0F)(re);
+#endif
+    angle_timer += angle_timer_max;
+  }
+
+  y_timer -= dt;
+  if (y_timer <= 0.0F) {
+#ifdef __EMSCRIPTEN__
+    y_timer_max = QM_Y_TIMER_MAX + QM_Y_TIMER_VARIANCE * call_js_get_random();
+#else
+    y_timer_max = QM_Y_TIMER_MAX +
+                  QM_Y_TIMER_VARIANCE *
+                      std::uniform_real_distribution<float>(0.0F, 1.0F)(re);
+#endif
+    y_timer += y_timer_max;
+  }
+}
+
+void QuestionMark::draw() {
+  Vector3 unit{1.0F, 1.0F, 1.0F};
+  Vector3 vec3pos = V3ToRV3(pos);
+  float angle = angle_timer / angle_timer_max * 2.0F - 1.0F;
+  angle = angle >= 0.0F ? (std::cos(PI_F * angle) * QM_MAX_ANGLE_OFFSET)
+                        : (std::cos(PI_F * (-angle)) * QM_MAX_ANGLE_OFFSET);
+  float offset = (y_timer / y_timer_max) * 2.0F - 1.0F;
+  offset = offset >= 0.0F
+               ? ((std::cos(PI_F * offset) + 1.0F) / 2.0F * QM_MAX_Y_OFFSET)
+               : ((std::cos(PI_F * (-offset)) + 1.0F) / 2.0F * QM_MAX_Y_OFFSET);
+  vec3pos.y += offset;
+  DrawModelEx(*model, vec3pos, {0.0F, 1.0F, 0.0F}, angle, unit, VC4ToC(color));
+}
+
+void QuestionMark::randomize_timer_values() {
+#ifdef __EMSCRIPTEN__
+  angle_timer = call_js_get_random() * QM_ANGLE_TIMER_MAX;
+  y_timer = call_js_get_random() * QM_Y_TIMER_MAX;
+#else
+  angle_timer =
+      std::uniform_real_distribution<float>(0.0F, QM_ANGLE_TIMER_MAX)(re);
+  y_timer = std::uniform_real_distribution<float>(0.0F, QM_Y_TIMER_MAX)(re);
+#endif
+  angle_timer_max = QM_ANGLE_TIMER_MAX;
+  y_timer_max = QM_Y_TIMER_MAX;
+}
diff --git a/src/3d/qm.h b/src/3d/qm.h
new file mode 100644 (file)
index 0000000..fca0391
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef ROCK_PAPER_SCISSORS_3D_QUESTION_MARK_H_
+#define ROCK_PAPER_SCISSORS_3D_QUESTION_MARK_H_
+
+#include "obj.h"
+
+#ifndef __EMSCRIPTEN__
+#include <random>
+#endif
+
+class QuestionMark : public Object3D {
+ public:
+  QuestionMark(Model *m);
+  ~QuestionMark() override;
+
+  void update(float dt) override;
+  void draw() override;
+
+ private:
+  void randomize_timer_values();
+
+#ifndef __EMSCRIPTEN__
+  std::default_random_engine re;
+#endif
+  float angle_timer;
+  float angle_timer_max;
+  float y_timer;
+  float y_timer_max;
+};
+
+#endif
diff --git a/src/3d/v3.cc b/src/3d/v3.cc
new file mode 100644 (file)
index 0000000..fae3d69
--- /dev/null
@@ -0,0 +1,22 @@
+#include "v3.h"
+
+V3 operator+(const V3 &a, const V3 &b) {
+  return V3{a[0] + b[0], a[1] + b[1], a[2] + b[2]};
+}
+
+V3 operator-(const V3 &a, const V3 &b) {
+  return V3{a[0] - b[0], a[1] - b[1], a[2] - b[2]};
+}
+
+V3 operator*(const V3 &v, float s) { return V3{v[0] * s, v[1] * s, v[2] * s}; }
+
+V3 operator/(const V3 &v, float s) { return V3{v[0] / s, v[1] / s, v[2] / s}; }
+
+float V3F::dotp(const V3 &a, const V3 &b) {
+  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+}
+
+V3 V3F::crossp(const V3 &a, const V3 &b) {
+  return V3{a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2],
+            a[0] * b[1] - a[1] * b[0]};
+}
diff --git a/src/3d/v3.h b/src/3d/v3.h
new file mode 100644 (file)
index 0000000..a03d2da
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef ROCK_PAPER_SCISSORS_3D_V3_H_
+#define ROCK_PAPER_SCISSORS_3D_V3_H_
+
+#include <array>
+
+using V3 = std::array<float, 3>;
+
+V3 operator+(const V3 &a, const V3 &b);
+V3 operator-(const V3 &a, const V3 &b);
+
+V3 operator*(const V3 &v, float s);
+V3 operator/(const V3 &v, float s);
+
+using VC3 = std::array<unsigned char, 3>;
+using VC4 = std::array<unsigned char, 4>;
+
+namespace V3F {
+extern float dotp(const V3 &a, const V3 &b);
+extern V3 crossp(const V3 &a, const V3 &b);
+}  // namespace V3F
+
+#endif
diff --git a/src/3d/v3_conv.cc b/src/3d/v3_conv.cc
new file mode 100644 (file)
index 0000000..6eb61a8
--- /dev/null
@@ -0,0 +1,9 @@
+#include "v3_conv.h"
+
+Vector3 V3ToRV3(const V3 &v) { return Vector3{v[0], v[1], v[2]}; }
+
+V3 RV3ToV3(const Vector3 &v) { return V3{v.x, v.y, v.z}; }
+
+Color VC4ToC(const VC4 &v) { return Color{v[0], v[1], v[2], v[3]}; }
+
+VC4 CToVC4(const Color &c) { return VC4{c.r, c.g, c.b, c.a}; }
diff --git a/src/3d/v3_conv.h b/src/3d/v3_conv.h
new file mode 100644 (file)
index 0000000..72443fa
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef ROCK_PAPER_SCISSORS_3D_V3_CONF_H_
+#define ROCK_PAPER_SCISSORS_3D_V3_CONF_H_
+
+#include "v3.h"
+
+// third party includes
+#include <raylib.h>
+
+extern Vector3 V3ToRV3(const V3 &v);
+extern V3 RV3ToV3(const Vector3 &v);
+
+extern Color VC4ToC(const VC4 &v);
+extern VC4 CToVC4(const Color &c);
+
+#endif
index 229ca019e3fccbf089db92f00d9571997841cf64..f6ee3e72b6edd1148fc0d328f0ca4f62712493ff 100644 (file)
@@ -13,7 +13,9 @@
 #include "helpers.h"
 
 Renderer3D::Renderer3D()
-    : p1_pos{-1.0F, 0.0F, 0.0F},
+    : qms{QuestionMark(&qm_model), QuestionMark(&qm_model)},
+      qm_model(LoadModel("resources/question_mark.obj")),
+      p1_pos{-1.0F, 0.0F, 0.0F},
       p2_pos{1.0F, 0.0F, 0.0F},
       overview_timer(OVERVIEW_TIMER_MAX) {
   camera.position.x = 0.0F;
@@ -43,7 +45,7 @@ Renderer3D::Renderer3D()
 
   skybox_model = LoadModel("resources/skybox.obj");
   platform_model = LoadModel("resources/platform.obj");
-  qm_model = LoadModel("resources/question_mark.obj");
+  // qm_model = LoadModel("resources/question_mark.obj");
   rock_model = LoadModel("resources/rock.obj");
   paper_model = LoadModel("resources/paper.obj");
   scissors_model = LoadModel("resources/scissors.obj");
@@ -60,6 +62,13 @@ Renderer3D::Renderer3D()
   flags.set(1);
   flags.set(4);
   flags.set(5);
+
+  qms.at(0).set_pos({-1.0F, 0.0F, 0.0F});
+  qms.at(0).set_color_g(0);
+  qms.at(0).set_color_b(0);
+  qms.at(1).set_pos({1.0F, 0.0F, 0.0F});
+  qms.at(1).set_color_r(0);
+  qms.at(1).set_color_g(0);
 }
 
 Renderer3D::~Renderer3D() {
@@ -158,6 +167,10 @@ void Renderer3D::update_impl() {
   }
 
   UpdateCamera(&camera);
+
+  for (auto &obj : qms) {
+    obj.update(dt);
+  }
 }
 
 void Renderer3D::draw_impl() {
@@ -166,12 +179,15 @@ void Renderer3D::draw_impl() {
   BeginMode3D(camera);
   DrawModel(skybox_model, root_pos, 1.0F, WHITE);
   DrawModel(platform_model, root_pos, 1.0F, WHITE);
-  DrawModel(qm_model, {-5.0F, 0.0F, 0.0F}, 1.0F, RED);
-  DrawModel(qm_model, {5.0F, 0.0F, 0.0F}, 1.0F, BLUE);
-  DrawModel(rock_model, p1_pos, 1.0F, WHITE);
-  DrawModel(paper_model, p2_pos, 1.0F, WHITE);
-  DrawModel(scissors_model, {-3.0F, 0.0F, 0.0F}, 1.0F, WHITE);
-  DrawModel(scissors_model, {3.0F, 0.0F, 0.0F}, 1.0F, WHITE);
+  // DrawModel(qm_model, {-5.0F, 0.0F, 0.0F}, 1.0F, RED);
+  // DrawModel(qm_model, {5.0F, 0.0F, 0.0F}, 1.0F, BLUE);
+  // DrawModel(rock_model, p1_pos, 1.0F, WHITE);
+  // DrawModel(paper_model, p2_pos, 1.0F, WHITE);
+  // DrawModel(scissors_model, {-3.0F, 0.0F, 0.0F}, 1.0F, WHITE);
+  // DrawModel(scissors_model, {3.0F, 0.0F, 0.0F}, 1.0F, WHITE);
+  for (auto &obj : qms) {
+    obj.draw();
+  }
   EndMode3D();
   DrawText("Testing...", 0, 0, 20, RAYWHITE);
   EndDrawing();
index 741fa6e0e5a4275f02074456bf6cdfc31a8435af..0f8bc78a239b1bac9d8426628fea0ffc47644a6f 100644 (file)
@@ -10,6 +10,9 @@
 // third party includes
 #include <raylib.h>
 
+// local includes
+#include "3d/qm.h"
+
 class Renderer3D : public GameRenderer {
  public:
   Renderer3D();
@@ -30,6 +33,8 @@ class Renderer3D : public GameRenderer {
   void update_impl();
   void draw_impl();
 
+  std::array<QuestionMark, 2> qms;
+
   Camera camera;
 
   Texture2D skybox_texture;
index a752cdd209e2323d0321bb77cc087817f36a425d..fb0d0503732087087a0c024c25137346b9718ec4 100644 (file)
@@ -63,4 +63,13 @@ constexpr float OVERVIEW_ORBIT_RADIUS = 12.0F;
 constexpr float OVERVIEW_ORBIT_Y = 7.0F;
 constexpr float OVERVIEW_ORBIT_MODIFIER = 0.9F;
 
+// src/3D/
+
+constexpr float QM_ANGLE_TIMER_VARIANCE = 2.0F;
+constexpr float QM_Y_TIMER_VARIANCE = 2.0F;
+constexpr float QM_MAX_ANGLE_OFFSET = 30.0F;
+constexpr float QM_MAX_Y_OFFSET = 0.3F;
+constexpr float QM_ANGLE_TIMER_MAX = 5.0F;
+constexpr float QM_Y_TIMER_MAX = 3.5F;
+
 #endif
index f6898b4d7e3255a5d18fa6b0e037d63ec322e59b..898a0e20ce71131a94a448c5c394f3d4bc53fb76 100644 (file)
@@ -10,7 +10,11 @@ SOURCES = \
                ../src/basic_renderer.cc \
                ../src/helpers.cc \
                ../src/3d_renderer.cc \
-               ../src/constants.cc
+               ../src/constants.cc \
+               ../src/3d/obj.cc \
+               ../src/3d/v3.cc \
+               ../src/3d/v3_conv.cc \
+               ../src/3d/qm.cc
 
 HEADERS = \
                ../src/constants.h \
@@ -18,7 +22,11 @@ HEADERS = \
                ../src/basic_renderer.h \
                ../src/helpers.h \
                ../src/game_renderer.h \
-               ../src/3d_renderer.h
+               ../src/3d_renderer.h \
+               ../src/3d/obj.h \
+               ../src/3d/v3.h \
+               ../src/3d/v3_conv.h \
+               ../src/3d/qm.h
 
 CXX = source ${HOME}/git/emsdk/emsdk_env.sh && em++