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
All checks were successful
Build and Publish WASM version of demo / Build-And-Deploy (push) Successful in 23s
This commit is contained in:
parent
b113f2ae23
commit
6a0c4d6f37
6 changed files with 159 additions and 5 deletions
6
Makefile
6
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 \
|
||||
|
@ -31,7 +32,8 @@ HEADERS = \
|
|||
src/ems.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 .cc,.cc.o,${SOURCES}))
|
||||
|
||||
|
|
86
src/electricity_effect.cc
Normal file
86
src/electricity_effect.cc
Normal 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
38
src/electricity_effect.h
Normal 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
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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})))
|
||||
|
||||
|
|
Loading…
Reference in a new issue