Commit 1296e68c authored by Kevin Balz's avatar Kevin Balz
Browse files

merge

parents e1a5942d 0eb27437
Pipeline #3292 failed with stage
in 4 minutes and 30 seconds
......@@ -15,7 +15,7 @@
"beats_per_step": 1,
"distance_per_step": 1,
"step_time_percentage": 0.2,
"off_beat_threshold": 0.2
"off_beat_threshold": 0.0
},
"Killable": {
},
......
......@@ -15,10 +15,10 @@
"beats_per_step": 1,
"distance_per_step": 1,
"step_time_percentage": 0.2,
"off_beat_threshold": 0.2
"off_beat_threshold": 0.0
},
"ContinuousPath": {
"direction": 270,
"curvature": 0,
"curvature": 0
}
}
......@@ -15,7 +15,7 @@
"beats_per_step": 1,
"distance_per_step": 1,
"step_time_percentage": 0.2,
"off_beat_threshold": 0.2
"off_beat_threshold": 0.0
},
"FollowTarget": {
},
......
......@@ -23,6 +23,6 @@
"attack_width": 0.8
},
"Rigid_body": {
"radius": 1.0
"radius": 0.5
}
}
......@@ -32,21 +32,22 @@ namespace phase_shifter::gameplay {
void Beat_system::update(mirrage::util::Time dt)
{
_acc += dt.value();
auto beat = _beat_index + 1 < _time_stamps.size() && _acc >= _time_stamps[_beat_index + 1];
int size = static_cast<int>(_time_stamps.size());
auto beat = _beat_index + 1 < size && _acc >= _time_stamps[_beat_index + 1];
if(beat) {
_beat_index++;
LOG(plog::debug) << "beat";
if(_beat_index + 1 >= _time_stamps.size()) {
if(_beat_index + 1 >= size) {
_bus.send<Lose_msg>();
}
}
_state = {beat,
_beat_index >= 0 ? _acc - _time_stamps[_beat_index] : _acc,
_beat_index + 1 < _time_stamps.size() ? _time_stamps[_beat_index + 1] - _acc : 999,
_beat_index + 1 < size ? _time_stamps[_beat_index + 1] - _acc : 999,
_state.avg_beat_time,
static_cast<int>(_time_stamps.size()) - 1 - _beat_index
size - 1 - _beat_index
};
}
......@@ -64,6 +65,15 @@ namespace phase_shifter::gameplay {
factor * (1.f - smootherstep(0.f, t2_len, from)));
}
void Beat_system::decrease_beats_left(int count) { _state.beats_left -= count; }
void Beat_system::decrease_beats_left(int count)
{
if(_state.beats_left > 0) {
_state.beats_left -= count;
if(_state.beats_left <= 0) {
_bus.send<Lose_msg>();
}
}
}
} // namespace phase_shifter::gameplay
......@@ -71,20 +71,10 @@ namespace phase_shifter::gameplay {
angle);
glm::vec2 topleft(center.x - width / 2, center.y + height / 2);
std::cout << angle * 180 / 3.14 << std::endl;
for(auto&& [entity, k_transform, kill] :
_ecs.list<Entity_handle, Transform_comp, Killable_comp>()) {
auto circle = rotate_point({k_transform.position.x, k_transform.position.z}, angle);
if(rect_circle_intersects(
topleft.x,
topleft.y,
width,
height,
circle.x,
circle.y,
1))
{
if(rect_circle_intersects(topleft.x, topleft.y, width, height, circle.x, circle.y, 1)) {
_ecs.erase(entity);
}
}
......@@ -105,4 +95,4 @@ namespace phase_shifter::gameplay {
}
}
}
} // namespace phase_shifter::gameplay
\ No newline at end of file
} // namespace phase_shifter::gameplay
......@@ -23,8 +23,7 @@ namespace phase_shifter::gameplay {
float step_time_left = 0;
float step_time = 0;
glm::vec2 last_step;
glm::vec2 pos_start;
glm::vec2 pos_end;
glm::vec2 last_aim;
};
sf2_structDef(Movement_comp,
......
......@@ -3,6 +3,10 @@
#include "beat_system.hpp"
#include "combat_system.hpp"
#include "movement_comp.hpp"
#include "rigid_body_comp.hpp"
#include "../level/level_system.hpp"
#include "../messages.hpp"
#include <mirrage/ecs/components/transform_comp.hpp>
#include <mirrage/ecs/ecs.hpp>
......@@ -11,6 +15,7 @@
namespace phase_shifter::gameplay {
using namespace mirrage::ecs;
using mirrage::ecs::components::Transform_comp;
namespace {
......@@ -28,8 +33,9 @@ namespace phase_shifter::gameplay {
Movement_system::Movement_system(mirrage::util::Message_bus& bus,
mirrage::ecs::Entity_manager& ecs,
const Beat_system& beat_system)
: _bus(bus), _ecs(ecs), _beat_system(beat_system)
const Beat_system& beat_system,
const level::Level_system& level_system)
: _bus(bus), _ecs(ecs), _beat_system(beat_system), _level_system(level_system)
{
_ecs.register_component_type<Movement_comp>();
}
......@@ -38,13 +44,11 @@ namespace phase_shifter::gameplay {
{
auto beat = _beat_system.beat_state();
for(auto&& [transform, move] : _ecs.list<Transform_comp, Movement_comp>()) {
for(auto&& [entity, transform, move] : _ecs.list<Entity_facet, Transform_comp, Movement_comp>()) {
if(beat.beat) {
move.beats_since_move++;
}
auto allowed = (beat.beat || beat.time_since_beat <= move.off_beat_threshold
|| beat.time_to_beat <= move.off_beat_threshold)
&& move.beats_since_move >= move.beats_per_step;
......@@ -74,25 +78,42 @@ 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);
auto t0 = overshoot(1.f - move.step_time_left / move.step_time, move.overshoot);
move.step_time_left -= 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 offset = -move.last_step * t0 + move.last_step * t1;
auto pos = glm::vec2(transform.position.x, transform.position.z);
entity.process([&](Rigid_body_comp& body) {
_level_system.check_contacts(pos + offset, body.radius, [&](util::Contact contact) {
if(contact.distance2 <= 0.0001f) {
offset = glm::vec2(0, 0);
_bus.send<Entity_hit_wall>(entity.handle());
} else if(auto normal_vel = glm::dot(offset, contact.normal); normal_vel > 0) {
offset -= normal_vel * contact.normal;
_bus.send<Entity_hit_wall>(entity.handle());
}
});
});
look_dir = offset;
transform.position.x = pos.x + offset.x;
transform.position.z = pos.y + offset.y;
}
auto look_dir_len = glm::length(look_dir);
if(look_dir_len < 0.001f) {
look_dir = move.last_step;
look_dir = move.last_aim;
look_dir_len = glm::length(look_dir);
}
if(look_dir_len > 0.001f) {
move.last_aim = look_dir;
look_dir /= look_dir_len;
transform.orientation = glm::normalize(glm::slerp(
......
......@@ -7,13 +7,20 @@ namespace mirrage::ecs {
class Entity_manager;
}
namespace phase_shifter::level {
class Level_system;
}
namespace phase_shifter::gameplay {
class Beat_system;
class Movement_system {
public:
Movement_system(mirrage::util::Message_bus&, mirrage::ecs::Entity_manager&, const Beat_system&);
Movement_system(mirrage::util::Message_bus&,
mirrage::ecs::Entity_manager&,
const Beat_system&,
const level::Level_system&);
void update(mirrage::util::Time);
......@@ -21,6 +28,7 @@ namespace phase_shifter::gameplay {
mirrage::util::Message_bus& _bus;
mirrage::ecs::Entity_manager& _ecs;
const Beat_system& _beat_system;
const level::Level_system& _level_system;
};
} // namespace phase_shifter::gameplay
......@@ -11,6 +11,7 @@
namespace phase_shifter::level {
using namespace mirrage;
using namespace mirrage::ecs::components;
using namespace mirrage::util;
Level_system::Level_system(mirrage::ecs::Entity_manager& entities, mirrage::asset::Asset_manager& assets)
: _entities(entities), _assets(assets)
......@@ -111,6 +112,54 @@ namespace phase_shifter::level {
return result;
}
void Level_system::check_contacts(glm::vec2 origin,
float radius,
std::function<void(util ::Contact)> on_contact) const
{
auto& level = _current_level.get_blocking();
auto& tile_types = level.tileset->tiles;
auto tile_size = level.tileset->tile_size;
auto level_size_x = level.tiles[0].size();
auto level_size_y = level.tiles.size();
auto min_x = std::clamp(
static_cast<std::size_t>(std::floor(origin.x / tile_size - radius / tile_size - 0.5f)),
(std::size_t) 0,
level_size_x - 1);
auto min_y = std::clamp(
static_cast<std::size_t>(std::floor(origin.y / tile_size - radius / tile_size - 0.5f)),
(std::size_t) 0,
level_size_y - 1);
auto max_x = std::clamp(
static_cast<std::size_t>(std::ceil(origin.x / tile_size + radius / tile_size + 0.5f)),
(std::size_t) 0,
level_size_x - 1);
auto max_y = std::clamp(
static_cast<std::size_t>(std::ceil(origin.y / tile_size + radius / tile_size + 0.5f)),
(std::size_t) 0,
level_size_y - 1);
for(auto y = min_y; y <= max_y; y++) {
for(auto x = min_x; x <= max_x; x++) {
auto tile = level.tiles[y][x];
auto key = std::string(1, tile);
if(auto tile_it = tile_types.find(key);
tile_it != tile_types.end() && tile_it->second.solid) {
auto tile_origin = glm::vec2{x * tile_size, y * tile_size};
auto half_size = tile_size / 2.f * 1.1f;
auto half_vector = glm::vec2{half_size, half_size};
auto [hit, contact] = util::intersect(util::Aabb{tile_origin, half_vector},
util::Circle{origin, radius});
if(hit) {
on_contact(contact);
}
}
}
}
}
auto Level_system::_spawn_function(const std::string& key)
-> std::function<auto(const Tile&, const glm::vec3&)->void>
{
......
......@@ -3,6 +3,7 @@
#include "../util/collision.hpp"
#include "level.hpp"
#include <mirrage/utils/maybe.hpp>
#include <mirrage/utils/units.hpp>
#include <functional>
......@@ -26,6 +27,7 @@ namespace phase_shifter::level {
auto update(const mirrage::util::Time& time) -> void;
auto load(const std::string& name) -> void;
auto ray_cast(const glm::vec2& origin, const glm::vec2& direction) -> std::pair<bool, util::Contact>;
void check_contacts(glm::vec2 origin, float radius, std::function<void(util::Contact)>) const;
private:
auto _spawn_function(const std::string& key)
......
#pragma once
#include <mirrage/ecs/types.hpp>
namespace phase_shifter {
......@@ -8,4 +9,8 @@ namespace phase_shifter {
struct Lose_msg {
};
struct Entity_hit_wall {
mirrage::ecs::Entity_handle entity;
};
} // namespace phase_shifter
......@@ -5,13 +5,13 @@
#include "gameplay/beat_system.hpp"
#include "gameplay/camera_system.hpp"
#include "gameplay/combat_system.hpp"
#include "gameplay/dash_system.hpp"
#include "gameplay/enemy_system.hpp"
#include "gameplay/killable_comp.hpp"
#include "gameplay/movement_system.hpp"
#include "helper/attachment_system.hpp"
#include "input/input_system.hpp"
#include "level/level_system.hpp"
#include "gameplay/killable_comp.hpp"
#include "gameplay/dash_system.hpp"
#include "ui/hud_system.hpp"
#include <context.hpp>
......@@ -33,12 +33,13 @@ namespace phase_shifter {
, _renderer(engine.renderer_factory().create_renderer(_entities, engine.render_pass_mask()))
, _model_loading(std::make_unique<renderer::Loading_system>(_entities, engine.assets()))
, _beat_system(std::make_unique<gameplay::Beat_system>(engine.bus(), engine.assets()))
, _movement_system(std::make_unique<gameplay::Movement_system>(engine.bus(), _entities, *_beat_system))
, _level_system(std::make_unique<level::Level_system>(_entities, engine.assets()))
, _movement_system(std::make_unique<gameplay::Movement_system>(
engine.bus(), _entities, *_beat_system, *_level_system))
, _input_system(std::make_unique<input::Input_system>(engine.bus(), _entities))
, _combat_system(std::make_unique<gameplay::Combat_system>(engine.bus(), _entities, *_beat_system))
, _attachment_system(std::make_unique<helper::Attachment_system>(_entities))
, _hud_system(std::make_unique<ui::Hud_system>(engine.gui(), _entities, *_beat_system))
, _level_system(std::make_unique<level::Level_system>(_entities, engine.assets()))
, _camera_system(std::make_unique<gameplay::Camera_system>(_entities))
, _enemy_system(std::make_unique<gameplay::Enemy_system>(_entities))
, _dash_system(std::make_unique<gameplay::Dash_system>(_entities))
......
......@@ -64,12 +64,12 @@ namespace phase_shifter {
std::unique_ptr<mirrage::renderer::Loading_system> _model_loading;
std::unique_ptr<gameplay::Beat_system> _beat_system;
std::unique_ptr<level::Level_system> _level_system;
std::unique_ptr<gameplay::Movement_system> _movement_system;
std::unique_ptr<input::Input_system> _input_system;
std::unique_ptr<gameplay::Combat_system> _combat_system;
std::unique_ptr<helper::Attachment_system> _attachment_system;
std::unique_ptr<ui::Hud_system> _hud_system;
std::unique_ptr<level::Level_system> _level_system;
std::unique_ptr<gameplay::Camera_system> _camera_system;
std::unique_ptr<gameplay::Enemy_system> _enemy_system;
std::unique_ptr<gameplay::Dash_system> _dash_system;
......
......@@ -70,4 +70,36 @@ namespace phase_shifter::util {
return {false, {}};
}
auto intersect(const Aabb& aabb, const Circle& circle) -> std::pair<bool, Contact>
{
const auto n = aabb.origin - circle.origin;
auto closest = glm::clamp(n, -aabb.half_vec, aabb.half_vec);
auto inside = glm::distance2(n, closest) <= 0.0f;
if(inside) {
if(std::abs(n.x) > std::abs(n.y))
closest.x = closest.x > 0 ? aabb.half_vec.x : -aabb.half_vec.x;
else
closest.y = closest.y > 0 ? aabb.half_vec.y : -aabb.half_vec.y;
}
auto diff = n - closest;
auto dist2 = glm::length2(diff);
if(dist2 <= circle.radius * circle.radius || inside) {
auto dist = glm::sqrt(dist2);
auto normal = dist > 0.f ? diff / dist : glm::vec2(1, 0);
//auto penetration = std::abs(dist - radius);
if(inside) {
normal *= -1.f;
dist2 = 0;
}
return {true, {glm::vec2{0, 0}, normal, dist2}};
} else {
return {false, {}};
}
}
} // namespace phase_shifter::util
......@@ -27,7 +27,8 @@ namespace phase_shifter::util {
float radius;
};
auto intersect(const Ray& ray, const Aabb& aabb) -> std::pair<bool, Contact>;
auto intersect(const Ray& ray, const Circle& circle) -> std::pair<bool, Contact>;
auto intersect(const Circle& circle1, const Circle& circle2) -> std::pair<bool, Contact>;
extern auto intersect(const Ray& ray, const Aabb& aabb) -> std::pair<bool, Contact>;
extern auto intersect(const Ray& ray, const Circle& circle) -> std::pair<bool, Contact>;
extern auto intersect(const Circle& circle1, const Circle& circle2) -> std::pair<bool, Contact>;
extern auto intersect(const Aabb& aabb, const Circle& circle) -> std::pair<bool, Contact>;
} // namespace phase_shifter::util
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