Add "electricity" effect when "hacking" a walker
All checks were successful
Build and Publish WASM version of demo / Build-And-Deploy (push) Successful in 23s

This commit is contained in:
Stephen Seo 2023-08-24 13:53:57 +09:00
parent b113f2ae23
commit 6a0c4d6f37
6 changed files with 159 additions and 5 deletions

View file

@ -20,7 +20,8 @@ SOURCES = \
src/ems.cc \ src/ems.cc \
src/walker.cc \ src/walker.cc \
src/surface_triangle.cc \ src/surface_triangle.cc \
src/screen_walker_hack.cc src/screen_walker_hack.cc \
src/electricity_effect.cc
HEADERS = \ HEADERS = \
src/game.h \ src/game.h \
@ -31,7 +32,8 @@ HEADERS = \
src/ems.h \ src/ems.h \
src/walker.h \ src/walker.h \
src/surface_triangle.h \ src/surface_triangle.h \
src/screen_walker_hack.h src/screen_walker_hack.h \
src/electricity_effect.h
OBJECTS = $(addprefix ${OBJDIR}/,$(subst .cc,.cc.o,${SOURCES})) OBJECTS = $(addprefix ${OBJDIR}/,$(subst .cc,.cc.o,${SOURCES}))

86
src/electricity_effect.cc Normal file
View file

@ -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);
}
}

38
src/electricity_effect.h Normal file
View file

@ -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

View file

@ -49,6 +49,7 @@ TRunnerScreen::TRunnerScreen(std::weak_ptr<ScreenStack> stack)
camera_target{0.0F, 0.0F, 0.0F}, camera_target{0.0F, 0.0F, 0.0F},
mouse_hit{0.0F, 0.0F, 0.0F}, mouse_hit{0.0F, 0.0F, 0.0F},
surface_triangles(), surface_triangles(),
electricityEffects(),
idx_hit(SURFACE_UNIT_WIDTH / 2 + idx_hit(SURFACE_UNIT_WIDTH / 2 +
(SURFACE_UNIT_HEIGHT / 2) * SURFACE_UNIT_WIDTH), (SURFACE_UNIT_HEIGHT / 2) * SURFACE_UNIT_WIDTH),
controlled_walker_idx(std::nullopt), controlled_walker_idx(std::nullopt),
@ -99,6 +100,10 @@ bool TRunnerScreen::update(float dt, bool is_resized) {
if (flags.test(1)) { if (flags.test(1)) {
if (walker_hack_success && controlled_walker_idx.has_value()) { if (walker_hack_success && controlled_walker_idx.has_value()) {
walkers[controlled_walker_idx.value()].set_player_controlled(true); 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 { } else {
controlled_walker_idx.reset(); controlled_walker_idx.reset();
} }
@ -278,6 +283,21 @@ post_check_click:
SURFACE_UNIT_HEIGHT); 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; return false;
} }
@ -319,6 +339,10 @@ bool TRunnerScreen::draw(RenderTexture *render_texture) {
walker.draw(TEMP_cube_model); walker.draw(TEMP_cube_model);
} }
for (auto &ee : electricityEffects) {
ee.draw(GREEN);
}
// TODO DEBUG // TODO DEBUG
if (!controlled_walker_idx.has_value() && !flags.test(0)) { if (!controlled_walker_idx.has_value() && !flags.test(0)) {
DrawLine3D(Vector3{0.0F, 3.0F, 0.0F}, mouse_hit, BLACK); DrawLine3D(Vector3{0.0F, 3.0F, 0.0F}, mouse_hit, BLACK);

View file

@ -14,6 +14,7 @@
// local includes // local includes
#include "common_constants.h" #include "common_constants.h"
#include "electricity_effect.h"
#include "surface_triangle.h" #include "surface_triangle.h"
#include "walker.h" #include "walker.h"
@ -82,6 +83,7 @@ class TRunnerScreen : public Screen {
std::unique_ptr<std::array<SurfaceTriangle, std::unique_ptr<std::array<SurfaceTriangle,
SURFACE_UNIT_WIDTH * SURFACE_UNIT_HEIGHT * 2> > SURFACE_UNIT_WIDTH * SURFACE_UNIT_HEIGHT * 2> >
surface_triangles; surface_triangles;
std::vector<ElectricityEffect> electricityEffects;
unsigned int idx_hit; unsigned int idx_hit;
std::optional<unsigned int> controlled_walker_idx; std::optional<unsigned int> controlled_walker_idx;
const int left_text_width; const int left_text_width;

View file

@ -17,7 +17,8 @@ SOURCES = \
../src/raymath.cc \ ../src/raymath.cc \
../src/walker.cc \ ../src/walker.cc \
../src/surface_triangle.cc \ ../src/surface_triangle.cc \
../src/screen_walker_hack.cc ../src/screen_walker_hack.cc \
../src/electricity_effect.cc
HEADERS = \ HEADERS = \
../src/ems.h \ ../src/ems.h \
@ -28,7 +29,8 @@ HEADERS = \
../src/3d_helpers.h \ ../src/3d_helpers.h \
../src/walker.h \ ../src/walker.h \
../src/surface_triangle.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}))) OBJECTS = $(addprefix ${OBJDIR}/,$(subst ..,PREVDIR,$(subst .cc,.cc.o,${SOURCES})))