]> git.seodisparate.com - jumpartifact.com_demo_0/commitdiff
Rework electricity effect (again)
authorStephen Seo <seo.disparate@gmail.com>
Thu, 24 Aug 2023 07:55:43 +0000 (16:55 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Thu, 24 Aug 2023 07:55:43 +0000 (16:55 +0900)
src/electricity_effect.cc
src/electricity_effect.h
src/screen_trunner.cc
src/screen_trunner.h

index 33eebcc586e51af7a1cdbf387c40a95a21806e97..699b422ce4bb33c87ae1c0194605d61718a3bf09 100644 (file)
@@ -2,6 +2,7 @@
 
 // standard library includes
 #include <queue>
+#include <tuple>
 
 // third party includes
 #include <raylib.h>
 
 ElectricityEffect::ElectricityEffect(Vector3 center, float radius,
                                      int line_count, float lifetime)
-    : cylinders(), lifetime(lifetime), timer(0.0F) {
+    : cylinders(),
+      center(center),
+      radius(radius),
+      lifetime(lifetime),
+      timer(0.0F) {
   cylinders.reserve(line_count);
 
+  const float line_max_length = radius * CYLINDER_LINE_MAX_LENGTH_RATIO;
+
   // Generate cylinders.
-  std::queue<Vector3> positions;
-  Vector3 next, dir;
-  for (unsigned int idx = 0; idx < CYLINDER_SPLIT_COUNT; ++idx) {
-    positions.push(center);
+  std::queue<std::tuple<Vector3, int>> positions;
+  std::tuple<Vector3, int> next;
+  Vector3 next_pos, dir;
+  for (unsigned int idx = 0; idx < CYLINDER_SPLIT_COUNT && line_count > 0;
+       ++idx, --line_count) {
+    cylinders.push_back(Cylinder{.next_idx = -1,
+                                 .point = center,
+                                 .mdir = Vector3Normalize(Vector3{
+                                     call_js_get_random() * 2.0F - 1.0F,
+                                     call_js_get_random() * 2.0F - 1.0F,
+                                     call_js_get_random() * 2.0F - 1.0F,
+                                 })});
+    positions.push({center, cylinders.size() - 1});
   }
   while (line_count-- > 0 && !positions.empty()) {
     next = positions.front();
+    next_pos = std::get<Vector3>(next);
     positions.pop();
 
-    dir = Vector3Normalize(center - next);
+    dir = Vector3Normalize(center - next_pos);
     dir = Vector3Normalize(Vector3{call_js_get_random() * 2.0F - 1.0F,
                                    call_js_get_random() * 2.0F - 1.0F,
                                    call_js_get_random() * 2.0F - 1.0F} +
                            dir);
 
-    auto coll = GetRayCollisionSphere(Ray{.position = next, .direction = dir},
-                                      center, radius);
+    auto coll = GetRayCollisionSphere(
+        Ray{.position = next_pos, .direction = dir}, center, radius);
 
-    if (coll.distance > CYLINDER_LINE_MAX_LENGTH) {
+    if (coll.distance > line_max_length) {
       coll.point =
-          next + Vector3Normalize(coll.point - next) * CYLINDER_LINE_MAX_LENGTH;
+          next_pos + Vector3Normalize(coll.point - next_pos) * line_max_length;
     }
 
-    cylinders.push_back(Cylinder{.start = next, .end = coll.point});
+    cylinders.push_back(Cylinder{
+        .next_idx = std::get<int>(next),
+        .point = coll.point,
+        .mdir = Vector3Normalize(Vector3{call_js_get_random() * 2.0F - 1.0F,
+                                         call_js_get_random() * 2.0F - 1.0F,
+                                         call_js_get_random() * 2.0F - 1.0F})});
 
     dir = Vector3Normalize(center - coll.point);
     coll.point = coll.point + dir * (radius * CYLINDER_EDGE_OFFSET);
     for (unsigned int idx = 0; idx < CYLINDER_SPLIT_COUNT; ++idx) {
-      positions.push(coll.point);
+      positions.push({coll.point, cylinders.size() - 1});
     }
   }
 }
@@ -53,6 +75,21 @@ ElectricityEffect::ElectricityEffect(Vector3 center, float radius,
 bool ElectricityEffect::update(float dt) {
   timer += dt;
 
+  for (auto &cylinder : cylinders) {
+    cylinder.point = cylinder.point + cylinder.mdir * (dt * CYLINDER_MOVE_RATE);
+    if (Vector3Distance(cylinder.point, center) > radius) {
+      cylinder.point =
+          cylinder.point - cylinder.mdir * (dt * CYLINDER_MOVE_RATE);
+      Vector3 to_center = center - cylinder.point;
+      Vector3 perpendicular = Vector3Normalize(Vector3Perpendicular(to_center));
+      cylinder.mdir = Vector3Normalize(
+          to_center + Vector3RotateByAxisAngle(perpendicular,
+                                               Vector3Normalize(to_center),
+                                               call_js_get_random() * PI * 2) *
+                          (call_js_get_random() * radius));
+    }
+  }
+
   return timer >= lifetime;
 }
 
@@ -60,7 +97,10 @@ 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, CYLINDER_SIDES, color);
+    if (cylinder.next_idx >= 0) {
+      DrawCylinderEx(cylinder.point, cylinders.at(cylinder.next_idx).point,
+                     CYLINDER_MAX_RADIUS * ratio, CYLINDER_MAX_RADIUS * ratio,
+                     CYLINDER_SIDES, color);
+    }
   }
 }
index bb43010ef354d10eb61670e01688ddf2d39c6d1e..e82d63a0621672e91bb5ce34ebeb014915f35caa 100644 (file)
@@ -11,7 +11,8 @@ constexpr int CYLINDER_SPLIT_COUNT = 3;
 constexpr int CYLINDER_SIDES = 3;
 constexpr float CYLINDER_MAX_RADIUS = 0.03F;
 constexpr float CYLINDER_EDGE_OFFSET = 0.01F;
-constexpr float CYLINDER_LINE_MAX_LENGTH = 1.5F;
+constexpr float CYLINDER_LINE_MAX_LENGTH_RATIO = 0.85F;
+constexpr float CYLINDER_MOVE_RATE = 0.05F;
 
 class ElectricityEffect {
  public:
@@ -25,10 +26,13 @@ class ElectricityEffect {
 
  private:
   struct Cylinder {
-    Vector3 start, end;
+    int next_idx;
+    Vector3 point, mdir;
   };
 
   std::vector<Cylinder> cylinders;
+  Vector3 center;
+  float radius;
   float lifetime;
   float timer;
 };
index 1b9e472ca7abe58ac114ab48584edd71938bc7f2..fea5b55dad315eee3ac8187fb6c78494136725d0 100644 (file)
@@ -101,8 +101,9 @@ bool TRunnerScreen::update(float dt, bool is_resized) {
     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,
-          ELECTRICITY_EFFECT_LINE_COUNT, 1.0F));
+          walkers[controlled_walker_idx.value()].get_body_pos(),
+          ELECTRICITY_EFFECT_RADIUS, ELECTRICITY_EFFECT_LINE_COUNT,
+          ELECTRICITY_EFFECT_LIFETIME));
 
     } else {
       controlled_walker_idx.reset();
index 2289d72f99a3191318312512a2737537a9b4fec9..966cf61e17a847466bce81acbe93efceddc96e5c 100644 (file)
@@ -30,6 +30,8 @@ constexpr float SURFACE_RESET_TIME_TRI_DRAW = 3.0F;
 constexpr float SURFACE_RESET_Y_OFFSET = 40.0F;
 
 constexpr int ELECTRICITY_EFFECT_LINE_COUNT = 35;
+constexpr float ELECTRICITY_EFFECT_RADIUS = 2.0F;
+constexpr float ELECTRICITY_EFFECT_LIFETIME = 3.0F;
 
 class TRunnerScreen : public Screen {
  public: