]> git.seodisparate.com - jumpartifact.com_demo_0/commitdiff
Add "electricity" effect when "hacking" a walker
authorStephen Seo <seo.disparate@gmail.com>
Thu, 24 Aug 2023 04:53:57 +0000 (13:53 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Thu, 24 Aug 2023 04:53:57 +0000 (13:53 +0900)
Makefile
src/electricity_effect.cc [new file with mode: 0644]
src/electricity_effect.h [new file with mode: 0644]
src/screen_trunner.cc
src/screen_trunner.h
wasm_build/Makefile

index e1ececd9a5b458987eb37db2f80ab99abab53f7c..ccafaa3354d878e9f013cbf606be6dae0ccef2b8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,8 @@ SOURCES = \
                src/ems.cc \
                src/walker.cc \
                src/surface_triangle.cc \
-               src/screen_walker_hack.cc
+               src/screen_walker_hack.cc \
+               src/electricity_effect.cc
 
 HEADERS = \
                src/game.h \
@@ -30,8 +31,9 @@ HEADERS = \
                src/3d_helpers.h \
                src/ems.h \
                src/walker.h \
-               src/surface_triangle.h\
-               src/screen_walker_hack.h
+               src/surface_triangle.h \
+               src/screen_walker_hack.h \
+               src/electricity_effect.h
 
 OBJECTS = $(addprefix ${OBJDIR}/,$(subst .cc,.cc.o,${SOURCES}))
 
diff --git a/src/electricity_effect.cc b/src/electricity_effect.cc
new file mode 100644 (file)
index 0000000..e449c93
--- /dev/null
@@ -0,0 +1,86 @@
+#include "electricity_effect.h"
+
+// third party includes
+#include <raylib.h>
+#include <raymath.h>
+
+// local includes
+#include "3d_helpers.h"
+#include "ems.h"
+
+ElectricityEffect::ElectricityEffect(Vector3 center, float radius,
+                                     int line_count, float lifetime)
+    : cylinders(),
+      center(center),
+      cylinder_radius(CYLINDER_MAX_RADIUS),
+      lifetime(lifetime),
+      timer(0.0F) {
+  cylinders.reserve(line_count);
+
+  // Generate cylinders.
+  int sub_count = 0;
+  Vector3 dir, pos;
+  for (; line_count > 0; --line_count) {
+    if (sub_count == 0) {
+      dir.x = call_js_get_random() * 2.0F - 1.0F;
+      dir.y = call_js_get_random() * 2.0F - 1.0F;
+      dir.z = call_js_get_random() * 2.0F - 1.0F;
+
+      dir = Vector3Normalize(dir);
+
+      pos = center + dir * (radius * 0.7F);
+
+      dir.x = call_js_get_random() * 2.0F - 1.0F;
+      dir.y = call_js_get_random() * 2.0F - 1.0F;
+      dir.z = call_js_get_random() * 2.0F - 1.0F;
+
+      dir = Vector3Normalize(dir);
+
+      auto coll = GetRayCollisionSphere(
+          Ray{.position = center, .direction = dir}, center, radius);
+
+      cylinders.push_back(Cylinder{.start = pos, .end = coll.point});
+
+      pos = coll.point;
+    } else {
+      dir = Vector3Normalize(center - pos);
+
+      pos = pos + dir * (radius * CYLINDER_EDGE_OFFSET);
+
+      for (unsigned int idx = 0; idx < CYLINDER_SPLIT_COUNT; ++idx) {
+        dir.x = call_js_get_random() * 2.0F - 1.0F;
+        dir.y = call_js_get_random() * 2.0F - 1.0F;
+        dir.z = call_js_get_random() * 2.0F - 1.0F;
+
+        dir = Vector3Normalize(dir);
+
+        auto coll = GetRayCollisionSphere(
+            Ray{.position = pos, .direction = dir}, center, radius);
+
+        cylinders.push_back(Cylinder{.start = pos, .end = coll.point});
+
+        if (idx == CYLINDER_SPLIT_COUNT - 1) {
+          pos = coll.point;
+        }
+      }
+    }
+    if (++sub_count >= CYLINDER_SUB_COUNT_MAX) {
+      sub_count = 0;
+    }
+  }
+}
+
+bool ElectricityEffect::update(float dt) {
+  timer += dt;
+
+  return timer >= lifetime;
+}
+
+void ElectricityEffect::draw(Color color) {
+  float ratio = timer < lifetime ? (1.0F - timer / lifetime) : 0.0F;
+
+  for (const auto &cylinder : cylinders) {
+    DrawCylinderEx(cylinder.start, cylinder.end, CYLINDER_MAX_RADIUS * ratio,
+                   CYLINDER_MAX_RADIUS * ratio, 8, color);
+  }
+}
diff --git a/src/electricity_effect.h b/src/electricity_effect.h
new file mode 100644 (file)
index 0000000..7842fd5
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef JUMPARTIFACT_DOT_COM_DEMO_0_ELECTRICITY_EFFECT_H_
+#define JUMPARTIFACT_DOT_COM_DEMO_0_ELECTRICITY_EFFECT_H_
+
+// standard library includes
+#include <vector>
+
+// third party includes
+#include <raylib.h>
+
+constexpr int CYLINDER_SUB_COUNT_MAX = 3;
+constexpr int CYLINDER_SPLIT_COUNT = 3;
+constexpr int CYLINDER_SIDES = 8;
+constexpr float CYLINDER_MAX_RADIUS = 0.03F;
+constexpr float CYLINDER_EDGE_OFFSET = 0.01F;
+
+class ElectricityEffect {
+ public:
+  ElectricityEffect(Vector3 center, float radius, int line_count,
+                    float lifetime);
+
+  /// Returns true if lifetime ended.
+  bool update(float dt);
+  /// Assumes draw mode is active.
+  void draw(Color color);
+
+ private:
+  struct Cylinder {
+    Vector3 start, end;
+  };
+
+  std::vector<Cylinder> cylinders;
+  Vector3 center;
+  float cylinder_radius;
+  float lifetime;
+  float timer;
+};
+
+#endif
index 91070a4ed14ec790593acff0ef65e82a8161c6a6..967e7d882e0a8f8f7655131c8563a24526a36ce0 100644 (file)
@@ -49,6 +49,7 @@ TRunnerScreen::TRunnerScreen(std::weak_ptr<ScreenStack> stack)
       camera_target{0.0F, 0.0F, 0.0F},
       mouse_hit{0.0F, 0.0F, 0.0F},
       surface_triangles(),
+      electricityEffects(),
       idx_hit(SURFACE_UNIT_WIDTH / 2 +
               (SURFACE_UNIT_HEIGHT / 2) * SURFACE_UNIT_WIDTH),
       controlled_walker_idx(std::nullopt),
@@ -99,6 +100,10 @@ bool TRunnerScreen::update(float dt, bool is_resized) {
   if (flags.test(1)) {
     if (walker_hack_success && controlled_walker_idx.has_value()) {
       walkers[controlled_walker_idx.value()].set_player_controlled(true);
+      electricityEffects.push_back(ElectricityEffect(
+          walkers[controlled_walker_idx.value()].get_body_pos(), 1.7F, 15,
+          1.0F));
+
     } else {
       controlled_walker_idx.reset();
     }
@@ -278,6 +283,21 @@ post_check_click:
                   SURFACE_UNIT_HEIGHT);
   }
 
+  std::vector<decltype(electricityEffects.size())> to_remove;
+  for (decltype(electricityEffects.size()) idx = 0;
+       idx < electricityEffects.size(); ++idx) {
+    if (electricityEffects[idx].update(dt)) {
+      to_remove.push_back(idx);
+    }
+  }
+
+  for (auto iter = to_remove.rbegin(); iter != to_remove.rend(); ++iter) {
+    if (*iter != electricityEffects.size() - 1) {
+      electricityEffects[*iter] = *electricityEffects.rbegin();
+    }
+    electricityEffects.pop_back();
+  }
+
   return false;
 }
 
