Commit a2e8d30b authored by Georg Schäfer's avatar Georg Schäfer
Browse files

Merge branch 'develop' into feature/22-level-collision-detection

parents 3043db13 57107559
Pipeline #3266 failed with stage
in 2 minutes and 15 seconds
particle: = particles/*.json
particle_def:test_particles = particles/test_particles.json
particle_sys:test_particles = particles/test_particle_system.json
{
"Transform": {
"scale": {
"x": 0.3,
"y": 0.3,
"z": 0.3
}
},
"Model": {
"aid": "model:cube"
},
"Shadowcaster": {
},
"Movement": {
"beats_per_step": 1,
"distance_per_step": 1,
"step_time_percentage": 0.2,
"off_beat_threshold": 0.2
},
"FixedPath": {
}
}
{
"Transform": {
"scale": {
"x": 0.3,
"y": 0.3,
"z": 0.3
}
},
"Model": {
"aid": "model:cube"
},
"Shadowcaster": {
},
"Movement": {
"beats_per_step": 1,
"distance_per_step": 1,
"step_time_percentage": 0.2,
"off_beat_threshold": 0.2
},
"ContinuousPath": {
"direction": 270,
"curvature": 0,
}
}
{
"Transform": {
"scale": {
"x": 0.3,
"y": 0.3,
"z": 0.3
}
},
"Model": {
"aid": "model:cube"
},
"Shadowcaster": {
},
"Movement": {
"beats_per_step": 1,
"distance_per_step": 1,
"step_time_percentage": 0.2,
"off_beat_threshold": 0.2
},
"FollowTarget": {
}
}
......@@ -12,9 +12,10 @@
"Shadowcaster": {},
"Movement": {
"beats_per_step": 1,
"distance_per_step": 1,
"step_time_percentage": 0.2,
"off_beat_threshold": 0.2
"distance_per_step": 5,
"step_time_percentage": 0.3,
"off_beat_threshold": 0.2,
"overshoot": 4
},
"Input_controller": {},
"Player": {},
......
{
"Transform":{
"scale": {"x": 1.0, "y": 1.0, "z": 1.0}
},
"Particle_system": {
"cfg": "particle_sys:test_particles"
}
}
{
"emitters": [{
"spawn": [
{"particles_per_second": 2000, "stddev":0, "time": 1},
{"particles_per_second": 0, "stddev":0, "time": 5}
],
"spawn_loop": true,
"size": {"x":0, "y":0},
"direction": {"mean":{"elevation":0.85, "azimuth":-0.25}, "stddev":{"elevation":0.1, "azimuth":0.1}},
"ttl": {"mean": 4, "stddev": 0.5},
"velocity": {"mean": 32, "stddev": 8.0},
"emit_script_id": "comp_shader:particle_spawn_sphere",
"type_id": "particle_def:test_particles"
}],
"effectors": [
{
"force": 10,
"force_dir": {"y":-1},
"distance_decay": 0,
"scale_with_mass": false
}
]
}
{
"keyframes": [
{
"time": 0,
"color": {"mean":{"hue":0, "saturation":1}, "stddev":{"hue":0.5}},
"size": {"mean": {"x": 0.05, "y":0.15, "z":0.04}, "stddev":{"x": 0.04, "y":0.02, "z":0.02}},
"rotation": {"mean":{"angle":0}, "stddev":{"elevation":1, "azimuth":1, "angle": 1}},
"drag": 0.1
},
{
"time": 4,
"color": {"mean":{"hue":0, "saturation":1}, "stddev":{"hue":1}},
"size": {"mean": {"x": 0.01, "y":0.1, "z":0.01}},
"rotation": {"mean":{"angle":1}, "stddev":{"elevation":1, "azimuth":1, "angle": 1}},
"drag": 1.0
}
],
"symmetric_scaling": true,
"rotate_with_velocity": false,
"blend": "solid",
/*
"geometry": "billboard",
"material_id": "mat:billboard_material.msf",
*/
"geometry": "mesh",
"model_id": "model:cube",
"update_script_id": "comp_shader:particle_update_simple"
}
......@@ -3,12 +3,19 @@
#include "../messages.hpp"
#include <mirrage/utils/log.hpp>
#include <mirrage/utils/min_max.hpp>
namespace phase_shifter::gameplay {
namespace {
constexpr auto beat_time = 1.f;
}
auto smootherstep(float edge0, float edge1, float x)
{
x = std::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
return x * x * x * (x * (x * 6.f - 15.f) + 10.f);
}
} // namespace
Beat_system::Beat_system(mirrage::util::Message_bus& bus) : _bus(bus) {}
......@@ -29,6 +36,20 @@ namespace phase_shifter::gameplay {
_state = {beat, _acc, beat_time - _acc, beat_time, _state.beats_left};
}
auto Beat_system::graphic_time_scale() const -> float
{
constexpr auto t1_len = 0.1f;
constexpr auto t2_len = 0.6f;
constexpr auto factor = (1.f - (1.f - t1_len - t2_len) * 0.01f) / (t1_len + t2_len) * 2.f;
auto to = _state.time_to_beat / _state.avg_beat_time;
auto from = _state.time_to_beat / _state.avg_beat_time;
return mirrage::util::max(0.01f,
factor * (1.f - smootherstep(0.f, t1_len, to)),
factor * (1.f - smootherstep(0.f, t2_len, from)));
}
void Beat_system::decrease_beats_left(int count) { _state.beats_left -= count; }
} // namespace phase_shifter::gameplay
......@@ -11,7 +11,7 @@ namespace phase_shifter::gameplay {
float time_to_beat = 0.f;
float avg_beat_time = 1.f;
int beats_left = 999.f;
int beats_left = 999;
};
// TODO: replace placeholder logic with actual beat detection
......@@ -25,6 +25,8 @@ namespace phase_shifter::gameplay {
void decrease_beats_left(int count);
auto graphic_time_scale() const -> float;
private:
mirrage::util::Message_bus& _bus;
Beat_state _state;
......
#include "continuous_path_comp.hpp"
namespace phase_shifter::gameplay {
float Continuous_path_comp::next_direction() {
float dir = direction;
direction += curvature;
return dir;
}
}
\ No newline at end of file
#pragma once
#include <mirrage/ecs/ecs.hpp>
namespace phase_shifter::gameplay {
struct Continuous_path_comp : public mirrage::ecs::Component<Continuous_path_comp> {
static constexpr const char* name() { return "ContinuousPath"; }
using Component::Component;
float next_direction();
float direction = 0; // angle of direction with 0 beeing North (-Z)
float curvature = 0; // angle of curvature in degrees
};
sf2_structDef(Continuous_path_comp, direction, curvature);
} // namespace phase_shifter::gameplay
\ No newline at end of file
#include "enemy_system.hpp"
#include "movement_comp.hpp"
#include <mirrage/ecs/components/transform_comp.hpp>
namespace phase_shifter::gameplay {
Enemy_system::Enemy_system(mirrage::ecs::Entity_manager& entity_manager) : _entity_manager(entity_manager)
{
_entity_manager.register_component_type<Fixed_path_comp>();
_entity_manager.register_component_type<Follow_target_comp>();
_entity_manager.register_component_type<Continuous_path_comp>();
}
void Enemy_system::update(mirrage::util::Time dt)
{
for (auto&& [movement, fixed_path] : _entity_manager.list<Movement_comp, Fixed_path_comp>()) {
if (!movement.move) {
float rad_direction = fixed_path.next_direction() * mirrage::util::PI / 180.f;
if (rad_direction >= 0) {
movement.aim.x = std::sin(rad_direction);
movement.aim.y = -std::cos(rad_direction);
movement.move = true;
}
}
}
for (auto&&[movement, follow_target, transform] : _entity_manager.list<Movement_comp, Follow_target_comp, mirrage::ecs::components::Transform_comp>()) {
auto target_facet = _entity_manager.get(follow_target.target);
if(target_facet.is_some()) {
auto target_transform = target_facet.get_or_throw().get<mirrage::ecs::components::Transform_comp>();
if(target_transform.is_some()) {
auto& target_position = target_transform.get_or_throw().position;
auto& my_position = transform.position;
movement.aim = glm::vec2({target_position.x - my_position.x, target_position.z - my_position.z});
movement.move = true;
}
}
}
for(auto&& [movement, cont_path] : _entity_manager.list<Movement_comp, Continuous_path_comp>()) {
if(!movement.move) {
float rad_direction = cont_path.next_direction() * mirrage::util::PI / 180.f;
movement.aim.x = std::sin(rad_direction);
movement.aim.y = -std::cos(rad_direction);
movement.move = true;
}
}
}
}
\ No newline at end of file
#pragma once
#include <mirrage/utils/units.hpp>
#include <mirrage/ecs/entity_manager.hpp>
#include "fixed_path_comp.hpp"
#include "follow_target_comp.hpp"
#include "continuous_path_comp.hpp"
namespace phase_shifter::gameplay {
class Enemy_system {
public:
Enemy_system(mirrage::ecs::Entity_manager& entity_manager);
void update(mirrage::util::Time dt);
private:
mirrage::ecs::Entity_manager& _entity_manager;
};
}
\ No newline at end of file
#include "fixed_path_comp.hpp"
namespace phase_shifter::gameplay {
void Fixed_path_comp::update_path(std::vector<float> directions)
{
next_step = 0;
reverse = false;
this->directions = directions;
}
float Fixed_path_comp::next_direction()
{
if(directions.empty()) {
return -1;
}
float dir = directions[next_step];
if(!reverse) {
if(next_step < directions.size() - 1) {
next_step++;
} else {
reverse = true;
}
} else {
if (dir >= 180) {
dir -= 180;
} else {
dir += 180;
}
if(next_step > 0) {
next_step--;
} else {
reverse = false;
}
}
return dir;
}
}
\ No newline at end of file
#pragma once
#include <mirrage/ecs/ecs.hpp>
#include <vector>
namespace phase_shifter::gameplay {
struct Fixed_path_comp : public mirrage::ecs::Component<Fixed_path_comp> {
static constexpr const char* name() { return "FixedPath"; }
using Component::Component;
void update_path(std::vector<float> directions);
float next_direction();
private:
unsigned int next_step = 0; //index of the next step
std::vector<float> directions; //vector containing the steps as angles (degrees) with 0 being North (-Z)
bool reverse = false; //flag wether the path is now traced backwards
};
}
\ No newline at end of file
#pragma once
#include <mirrage/ecs/ecs.hpp>
namespace phase_shifter::gameplay {
struct Follow_target_comp : public mirrage::ecs::Component<Follow_target_comp> {
static constexpr const char* name() { return "FollowTarget"; }
using Component::Component;
mirrage::ecs::Entity_handle target;
};
} // namespace phase_shifter::gameplay
\ No newline at end of file
......@@ -15,14 +15,23 @@ namespace phase_shifter::gameplay {
float distance_per_step = 1.f;
float step_time_percentage = 0.2f;
float off_beat_threshold = 0.f;
float overshoot = 0.1f;
glm::vec2 aim{0.f, 0.f};
bool move = false;
int beats_since_move = 0;
float step_time_left = 0;
float step_time = 0;
glm::vec2 last_step;
glm::vec2 pos_start;
glm::vec2 pos_end;
};
sf2_structDef(Movement_comp, beats_per_step, distance_per_step, step_time_percentage, off_beat_threshold);
sf2_structDef(Movement_comp,
beats_per_step,
distance_per_step,
step_time_percentage,
off_beat_threshold,
overshoot);
} // namespace phase_shifter::gameplay
......@@ -13,6 +13,19 @@ namespace phase_shifter::gameplay {
using mirrage::ecs::components::Transform_comp;
namespace {
float overshoot(float t, float tension)
{
auto a = [](auto t, auto s) { return t * t * ((s + 1) * t - s); };
auto o = [](auto t, auto s) { return t * t * ((s + 1) * t + s); };
if(t < 0.5)
return 0.5 * a(t * 2.0, tension);
else
return 0.5 * (o(t * 2.0 - 2.0, tension) + 2.0);
}
} // namespace
Movement_system::Movement_system(mirrage::util::Message_bus& bus,
mirrage::ecs::Entity_manager& ecs,
const Beat_system& beat_system)
......@@ -47,7 +60,9 @@ namespace phase_shifter::gameplay {
// start movement
move.beats_since_move = 0;
move.step_time_left = beat.avg_beat_time * move.step_time_percentage;
move.last_step = (move.aim / aim_len * move.distance_per_step) / move.step_time_left;
move.step_time = move.step_time_left;
move.last_step =
(aim_len > 1.f ? move.aim / aim_len : move.aim) * move.distance_per_step;
}
} else {
......@@ -56,11 +71,34 @@ namespace phase_shifter::gameplay {
}
}
auto look_dir = move.aim;
if(move.step_time_left > 0.f) {
look_dir = move.last_step;
auto t0 = overshoot(1.f - move.step_time_left / move.step_time, move.overshoot);
move.step_time_left -= dt.value();
transform.position.x += move.last_step.x * dt.value();
transform.position.z += move.last_step.y * dt.value();
auto t1 = overshoot(1.f - move.step_time_left / move.step_time, move.overshoot);
transform.position.x = transform.position.x - move.last_step.x * t0 + move.last_step.x * t1;
transform.position.z = transform.position.z - move.last_step.y * t0 + move.last_step.y * t1;
}
auto look_dir_len = glm::length(look_dir);
if(look_dir_len < 0.001f) {
look_dir = move.last_step;
look_dir_len = glm::length(look_dir);
}
if(look_dir_len > 0.001f) {
look_dir /= look_dir_len;
transform.orientation = glm::normalize(glm::slerp(
transform.orientation,
glm::rotation(glm::vec3{0.f, 0.f, 1.f}, glm::vec3(look_dir.x, 0, look_dir.y)),
std::min(1.f, dt.value() * 4.f * _beat_system.graphic_time_scale())));
}
}
}
......
......@@ -9,11 +9,12 @@ namespace phase_shifter::gameplay {
static constexpr const char* name() { return "Spring"; }
using Component::Component;
glm::vec3 velocity = {0.f, 0.f, 0.f};
float spring_constant = 1.f;
float mass = 1.f;
glm::vec3 velocity = {0.f, 0.f, 0.f};
};
sf2_structDef(Spring_comp, spring_constant);
}
\ No newline at end of file
sf2_structDef(Spring_comp, spring_constant, mass);
} // namespace phase_shifter::gameplay
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment