src/walker.cc \
src/surface_triangle.cc \
src/screen_walker_hack.cc \
- src/electricity_effect.cc
+ src/electricity_effect.cc \
+ src/spark_effect.cc
HEADERS = \
src/game.h \
src/walker.h \
src/surface_triangle.h \
src/screen_walker_hack.h \
- src/electricity_effect.h
+ src/electricity_effect.h \
+ src/spark_effect.h
OBJECTS = $(addprefix ${OBJDIR}/,$(subst .cc,.cc.o,${SOURCES}))
mouse_hit{0.0F, 0.0F, 0.0F},
surface_triangles(),
electricityEffects(),
+ sparkEffects(),
idx_hit(SURFACE_UNIT_WIDTH / 2 +
(SURFACE_UNIT_HEIGHT / 2) * SURFACE_UNIT_WIDTH),
controlled_walker_idx(std::nullopt),
ELECTRICITY_EFFECT_RADIUS, ELECTRICITY_EFFECT_LINE_COUNT,
ELECTRICITY_EFFECT_LIFETIME));
+ sparkEffects.push_back(
+ SparkEffect(SPARK_EFFECT_SPARK_COUNT, SPARK_EFFECT_LIFETIME,
+ walkers[controlled_walker_idx.value()].get_body_pos(),
+ SPARK_EFFECT_XZ_VARIANCE, SPARK_EFFECT_RADIUS));
} else {
controlled_walker_idx.reset();
}
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);
+ {
+ 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();
}
}
- for (auto iter = to_remove.rbegin(); iter != to_remove.rend(); ++iter) {
- if (*iter != electricityEffects.size() - 1) {
- electricityEffects[*iter] = *electricityEffects.rbegin();
+ {
+ std::vector<decltype(sparkEffects.size())> to_remove;
+ for (decltype(sparkEffects.size()) idx = 0; idx < sparkEffects.size();
+ ++idx) {
+ if (sparkEffects[idx].update(dt)) {
+ to_remove.push_back(idx);
+ }
+ }
+
+ for (auto iter = to_remove.rbegin(); iter != to_remove.rend(); ++iter) {
+ if (*iter != sparkEffects.size() - 1) {
+ sparkEffects[*iter] = *sparkEffects.rbegin();
+ }
+ sparkEffects.pop_back();
}
- electricityEffects.pop_back();
}
return false;
ee.draw(GREEN);
}
+ for (auto &se : sparkEffects) {
+ se.draw(GREEN);
+ }
+
// TODO DEBUG
if (!controlled_walker_idx.has_value() && !flags.test(0)) {
DrawLine3D(Vector3{0.0F, 3.0F, 0.0F}, mouse_hit, BLACK);
// local includes
#include "common_constants.h"
#include "electricity_effect.h"
+#include "spark_effect.h"
#include "surface_triangle.h"
#include "walker.h"
constexpr float ELECTRICITY_EFFECT_RADIUS = 2.0F;
constexpr float ELECTRICITY_EFFECT_LIFETIME = 3.0F;
+constexpr int SPARK_EFFECT_SPARK_COUNT = 30;
+constexpr float SPARK_EFFECT_RADIUS = 2.0F;
+constexpr float SPARK_EFFECT_XZ_VARIANCE = 0.5F;
+constexpr float SPARK_EFFECT_LIFETIME = ELECTRICITY_EFFECT_LIFETIME;
+
class TRunnerScreen : public Screen {
public:
struct SurfaceUnit {
SURFACE_UNIT_WIDTH * SURFACE_UNIT_HEIGHT * 2> >
surface_triangles;
std::vector<ElectricityEffect> electricityEffects;
+ std::vector<SparkEffect> sparkEffects;
unsigned int idx_hit;
std::optional<unsigned int> controlled_walker_idx;
const int left_text_width;
--- /dev/null
+#include "spark_effect.h"
+
+// local includes
+#include "3d_helpers.h"
+#include "ems.h"
+
+SparkEffect::SparkEffect(int count, float lifetime, Vector3 pos,
+ float pos_xz_variance, float radius)
+ : sparks(), lifetime(lifetime), timer(0.0F) {
+ Vector3 above_pos = pos;
+ above_pos.y += radius;
+ for (; count > 0; --count) {
+ sparks.push_back(Spark{
+ .pos = pos + Vector3{call_js_get_random() * pos_xz_variance * 2 -
+ pos_xz_variance,
+ 0.0F,
+ call_js_get_random() * pos_xz_variance * 2 -
+ pos_xz_variance},
+ .vel =
+ from_edge_to_sphere_random(above_pos, pos, radius) *
+ (SPARK_VEL_RATE + call_js_get_random() * SPARK_VEL_VARIANCE * 2.0F -
+ SPARK_VEL_VARIANCE)});
+ }
+}
+
+bool SparkEffect::update(float dt) {
+ timer += dt;
+
+ for (auto &spark : sparks) {
+ spark.vel.y -= SPARK_ACC_RATE * dt;
+ spark.pos = spark.pos + spark.vel * dt;
+ }
+
+ return timer > lifetime;
+}
+
+void SparkEffect::draw(Color color) {
+ float ratio = timer < lifetime ? (1.0F - timer / lifetime) : 0.0F;
+
+ for (const auto &spark : sparks) {
+ DrawSphere(spark.pos, SPARK_RADIUS * ratio, color);
+ }
+}
--- /dev/null
+#ifndef JUMPARTIFACT_DOT_COM_DEMO_0_SPARK_EFFECT_H_
+#define JUMPARTIFACT_DOT_COM_DEMO_0_SPARK_EFFECT_H_
+
+// standard library includes
+#include <vector>
+
+// third party includes
+#include <raylib.h>
+
+constexpr float SPARK_RADIUS = 0.03F;
+constexpr float SPARK_VEL_RATE = 5.0F;
+constexpr float SPARK_VEL_VARIANCE = 1.0F;
+constexpr float SPARK_ACC_RATE = 10.0F;
+
+class SparkEffect {
+ public:
+ SparkEffect(int count, float lifetime, Vector3 pos, float pos_xz_variance,
+ float radius);
+
+ /// Returns true if end of lifetime.
+ bool update(float dt);
+
+ /// Assumes draw mode is active when called.
+ void draw(Color color);
+
+ private:
+ struct Spark {
+ Vector3 pos, vel;
+ };
+
+ std::vector<Spark> sparks;
+ float lifetime;
+ float timer;
+};
+
+#endif
../src/walker.cc \
../src/surface_triangle.cc \
../src/screen_walker_hack.cc \
- ../src/electricity_effect.cc
+ ../src/electricity_effect.cc \
+ ../src/spark_effect.cc
HEADERS = \
../src/ems.h \
../src/walker.h \
../src/surface_triangle.h \
../src/screen_walker_hack.h \
- ../src/electricity_effect.h
+ ../src/electricity_effect.h \
+ ../src/spark_effect.h
OBJECTS = $(addprefix ${OBJDIR}/,$(subst ..,PREVDIR,$(subst .cc,.cc.o,${SOURCES})))