Commit 7fc5aa65 authored by Florian Oetke's avatar Florian Oetke

smooth entity movement

parent 2a815341
particle: = particles/*.json
particle_def:test_particles = particles/test_particles.json
particle_sys:test_particles = particles/test_particle_system.json
......@@ -9,9 +9,10 @@
},
"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
......@@ -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;
......
......@@ -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 {
......@@ -57,10 +72,14 @@ namespace phase_shifter::gameplay {
}
if(move.step_time_left > 0.f) {
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;
}
}
}
......
......@@ -15,5 +15,6 @@ namespace phase_shifter::gameplay {
float mass = 1.f;
};
sf2_structDef(Spring_comp, spring_constant);
}
\ No newline at end of file
sf2_structDef(Spring_comp, spring_constant, mass);
} // namespace phase_shifter::gameplay
......@@ -25,7 +25,7 @@ namespace phase_shifter::level {
.position(glm::rotate(cam_dir, glm::vec3(0, 0, -1)) * 8.f + position)
.post_create([=](ecs::Entity_facet entity) {
entity.process<Transform_comp>([&](auto& transform) {
transform.position = transform.direction() * -10.f + position;
transform.position = transform.direction() * -15.f + position;
transform.look_at(position);
});
entity.process([=](gameplay::Viewtarget_comp& viewtarget) {
......
......@@ -91,6 +91,7 @@ namespace phase_shifter {
.position(glm::rotate(sun_dir, glm::vec3(0, 0, 1)) * 40.f)
.create();
entities().entity_builder("test_particle_emitter").position(glm::vec3(11, 0, 11)).create();
_level_system->load("dummy");
}
......@@ -116,7 +117,7 @@ namespace phase_shifter {
_hud_system->update(dt);
_model_loading->update(dt);
_renderer->update(dt);
_renderer->update(dt * _beat_system->graphic_time_scale());
}
void Meta_system::draw()
{
......
Markdown is supported
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