diff --git a/CMakeLists.txt b/CMakeLists.txt index 486ab3f..7f67ab2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,6 +87,7 @@ add_subdirectory(${DIRECTORY_GAME}) message(STATUS "Game executable: ${EXECUTABLE_GAME}") message(STATUS "Game-runner executable ${EXECUTABLE_GAME_RUNNER}") + # Tests set(DIRECTORY_TEST ${PROJECT_SOURCE_DIR}/test) set(EXECUTABLE_TEST test) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 5eaa516..ca6cd81 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -26,6 +26,12 @@ set( event/management/producer/SystemListener.cpp event/management/producer/SystemListener.hpp event/management/producer/EventProducer.hpp event/management/dispatcher/DelayedDispatcher.cpp event/management/dispatcher/DelayedDispatcher.hpp + event/physics/Collision.hpp + event/physics/Collision.cpp + event/management/handler/controller/Controller.hpp + event/management/handler/controller/Controller.cpp + ../game/mobs/MobController.hpp + ../game/mobs/MobController.cpp event/menu/MenuEvent.hpp event/menu/MenuEvent.cpp event/menu/MainMenuEvent.hpp event/menu/MainMenuEvent.cpp event/menu/PauseMenuEvent.hpp event/menu/PauseMenuEvent.cpp @@ -35,20 +41,29 @@ set( event/management/handler/CollisionHandler.hpp event/management/handler/CollisionHandler.cpp event/physics/Collision.hpp event/physics/Collision.cpp + event/management/handler/controller/Controller.hpp + event/management/handler/controller/Controller.cpp + ../game/mobs/MobController.hpp + ../game/mobs/MobController.cpp world/World.cpp world/World.hpp world/LocalWorld.cpp world/LocalWorld.hpp world/filter/Filter.hpp + world/filter/TagFilter.hpp world/filter/TrueFilter.hpp world/filter/IdFilter.hpp world/entity/EntityStorage.cpp world/entity/EntityStorage.hpp world/entity/ViewableEntity.hpp world/entity/ViewableEntity.cpp world/entity/Entity.hpp world/entity/Entity.cpp + world/entity/mobs/Mob.hpp + world/entity/mobs/Mob.cpp world/intent/Intent.cpp world/intent/Intent.hpp world/intent/LambdaIntent.cpp world/intent/LambdaIntent.hpp world/intent/Intent.cpp world/intent/Intent.hpp world/entity/PhysicalEntity.hpp world/entity/PhysicalEntity.cpp - world/entity/ContactListener/ContactListener.hpp + world/entity/contactListener/ContactListener.hpp + world/filter/RadiusFilter.hpp + world/filter/TagRadiusFilter.hpp menu/Menu.hpp menu/Menu.cpp menu/MainMenu.hpp menu/MainMenu.cpp @@ -56,9 +71,6 @@ set( runner/Runner.hpp runner/SequentialRunner.cpp runner/SequentialRunner.hpp - runner/LevelRunner.hpp runner/LevelRunner.cpp - runner/GameRunner.hpp runner/GameRunner.cpp - loader/LevelLoader.hpp visual/image/Image.hpp visual/image/static/RenderableStatic.cpp visual/image/static/RenderableStatic.hpp @@ -83,7 +95,7 @@ add_library( if (CMAKE_BUILD_TYPE MATCHES Debug) target_compile_definitions(${LIBRARY_CORE} PUBLIC SPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_TRACE) message(STATUS "Enable debug logs for ${LIBRARY_CORE}") -endif() +endif () target_include_directories( ${LIBRARY_CORE} PUBLIC diff --git a/core/common/FVec2D.cpp b/core/common/FVec2D.cpp index db3689d..cd05224 100644 --- a/core/common/FVec2D.cpp +++ b/core/common/FVec2D.cpp @@ -51,4 +51,7 @@ namespace mad::core { Vec2d operator*(float k, Vec2d v) { return v *= k; } + float dist_sq(const Vec2d &v1, const Vec2d &v2) { + return (v1.get_x() - v2.get_x()) * (v1.get_x() - v2.get_x()) + (v1.get_y() - v2.get_y()) * (v1.get_y() - v2.get_y()); + } } diff --git a/core/common/FVec2D.hpp b/core/common/FVec2D.hpp index 0a3ee2b..a87bfb6 100644 --- a/core/common/FVec2D.hpp +++ b/core/common/FVec2D.hpp @@ -36,6 +36,8 @@ namespace mad::core { Vec2d operator*(Vec2d v, float k); Vec2d operator*(float k, Vec2d v); + + float dist_sq(const Vec2d &v1, const Vec2d &v2); } #endif //MAD_CORE_COMMON_FVEC2D_HPP diff --git a/core/event/management/handler/controller/Controller.cpp b/core/event/management/handler/controller/Controller.cpp new file mode 100644 index 0000000..aa6011f --- /dev/null +++ b/core/event/management/handler/controller/Controller.cpp @@ -0,0 +1,21 @@ +#include "Controller.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +mad::core::Controller::Controller(std::shared_ptr m_storage) : m_storage(std::move(m_storage)){} + +void mad::core::Controller::handle(const mad::core::Event &event) { +} diff --git a/core/event/management/handler/controller/Controller.hpp b/core/event/management/handler/controller/Controller.hpp new file mode 100644 index 0000000..aef5d0a --- /dev/null +++ b/core/event/management/handler/controller/Controller.hpp @@ -0,0 +1,21 @@ +#ifndef MAD_CONTROLLER_HPP +#define MAD_CONTROLLER_HPP + +#include +#include +namespace mad::core { + + class Controller : public EventHandler { + public: + explicit Controller(std::shared_ptr m_storage); + + void handle(const Event &event) override; + + virtual void control() = 0; + + protected: + std::shared_ptr m_storage; + }; + +} +#endif//MAD_CONTROLLER_HPP diff --git a/core/world/LocalWorld.cpp b/core/world/LocalWorld.cpp index 67e9903..b51fe81 100644 --- a/core/world/LocalWorld.cpp +++ b/core/world/LocalWorld.cpp @@ -5,9 +5,14 @@ #include #include #include +#include +#include +#include +#include #include -#include +#include +#include #include @@ -18,6 +23,9 @@ mad::core::LocalWorld::LocalWorld(EventDispatcher &event_dispatcher, Vec2d gravi m_contact_listener = std::make_shared(event_dispatcher); m_physical_world.SetContactListener(&*m_contact_listener); + m_storage = std::make_shared(); + m_controller = std::make_shared(m_storage); + event_dispatcher.registry(m_controller); } @@ -25,8 +33,8 @@ bool mad::core::LocalWorld::manipulate(const mad::core::Filter &filter, const ma //CHECK_THROW(is_legal(validate_filter(f), IllegalManipulation, "Illegal filter"); //CHECK_THROW(is_legal(validate_intent(i), IllegalManipulation, "Illegal intent"); - for (Entity::Id entity_id : m_storage.extract(filter)) { - m_storage.get_entity(entity_id).accept(*this, intent, *m_event_queue_dispatcher); + for (Entity::Id entity_id : m_storage->extract(filter)) { + m_storage->get_entity(entity_id).accept(*this, intent, *m_event_queue_dispatcher); } return true; @@ -37,18 +45,18 @@ void mad::core::LocalWorld::produce(mad::core::EventDispatcher &dispatcher) { // calculating fps + dt sf::Time time = clock.getElapsedTime(); dt = time.asSeconds() - last_time; - sf::sleep(sf::seconds((1.0f/120) - dt)); + sf::sleep(sf::seconds((1.0f / 120) - dt)); last_time = time.asSeconds(); - float fact_dt = (1.0f/120); + float fact_dt = (1.0f / 120); //double fps = 1 / (time.asSeconds() - l_old); //SPDLOG_INFO("FPS {}", fps); // simulating physics m_physical_world.Step(fact_dt * render_scale, 3, 10); - for (Entity::Id entity_id : m_storage.extract(TrueFilter())) { - if (&m_storage.get_entity(entity_id) != nullptr && cast_to_or_null(m_storage.get_entity(entity_id)) != nullptr) { - auto physical_entity = cast_to_or_null(m_storage.get_entity(entity_id)); + for (Entity::Id entity_id : m_storage->extract(TrueFilter())) { + if (cast_to_or_null(m_storage->get_entity(entity_id)) != nullptr) { + auto physical_entity = cast_to_or_null(m_storage->get_entity(entity_id)); physical_entity->synchronize_position_with_viewable(); } } @@ -74,12 +82,15 @@ void mad::core::LocalWorld::produce(mad::core::EventDispatcher &dispatcher) { dispatcher.dispatch(m_step_events_queue->front()); m_step_events_queue->pop(); } + + //control + m_controller->control(); } -mad::core::Entity::Id mad::core::LocalWorld::create_viewable_entity(int z_ind, mad::core::Vec2d initial_position, float initial_rotation, +mad::core::Entity::Id mad::core::LocalWorld::create_viewable_entity(std::unordered_set tags, int z_ind, mad::core::Vec2d initial_position, float initial_rotation, std::shared_ptr image) { - return m_storage.create_viewable_entity(z_ind, initial_position, initial_rotation, image); + return m_storage->create_viewable_entity(std::move(tags), z_ind, initial_position, initial_rotation, std::move(image)); } -mad::core::Entity::Id mad::core::LocalWorld::create_physical_entity(int z_ind, mad::core::Vec2d initial_position, float initial_rotation, std::shared_ptr image, bool is_Fixed) { - return m_storage.create_physical_entity(z_ind, initial_position, initial_rotation, image, m_physical_world, is_Fixed); +mad::core::Entity::Id mad::core::LocalWorld::create_physical_entity(std::unordered_set tags, int z_ind, mad::core::Vec2d initial_position, float initial_rotation, std::shared_ptr image, bool is_Fixed) { + return m_storage->create_physical_entity(std::move(tags), z_ind, initial_position, initial_rotation, std::move(image), m_physical_world, is_Fixed); } diff --git a/core/world/LocalWorld.hpp b/core/world/LocalWorld.hpp index adab2ea..da22eeb 100644 --- a/core/world/LocalWorld.hpp +++ b/core/world/LocalWorld.hpp @@ -1,21 +1,21 @@ #ifndef MAD_CORE_WORLD_LOCALWORLD_HPP #define MAD_CORE_WORLD_LOCALWORLD_HPP -#include -#include -#include -#include -#include -#include -#include +#include #include #include #include #include #include #include - +#include +#include +#include #include +#include +#include +#include +#include namespace mad::core { @@ -28,15 +28,16 @@ namespace mad::core { void produce(EventDispatcher &dispatcher) override; - Entity::Id create_viewable_entity(int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image) override; + Entity::Id create_viewable_entity(std::unordered_set tags, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image) override; - Entity::Id create_physical_entity(int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image, bool is_Fixed = false) override; + Entity::Id create_physical_entity(std::unordered_set tags, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image, bool is_Fixed = false) override; private: std::shared_ptr>> m_step_events_queue; std::unique_ptr m_event_queue_dispatcher; - EntityStorage m_storage; + std::shared_ptr m_storage; b2World m_physical_world; + std::shared_ptr m_controller; float dt; float render_scale = 3; sf::Clock clock; @@ -44,7 +45,7 @@ namespace mad::core { std::shared_ptr m_contact_listener; }; -} +}// namespace mad::core -#endif //MAD_CORE_WORLD_LOCALWORLD_HPP +#endif//MAD_CORE_WORLD_LOCALWORLD_HPP diff --git a/core/world/World.hpp b/core/world/World.hpp index b0e9b62..cfcd93c 100644 --- a/core/world/World.hpp +++ b/core/world/World.hpp @@ -2,12 +2,12 @@ #define MAD_CORE_WORLD_WORLD_HPP -#include #include +#include #include -#include #include "visual/image/shape/Shape.hpp" +#include namespace mad::core { class Filter; @@ -26,11 +26,11 @@ namespace mad::core { bool manipulate_entity_id(Entity::Id entity_id, const Intent &intent); - virtual Entity::Id create_viewable_entity(int z_ind, + virtual Entity::Id create_viewable_entity(std::unordered_set tags, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image) = 0; - virtual Entity::Id create_physical_entity(int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image, bool is_Fixed) = 0; + virtual Entity::Id create_physical_entity(std::unordered_set tags, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image, bool is_Fixed) = 0; }; }// namespace mad::core diff --git a/core/world/entity/Entity.cpp b/core/world/entity/Entity.cpp index a5b9a76..1481f34 100644 --- a/core/world/entity/Entity.cpp +++ b/core/world/entity/Entity.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace mad::core { @@ -9,5 +10,6 @@ namespace mad::core { mad::core::Entity::Id mad::core::Entity::get_id() const noexcept { return m_id; } + Entity::Entity(std::unordered_set tags) : tags(std::move(tags)) {} } diff --git a/core/world/entity/Entity.hpp b/core/world/entity/Entity.hpp index e288d68..6e47c2c 100644 --- a/core/world/entity/Entity.hpp +++ b/core/world/entity/Entity.hpp @@ -4,6 +4,7 @@ #include #include +#include namespace mad::core { @@ -21,7 +22,10 @@ namespace mad::core { public: using Id = std::int32_t; - public: + const std::unordered_set tags; + + explicit Entity(std::unordered_set tags); + virtual void accept(World &world, const Intent &intent, EventDispatcher &dispatcher) = 0; [[nodiscard]] Id get_id() const noexcept; diff --git a/core/world/entity/EntityStorage.cpp b/core/world/entity/EntityStorage.cpp index c89f7f5..ddc4638 100644 --- a/core/world/entity/EntityStorage.cpp +++ b/core/world/entity/EntityStorage.cpp @@ -1,15 +1,18 @@ - - +#include "EntityStorage.hpp" +#include "world/entity/mobs/Mob.hpp" +#include "world/filter/RadiusFilter.hpp" +#include "world/filter/TagRadiusFilter.hpp" +#include "world/filter/TrueFilter.hpp" #include #include -#include #include -#include "EntityStorage.hpp" +#include +#include namespace mad::core { - std::vector EntityStorage::extract(const Filter &filter) const { + std::vector EntityStorage::extract(const Filter &filter) { switch (filter.type) { case Filter::Type::Id: { IdFilter id_filter = const_cast_to(filter); @@ -19,6 +22,46 @@ namespace mad::core { case Filter::Type::True: { return m_list_ids; } + + case Filter::Type::EntityTag: { + TagFilter tag_filter = const_cast_to(filter); + return m_map_entities_by_tag[tag_filter.get_filter_tag()]; + } + + case Filter::Type::Radius: { + std::vector arr; + + RadiusFilter radius_filter = const_cast_to(filter); + for (Entity::Id entity_id : extract(TrueFilter())) { + if ((&get_entity(entity_id)) != nullptr && cast_to_or_null(get_entity(entity_id)) != nullptr) { + auto physical_entity = cast_to_or_null(get_entity(entity_id)); + float t1 = dist_sq(physical_entity->get_position(), radius_filter.get_filter_point()); + float t2 = radius_filter.get_filter_radius_sq(); + if (dist_sq(physical_entity->get_position(), radius_filter.get_filter_point()) < radius_filter.get_filter_radius_sq()) { + arr.push_back(entity_id); + } + } + } + return arr; + } + + case Filter::Type::TagRadius: { + std::vector arr; + + auto tag_radius_filter = const_cast_to(filter); + for (Entity::Id entity_id : extract(TrueFilter())) { + if ((&get_entity(entity_id)) != nullptr && cast_to_or_null(get_entity(entity_id)) != nullptr) { + auto physical_entity = cast_to_or_null(get_entity(entity_id)); + float t1 = dist_sq(physical_entity->get_position(), tag_radius_filter.get_filter_point()); + float t2 = tag_radius_filter.get_filter_radius_sq(); + if (dist_sq(physical_entity->get_position(), tag_radius_filter.get_filter_point()) < tag_radius_filter.get_filter_radius_sq() && + physical_entity->tags.find(tag_radius_filter.get_filter_tag()) != physical_entity->tags.end()) { + arr.push_back(entity_id); + } + } + } + return arr; + } } } @@ -28,16 +71,27 @@ namespace mad::core { return *entity_it->second; } - Entity::Id EntityStorage::create_viewable_entity(int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image) { + Entity::Id EntityStorage::create_viewable_entity(std::unordered_set tags, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image) { auto new_entity_id = static_cast(m_map_entities.size()); m_list_ids.push_back(new_entity_id); - m_map_entities[new_entity_id] = std::make_unique(new_entity_id, z_ind, initial_position, initial_rotation, image); + m_map_entities[new_entity_id] = std::make_unique(tags, new_entity_id, z_ind, initial_position, initial_rotation, image); + for(const auto& tag : tags){ + m_map_entities_by_tag[tag].push_back(new_entity_id); + } return new_entity_id; } - Entity::Id EntityStorage::create_physical_entity(int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image, b2World &physicalWorld, bool is_Fixed) { + Entity::Id EntityStorage::create_physical_entity(std::unordered_set tags, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image, b2World &physicalWorld, bool is_Fixed) { auto new_entity_id = static_cast(m_map_entities.size()); m_list_ids.push_back(new_entity_id); - m_map_entities[new_entity_id] = std::make_unique(new_entity_id, z_ind, initial_position, initial_rotation, image, physicalWorld, is_Fixed); + if (tags.find("SimpleObject") != tags.end()) { + m_map_entities[new_entity_id] = std::make_unique(tags, new_entity_id, z_ind, initial_position, initial_rotation, image, physicalWorld, is_Fixed); + } + if (tags.find("Enemy") != tags.end() || tags.find("Hero") != tags.end()) { + m_map_entities[new_entity_id] = std::make_unique(tags, new_entity_id, z_ind, initial_position, initial_rotation, image, physicalWorld, is_Fixed); + } + for(const auto& tag : tags){ + m_map_entities_by_tag[tag].push_back(new_entity_id); + } return new_entity_id; } diff --git a/core/world/entity/EntityStorage.hpp b/core/world/entity/EntityStorage.hpp index 9ac298b..1dd2e9e 100644 --- a/core/world/entity/EntityStorage.hpp +++ b/core/world/entity/EntityStorage.hpp @@ -3,42 +3,49 @@ #include "Entity.hpp" -#include #include +#include #include #include #include #include "EntityStorage.hpp" +#include "PhysicalEntity.hpp" #include "ViewableEntity.hpp" #include "visual/image/shape/Shape.hpp" -#include "PhysicalEntity.hpp" -#include #include +#include namespace mad::core { class Image; -} + + struct EnumClassHash { + template + std::size_t operator()(T t) const { + return static_cast(t); + } + }; +}// namespace mad::core namespace mad::core { class EntityStorage { public: - [[nodiscard]] std::vector extract(const Filter &filter) const; + [[nodiscard]] std::vector extract(const Filter &filter); Entity &get_entity(Entity::Id id); - Entity::Id create_viewable_entity(int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image); - Entity::Id create_physical_entity(int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image, b2World &physicalWorld, bool is_Fixed); + Entity::Id create_viewable_entity(std::unordered_set tags, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image); + Entity::Id create_physical_entity(std::unordered_set tags, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image, b2World &physicalWorld, bool is_Fixed); private: std::unordered_map> m_map_entities; - + std::unordered_map> m_map_entities_by_tag; std::vector m_list_ids; }; -} +}// namespace mad::core -#endif //MAD_CORE_WORLD_ENTITY_ENTITYSTORAGE_HPP +#endif//MAD_CORE_WORLD_ENTITY_ENTITYSTORAGE_HPP diff --git a/core/world/entity/PhysicalEntity.cpp b/core/world/entity/PhysicalEntity.cpp index 79bd18f..8480731 100644 --- a/core/world/entity/PhysicalEntity.cpp +++ b/core/world/entity/PhysicalEntity.cpp @@ -2,22 +2,21 @@ // Created by mirong on 18.03.2022. // #include "PhysicalEntity.hpp" -#include "visual/image/shape/square/Square.hpp" #include "common/Cast.hpp" +#include "visual/image/shape/square/Square.hpp" #include "world/intent/LambdaIntent.hpp" #include -mad::core::PhysicalEntity::PhysicalEntity(std::int32_t id, int z_ind, Vec2d initial_position, float initial_rotation,std::shared_ptr image, b2World &physicalWorld, bool is_fixed) - : ViewableEntity(id, z_ind, initial_position, initial_rotation, image) { +mad::core::PhysicalEntity::PhysicalEntity(std::unordered_set tags, std::int32_t id, int z_ind, Vec2d initial_position, float initial_rotation,std::shared_ptr image, b2World &physicalWorld, bool is_fixed) + : ViewableEntity(std::move(tags), id, z_ind, initial_position, initial_rotation, image) { //rect.setOrigin(300, 50); float side_length = pointer_cast_to(image)->get_side_length(); - if(is_fixed) - { + if (is_fixed) { b2BodyDef fixedBodyDef; fixedBodyDef.position.Set(initial_position.get_x(), initial_position.get_y()); body = physicalWorld.CreateBody(&fixedBodyDef); @@ -25,9 +24,7 @@ mad::core::PhysicalEntity::PhysicalEntity(std::int32_t id, int z_ind, Vec2d init groundBox.SetAsBox(side_length / 2, side_length / 2); body->CreateFixture(&groundBox, 0.0f); body->SetTransform(body->GetPosition(), initial_rotation); - } - else - { + } else { b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.position.Set(initial_position.get_x(), initial_position.get_y()); diff --git a/core/world/entity/PhysicalEntity.hpp b/core/world/entity/PhysicalEntity.hpp index dc0703c..3634f64 100644 --- a/core/world/entity/PhysicalEntity.hpp +++ b/core/world/entity/PhysicalEntity.hpp @@ -30,7 +30,7 @@ namespace mad::core { using Id = std::int32_t; public: - explicit PhysicalEntity(Id id, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image, b2World &physicalWorld, bool is_fixed); + explicit PhysicalEntity(std::unordered_set tags, Id id, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image, b2World &physicalWorld, bool is_fixed); void accept(World &world, const Intent &intent, EventDispatcher &dispatcher) override; diff --git a/core/world/entity/ViewableEntity.cpp b/core/world/entity/ViewableEntity.cpp index 147f670..b18e211 100644 --- a/core/world/entity/ViewableEntity.cpp +++ b/core/world/entity/ViewableEntity.cpp @@ -1,9 +1,10 @@ #include "ViewableEntity.hpp" #include +#include #include #include -#include +#include #include @@ -40,12 +41,14 @@ void mad::core::ViewableEntity::appear(mad::core::EventDispatcher &dispatcher) c dispatcher.dispatch(std::make_shared(m_position, m_rotation, m_image, m_z_ind)); } -mad::core::ViewableEntity::ViewableEntity(mad::core::ViewableEntity::Id id, +mad::core::ViewableEntity::ViewableEntity(std::unordered_set tags, + mad::core::ViewableEntity::Id id, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image) - : m_id(id), + : Entity(std::move(tags)), + m_id(id), m_z_ind(z_ind), m_position(std::make_shared(initial_position)), m_rotation(std::make_shared(initial_rotation)), diff --git a/core/world/entity/ViewableEntity.hpp b/core/world/entity/ViewableEntity.hpp index dd46623..3619da0 100644 --- a/core/world/entity/ViewableEntity.hpp +++ b/core/world/entity/ViewableEntity.hpp @@ -2,10 +2,10 @@ #define MAD_VIEWABLEENTITY_HPP #include "Entity.hpp" -#include "common/FVec2D.hpp" #include "common/Error.hpp" -#include "visual/image/Image.hpp" +#include "common/FVec2D.hpp" #include "event/management/dispatcher/EventDispatcher.hpp" +#include "visual/image/Image.hpp" #include @@ -17,7 +17,7 @@ namespace mad::core { class Intent; class EventDispatcher; -} +}// namespace mad::core namespace mad::core { @@ -27,7 +27,7 @@ namespace mad::core { using Id = std::int32_t; public: - explicit ViewableEntity(Id id, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image); + explicit ViewableEntity(std::unordered_set tags, Id id, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image); void accept(World &world, const Intent &intent, EventDispatcher &dispatcher) override; @@ -55,6 +55,6 @@ namespace mad::core { std::shared_ptr m_image; }; -} +}// namespace mad::core -#endif //MAD_VIEWABLEENTITY_HPP +#endif//MAD_VIEWABLEENTITY_HPP diff --git a/core/world/entity/ContactListener/ContactListener.hpp b/core/world/entity/contactListener/ContactListener.hpp similarity index 100% rename from core/world/entity/ContactListener/ContactListener.hpp rename to core/world/entity/contactListener/ContactListener.hpp diff --git a/core/world/entity/mobs/Mob.cpp b/core/world/entity/mobs/Mob.cpp new file mode 100644 index 0000000..b810ff1 --- /dev/null +++ b/core/world/entity/mobs/Mob.cpp @@ -0,0 +1,6 @@ +#include "Mob.hpp" + +#include + +mad::core::Mob::Mob(std::unordered_set tags, std::int32_t id, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image, b2World &physicalWorld, bool is_fixed) : PhysicalEntity(std::move(tags), id, z_ind, initial_position, initial_rotation, std::move(image), physicalWorld, is_fixed) { +} diff --git a/core/world/entity/mobs/Mob.hpp b/core/world/entity/mobs/Mob.hpp new file mode 100644 index 0000000..384d78c --- /dev/null +++ b/core/world/entity/mobs/Mob.hpp @@ -0,0 +1,34 @@ +#ifndef MAD_MOB_HPP +#define MAD_MOB_HPP + +#include +#include + +namespace mad::core { + class World; + + class Intent; + + class EventDispatcher; +}// namespace mad::core + + +namespace mad::core { + + class Mob : public PhysicalEntity { + public: + using Id = std::int32_t; + + public: + explicit Mob(std::unordered_set tags, Id id, int z_ind, Vec2d initial_position, float initial_rotation, std::shared_ptr image, b2World &physicalWorld, bool is_fixed); + //virtual void take_damage(float damage) = 0; + + + private: + float health_points{}; + }; + + +}// namespace mad::core + +#endif//MAD_MOB_HPP diff --git a/core/world/filter/Filter.hpp b/core/world/filter/Filter.hpp index 5454c94..7b3fdb1 100644 --- a/core/world/filter/Filter.hpp +++ b/core/world/filter/Filter.hpp @@ -12,7 +12,10 @@ namespace mad::core { struct Filter { enum class Type { Id, - True + True, + EntityTag, + Radius, + TagRadius }; explicit Filter(Type new_type) : type(new_type) { diff --git a/core/world/filter/RadiusFilter.hpp b/core/world/filter/RadiusFilter.hpp new file mode 100644 index 0000000..8dd2cfd --- /dev/null +++ b/core/world/filter/RadiusFilter.hpp @@ -0,0 +1,33 @@ +#ifndef MAD_RADIUSFILTER_HPP +#define MAD_RADIUSFILTER_HPP + +#include "Filter.hpp" + +namespace mad::core { + + struct RadiusFilter : Filter { + explicit RadiusFilter(Vec2d p, float r) : Filter(Filter::Type::Radius), p(p), r(r) { + } + + [[nodiscard]] float get_filter_radius() const noexcept { + return r; + } + + [[nodiscard]] float get_filter_radius_sq() const noexcept { + return r * r; + } + + [[nodiscard]] Vec2d get_filter_point() const noexcept { + return p; + } + + private: + Vec2d p; + float r; + + }; + +} + + +#endif//MAD_RADIUSFILTER_HPP diff --git a/core/world/filter/TagFilter.hpp b/core/world/filter/TagFilter.hpp new file mode 100644 index 0000000..cc05c6d --- /dev/null +++ b/core/world/filter/TagFilter.hpp @@ -0,0 +1,25 @@ +#ifndef MAD_TAGFILTER_HPP +#define MAD_TAGFILTER_HPP + +#include "Filter.hpp" + +#include + +namespace mad::core { + + struct TagFilter : Filter { + explicit TagFilter(std::string filter_tag) : Filter(Filter::Type::EntityTag), m_filter_tag(std::move(filter_tag)) { + } + + [[nodiscard]] std::string get_filter_tag() const noexcept { + return m_filter_tag; + } + + private: + std::string m_filter_tag; + + }; + +}// namespace mad::core + +#endif//MAD_TAGFILTER_HPP diff --git a/core/world/filter/TagRadiusFilter.hpp b/core/world/filter/TagRadiusFilter.hpp new file mode 100644 index 0000000..0af370f --- /dev/null +++ b/core/world/filter/TagRadiusFilter.hpp @@ -0,0 +1,39 @@ +#ifndef MAD_TAGRADIUSFILTER_HPP +#define MAD_TAGRADIUSFILTER_HPP + +#include "Filter.hpp" +#include +#include +namespace mad::core { + + struct TagRadiusFilter : Filter { + explicit TagRadiusFilter(Vec2d m_point, float m_radius, std::string type) : Filter(Filter::Type::TagRadius), m_point(m_point), m_radius(m_radius), m_tag(std::move(type)) { + } + + [[nodiscard]] float get_filter_radius() const noexcept { + return m_radius; + } + + [[nodiscard]] float get_filter_radius_sq() const noexcept { + return m_radius * m_radius; + } + + [[nodiscard]] Vec2d get_filter_point() const noexcept { + return m_point; + } + + [[nodiscard]] std::string get_filter_tag() const noexcept { + return m_tag; + } + + private: + Vec2d m_point; + float m_radius; + std::string m_tag; + + }; + +} + + +#endif//MAD_TAGRADIUSFILTER_HPP diff --git a/game/example.cpp b/game/example.cpp index bae628e..a991c4e 100644 --- a/game/example.cpp +++ b/game/example.cpp @@ -1,7 +1,7 @@ -#include #include -#include #include +#include +#include #include #include #include @@ -85,84 +85,84 @@ int main(int argc, char *argv[]) { auto collision_handler = std::make_shared(); mad::core::Entity::Id square_id = world->create_viewable_entity( + {"SimpleObject"}, 0, - mad::core::Vec2d{25.0f, 25.0f},0, - std::make_shared(50.0f, mad::core::Color::Green()) - ); + mad::core::Vec2d{25.0f, 25.0f}, 0, + std::make_shared(50.0f, mad::core::Color::Green())); mad::core::Entity::Id square_id1 = world->create_physical_entity( + {"Enemy"}, 3, - mad::core::Vec2d{100.0f, 25.0f},0, - std::make_shared(50.0f, mad::core::Color::Green()) - ); + mad::core::Vec2d{100.0f, 25.0f}, 0, + std::make_shared(50.0f, mad::core::Color::Green())); mad::core::Entity::Id square_id2 = world->create_physical_entity( + {"SimpleObject"}, 0, - mad::core::Vec2d{80.0f, 100.0f},0.5, + mad::core::Vec2d{80.0f, 100.0f}, 0.5, std::make_shared(50.0f, mad::core::Color::Green()), - true - ); + true); mad::core::Entity::Id square_id3 = world->create_physical_entity( + {"SimpleObject"}, 0, - mad::core::Vec2d{180.0f, 180.0f},-0.5, + mad::core::Vec2d{180.0f, 180.0f}, -0.5, std::make_shared(50.0f, mad::core::Color::Green()), - true - ); + true); mad::core::Entity::Id square_id4 = world->create_physical_entity( + {"SimpleObject"}, 0, - mad::core::Vec2d{80.0f, 260.0f},0.5, + mad::core::Vec2d{80.0f, 260.0f}, 0.5, std::make_shared(50.0f, mad::core::Color::Green()), - true - ); + true); mad::core::Entity::Id square_id5 = world->create_physical_entity( + {"SimpleObject"}, 0, - mad::core::Vec2d{180.0f, 340.0f},-0.5, + mad::core::Vec2d{180.0f, 340.0f}, -0.5, std::make_shared(50.0f, mad::core::Color::Green()), - true - ); + true); mad::core::Entity::Id square_id6 = world->create_physical_entity( + {"SimpleObject"}, 0, - mad::core::Vec2d{500.0f, 500.0f},0, + mad::core::Vec2d{500.0f, 500.0f}, 0, std::make_shared(500.0f, mad::core::Color::Green()), - true - ); + true); world->create_physical_entity( + {"SimpleObject"}, 0, - mad::core::Vec2d{800.0f, 0.0f},0, + mad::core::Vec2d{800.0f, 0.0f}, 0, std::make_shared(500.0f, mad::core::Color::Green()), - true - ); + true); - for(int i = 0; i < 100; i++){ + for (int i = 0; i < 100; i++) { world->create_physical_entity( + {"SimpleObject"}, 0, - mad::core::Vec2d{500 + (float)(rand() % 100), (float)(rand() % 100)},0, - std::make_shared(5.0f, mad::core::Color::Green()) - ); + mad::core::Vec2d{500 + (float) (rand() % 100), (float) (rand() % 100)}, 0, + std::make_shared(5.0f, mad::core::Color::Green())); } //mad::core::StaticImage st_im_1 = mad::core::StaticImage("../../game/resources/static/brick.png", 50, 50, mad::core::StaticImage::TransformType::Fit); mad::core::Entity::Id static_id_1 = world->create_viewable_entity( + {"SimpleObject"}, 2, - mad::core::Vec2d{180.0f, 340.0f},-0.5, - std::make_shared(mad::core::StaticImage("../../game/resources/static/brick.png", 300.0f, 50.0f, mad::core::StaticImage::TransformType::Fit)) - ); + mad::core::Vec2d{180.0f, 340.0f}, -0.5, + std::make_shared(mad::core::StaticImage("../../game/resources/static/brick.png", 300.0f, 50.0f, mad::core::StaticImage::TransformType::Fit))); mad::core::Entity::Id animated_id_1 = world->create_viewable_entity( + {"SimpleObject"}, 5, - mad::core::Vec2d{180.0f, 240.0f},0, - std::make_shared(mad::core::AnimatedImage("../../game/resources/animated/runner_new.png", 5, 2, 120)) - ); + mad::core::Vec2d{180.0f, 240.0f}, 0, + std::make_shared(mad::core::AnimatedImage("../../game/resources/animated/runner_new.png", 5, 2, 120))); mad::core::Entity::Id animated_id_2 = world->create_viewable_entity( + {"SimpleObject"}, 6, - mad::core::Vec2d{380.0f, 70.0f},0, - std::make_shared(mad::core::AnimatedImage("../../game/resources/animated/helicopter.png", 1, 4, 150)) - ); + mad::core::Vec2d{380.0f, 70.0f}, 0, + std::make_shared(mad::core::AnimatedImage("../../game/resources/animated/helicopter.png", 1, 4, 150))); /*mad::core::StaticImage st_im_2 = mad::core::StaticImage("../../game/resources/static/18plus.png"); st_im_2.set_shape(400, 400, mad::core::StaticImage::TransformType::Tile); @@ -173,8 +173,6 @@ int main(int argc, char *argv[]) { );*/ - - camera->turn_on(*dispatcher); dispatcher->registry(camera); diff --git a/game/mobs/MobController.cpp b/game/mobs/MobController.cpp new file mode 100644 index 0000000..2c723aa --- /dev/null +++ b/game/mobs/MobController.cpp @@ -0,0 +1,55 @@ +#include "MobController.hpp" + +#include "event/Event.hpp" +#include "event/physics/Collision.hpp" +#include "event/system/KeyPressed.hpp" +#include "world/entity/Entity.hpp" +#include "world/entity/PhysicalEntity.hpp" +#include "world/entity/mobs/Mob.hpp" +#include "world/filter/RadiusFilter.hpp" +#include "world/filter/TagFilter.hpp" +#include "world/filter/TagRadiusFilter.hpp" +#include "world/intent/LambdaIntent.hpp" + +#include + +#include "common/Cast.hpp" +#include "common/Color.hpp" + +#include "spdlog/spdlog.h" + +#include + + +mad::core::MobController::MobController(std::shared_ptr m_storage) : Controller(std::move(m_storage)){} +void mad::core::MobController::handle(const mad::core::Event &event) { + if (event.type == mad::core::Event::Type::KeyPressed) { + const auto &keystroke = mad::core::const_cast_to(event); + if (keystroke.key_id == sf::Keyboard::Key::Q) { + for (Entity::Id entity_id : m_storage->extract(TagFilter("Hero"))) { + if (cast_to_or_null(m_storage->get_entity(entity_id)) != nullptr) { + auto hero = cast_to_or_null(m_storage->get_entity(entity_id)); + if(m_storage->extract(TagRadiusFilter(hero->get_position(), 200.0f, "Enemy")).size() > 0){ + auto mob = cast_to_or_null(m_storage->get_entity(m_storage->extract(TagRadiusFilter(hero->get_position(), 200.0f, "Enemy"))[0])); + mob->set_image_color(Color(rand() % 256, rand() % 256, rand() % 256)); + } + } + } + } + } +} +void mad::core::MobController::control() { + for (Entity::Id entity_id : m_storage->extract(TagFilter("Enemy"))) { + if (cast_to_or_null(m_storage->get_entity(entity_id)) != nullptr) { + auto mob = cast_to_or_null(m_storage->get_entity(entity_id)); + if(m_storage->extract(TagRadiusFilter(mob->get_position(), 100.0f, "Hero")).size() > 0){ + auto hero = cast_to_or_null(m_storage->get_entity(m_storage->extract(TagRadiusFilter(mob->get_position(), 100.0f, "Hero"))[0])); + hero->set_image_color(Color(rand() % 256, rand() % 256, rand() % 256)); + } + } + } +} + +std::unordered_set mad::core::MobController::handled_types() { + return {Event::Type::Collision, Event::Type::KeyPressed}; +} diff --git a/game/mobs/MobController.hpp b/game/mobs/MobController.hpp new file mode 100644 index 0000000..b8de304 --- /dev/null +++ b/game/mobs/MobController.hpp @@ -0,0 +1,24 @@ +#ifndef MAD_MOBCONTROLLER_HPP +#define MAD_MOBCONTROLLER_HPP + + +#include "event/management/handler/controller/Controller.hpp" +namespace mad::core { + + class MobController : public Controller { + public: + explicit MobController(std::shared_ptr m_storage); + + void handle(const Event &event) override; + + std::unordered_set handled_types() override; + + void control() override; + + private: + }; + +}// namespace mad::core + + +#endif//MAD_MOBCONTROLLER_HPP diff --git a/test/core/TestCast.cpp b/test/core/TestCast.cpp index 50d9941..ce5333f 100644 --- a/test/core/TestCast.cpp +++ b/test/core/TestCast.cpp @@ -9,6 +9,7 @@ TEST(Cast, EntityCast) { class MockEntity_1 : public mad::core::Entity { public: + MockEntity_1() : Entity("SimpleObject"){}; void accept(mad::core::World &world, const mad::core::Intent &intent, mad::core::EventDispatcher &dispatcher) override { @@ -21,6 +22,7 @@ TEST(Cast, EntityCast) { class MockEntity_2 : public mad::core::Entity { public: + MockEntity_2() : Entity("SimpleObject"){}; void accept(mad::core::World &world, const mad::core::Intent &intent, mad::core::EventDispatcher &dispatcher) override {