@@ -319,6 +339,10 @@ bool TRunnerScreen::draw(RenderTexture *render_texture) {
     walker.draw(TEMP_cube_model);
   }
 
+  for (auto &ee : electricityEffects) {
+    ee.draw(GREEN);
+  }
+
   // TODO DEBUG
   if (!controlled_walker_idx.has_value() && !flags.test(0)) {
     DrawLine3D(Vector3{0.0F, 3.0F, 0.0F}, mouse_hit, BLACK);
index 27674cd98a58a65d5b961721406e992c0ef3cb59..7a47347290fdec6751fcee10527e5cb4b7301347 100644 (file)
@@ -14,6 +14,7 @@
 
 // local includes
 #include "common_constants.h"
+#include "electricity_effect.h"
 #include "surface_triangle.h"
 #include "walker.h"
 
@@ -82,6 +83,7 @@ class TRunnerScreen : public Screen {
   std::unique_ptr<std::array<SurfaceTriangle,
                              SURFACE_UNIT_WIDTH * SURFACE_UNIT_HEIGHT * 2> >
       surface_triangles;
+  std::vector<ElectricityEffect> electricityEffects;
   unsigned int idx_hit;
   std::optional<unsigned int> controlled_walker_idx;
   const int left_text_width;
index 2fc73b397dfe4245a7312997556949f607c2507d..aeb738e526d4171bc24e26d3f48bf42f70b41cb2 100644 (file)
@@ -17,7 +17,8 @@ SOURCES = \
                ../src/raymath.cc \
                ../src/walker.cc \
                ../src/surface_triangle.cc \
-               ../src/screen_walker_hack.cc
+               ../src/screen_walker_hack.cc \
+               ../src/electricity_effect.cc
 
 HEADERS = \
                ../src/ems.h \
@@ -28,7 +29,8 @@ HEADERS = \
                ../src/3d_helpers.h \
                ../src/walker.h \
                ../src/surface_triangle.h \
-               ../src/screen_walker_hack.h
+               ../src/screen_walker_hack.h \
+               ../src/electricity_effect.h
 
 OBJECTS = $(addprefix ${OBJDIR}/,$(subst ..,PREVDIR,$(subst .cc,.cc.o,${SOURCES})))