diff options
author | JAROWMR <jarorutjes07@gmail.com> | 2024-12-05 21:10:07 +0100 |
---|---|---|
committer | JAROWMR <jarorutjes07@gmail.com> | 2024-12-05 21:10:07 +0100 |
commit | 9604616001ac273f2c966c3c829638e905def7bf (patch) | |
tree | 7e958c2b658a4dbc9e79068d7309513efa928937 /src/crepe/system | |
parent | 018a451051669506be447aa925ecb6a9f5aaf418 (diff) | |
parent | 1f4e961d7f9d6887c807cac1a362f2d178b0860b (diff) |
merge with master and keypressed added to game
Diffstat (limited to 'src/crepe/system')
-rw-r--r-- | src/crepe/system/AnimatorSystem.cpp | 8 | ||||
-rw-r--r-- | src/crepe/system/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/crepe/system/CollisionSystem.cpp | 43 | ||||
-rw-r--r-- | src/crepe/system/CollisionSystem.h | 13 | ||||
-rw-r--r-- | src/crepe/system/InputSystem.cpp | 187 | ||||
-rw-r--r-- | src/crepe/system/InputSystem.h | 85 | ||||
-rw-r--r-- | src/crepe/system/ParticleSystem.cpp | 8 | ||||
-rw-r--r-- | src/crepe/system/PhysicsSystem.cpp | 4 | ||||
-rw-r--r-- | src/crepe/system/RenderSystem.cpp | 8 | ||||
-rw-r--r-- | src/crepe/system/ScriptSystem.cpp | 4 | ||||
-rw-r--r-- | src/crepe/system/System.cpp | 2 | ||||
-rw-r--r-- | src/crepe/system/System.h | 11 |
12 files changed, 333 insertions, 42 deletions
diff --git a/src/crepe/system/AnimatorSystem.cpp b/src/crepe/system/AnimatorSystem.cpp index 4c40940..8bb6465 100644 --- a/src/crepe/system/AnimatorSystem.cpp +++ b/src/crepe/system/AnimatorSystem.cpp @@ -1,15 +1,15 @@ #include <cstdint> -#include "api/Animator.h" -#include "facade/SDLContext.h" +#include "../api/Animator.h" +#include "../facade/SDLContext.h" +#include "../manager/ComponentManager.h" #include "AnimatorSystem.h" -#include "ComponentManager.h" using namespace crepe; void AnimatorSystem::update() { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector<Animator> animations = mgr.get_components_by_type<Animator>(); diff --git a/src/crepe/system/CMakeLists.txt b/src/crepe/system/CMakeLists.txt index d658b25..95f6e33 100644 --- a/src/crepe/system/CMakeLists.txt +++ b/src/crepe/system/CMakeLists.txt @@ -6,6 +6,7 @@ target_sources(crepe PUBLIC CollisionSystem.cpp RenderSystem.cpp AnimatorSystem.cpp + InputSystem.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -15,4 +16,5 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES CollisionSystem.h RenderSystem.h AnimatorSystem.h + InputSystem.h ) diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp index e3b2eca..86eafc0 100644 --- a/src/crepe/system/CollisionSystem.cpp +++ b/src/crepe/system/CollisionSystem.cpp @@ -9,15 +9,15 @@ #include "api/BoxCollider.h" #include "api/CircleCollider.h" #include "api/Event.h" -#include "api/EventManager.h" #include "api/Metadata.h" #include "api/Rigidbody.h" #include "api/Transform.h" #include "api/Vector2.h" +#include "../manager/ComponentManager.h" +#include "../manager/EventManager.h" #include "Collider.h" #include "CollisionSystem.h" -#include "ComponentManager.h" #include "types.h" #include "util/OptionalRef.h" @@ -26,17 +26,18 @@ using namespace crepe; void CollisionSystem::update() { std::vector<CollisionInternal> all_colliders; game_object_id_t id = 0; + ComponentManager & mgr = this->mediator.component_manager; RefVector<Rigidbody> rigidbodies - = this->component_manager.get_components_by_type<Rigidbody>(); + = mgr.get_components_by_type<Rigidbody>(); // Collisions can only happen on object with a rigidbody for (Rigidbody & rigidbody : rigidbodies) { if (!rigidbody.active) continue; id = rigidbody.game_object_id; Transform & transform - = this->component_manager.get_components_by_id<Transform>(id).front().get(); + = mgr.get_components_by_id<Transform>(id).front().get(); // Check if the boxcollider is active and has the same id as the rigidbody. RefVector<BoxCollider> boxcolliders - = this->component_manager.get_components_by_type<BoxCollider>(); + = mgr.get_components_by_type<BoxCollider>(); for (BoxCollider & boxcollider : boxcolliders) { if (boxcollider.game_object_id != id) continue; if (!boxcollider.active) continue; @@ -47,7 +48,7 @@ void CollisionSystem::update() { } // Check if the circlecollider is active and has the same id as the rigidbody. RefVector<CircleCollider> circlecolliders - = this->component_manager.get_components_by_type<CircleCollider>(); + = mgr.get_components_by_type<CircleCollider>(); for (CircleCollider & circlecollider : circlecolliders) { if (circlecollider.game_object_id != id) continue; if (!circlecollider.active) continue; @@ -76,11 +77,11 @@ void CollisionSystem::collision_handler_request(CollisionInternal & this_data, = this->get_collider_type(this_data.collider, other_data.collider); std::pair<vec2, CollisionSystem::Direction> resolution_data = this->collision_handler(this_data, other_data, type); - + ComponentManager & mgr = this->mediator.component_manager; OptionalRef<Metadata> this_metadata - = this->component_manager.get_components_by_id<Metadata>(this_data.id).front().get(); + = mgr.get_components_by_id<Metadata>(this_data.id).front().get(); OptionalRef<Metadata> other_metadata - = this->component_manager.get_components_by_id<Metadata>(other_data.id).front().get(); + = mgr.get_components_by_id<Metadata>(other_data.id).front().get(); OptionalRef<Collider> this_collider; OptionalRef<Collider> other_collider; switch (type) { @@ -308,7 +309,8 @@ void CollisionSystem::determine_collision_handler(CollisionInfo & info) { }; // Call collision event for user CollisionEvent data(info); - EventManager::get_instance().trigger_event<CollisionEvent>( + EventManager & emgr = this->mediator.event_manager; + emgr.trigger_event<CollisionEvent>( data, info.this_collider.game_object_id); } @@ -384,16 +386,19 @@ CollisionSystem::gather_collisions(std::vector<CollisionInternal> & colliders) { return collisions_ret; } -bool CollisionSystem::have_common_layer(const std::vector<int> & layers1, - const std::vector<int> & layers2) { - // Iterate through each layer in the first vector - for (int layer : layers1) { - // Check if the current layer is present in the second vector - if (std::find(layers2.begin(), layers2.end(), layer) != layers2.end()) { - return true; // Common layer found - } +bool CollisionSystem::have_common_layer(const std::set<int> & layers1, + const std::set<int> & layers2) { + + // Check if any number is equal in the layers + for (int num : layers1) { + if (layers2.contains(num)) { + // Common layer found + return true; + break; + } } - return false; // No common layers found + // No common layer found + return false; } CollisionSystem::CollisionInternalType diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h index eb361b8..6995bb5 100644 --- a/src/crepe/system/CollisionSystem.h +++ b/src/crepe/system/CollisionSystem.h @@ -10,6 +10,7 @@ #include "api/Rigidbody.h" #include "api/Transform.h" #include "api/Vector2.h" +#include "api/Event.h" #include "Collider.h" #include "System.h" @@ -228,7 +229,7 @@ private: * \return Returns true if there is at least one common layer, false otherwise. */ - bool have_common_layer(const std::vector<int> & layers1, const std::vector<int> & layers2); + bool have_common_layer(const std::set<int> & layers1, const std::set<int> & layers2); /** * \brief Checks for collision between two colliders. @@ -297,4 +298,14 @@ private: const Rigidbody & rigidbody2) const; }; +/** + * \brief Event triggered during a collision between objects. + */ +class CollisionEvent : public Event { +public: + crepe::CollisionSystem::CollisionInfo info; + CollisionEvent(const crepe::CollisionSystem::CollisionInfo & collisionInfo) + : info(collisionInfo) {} +}; + } // namespace crepe diff --git a/src/crepe/system/InputSystem.cpp b/src/crepe/system/InputSystem.cpp new file mode 100644 index 0000000..7cc8d30 --- /dev/null +++ b/src/crepe/system/InputSystem.cpp @@ -0,0 +1,187 @@ +#include "../api/Button.h" +#include "../manager/ComponentManager.h" +#include "../manager/EventManager.h" + +#include "InputSystem.h" + +using namespace crepe; + +void InputSystem::update() { + ComponentManager & mgr = this->mediator.component_manager; + EventManager & event_mgr = this->mediator.event_manager; + std::vector<SDLContext::EventData> event_list = SDLContext::get_instance().get_events(); + RefVector<Button> buttons = mgr.get_components_by_type<Button>(); + RefVector<Camera> cameras = mgr.get_components_by_type<Camera>(); + OptionalRef<Camera> curr_cam_ref; + // Find the active camera + for (Camera & cam : cameras) { + if (!cam.active) continue; + curr_cam_ref = cam; + break; + } + if (!curr_cam_ref) return; + Camera & current_cam = curr_cam_ref; + RefVector<Transform> transform_vec + = mgr.get_components_by_id<Transform>(current_cam.game_object_id); + Transform & cam_transform = transform_vec.front().get(); + int camera_origin_x + = cam_transform.position.x + current_cam.offset.x - (current_cam.viewport_size.x / 2); + int camera_origin_y + = cam_transform.position.y + current_cam.offset.y - (current_cam.viewport_size.y / 2); + + for (const SDLContext::EventData & event : event_list) { + int world_mouse_x = event.mouse_position.x + camera_origin_x; + int world_mouse_y = event.mouse_position.y + camera_origin_y; + // check if the mouse is within the viewport + bool mouse_in_viewport + = !(world_mouse_x < camera_origin_x + || world_mouse_x > camera_origin_x + current_cam.viewport_size.x + || world_mouse_y < camera_origin_y + || world_mouse_y > camera_origin_y + current_cam.viewport_size.y); + + switch (event.event_type) { + case SDLContext::EventType::KEYDOWN: + event_mgr.queue_event<KeyPressEvent>(KeyPressEvent{ + .repeat = event.key_repeat, + .key = event.key, + }); + break; + case SDLContext::EventType::KEYUP: + event_mgr.queue_event<KeyReleaseEvent>(KeyReleaseEvent{ + .key = event.key, + }); + break; + case SDLContext::EventType::MOUSEDOWN: + if (!mouse_in_viewport) { + break; + } + event_mgr.queue_event<MousePressEvent>(MousePressEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .button = event.mouse_button, + }); + this->last_mouse_down_position = {world_mouse_x, world_mouse_y}; + this->last_mouse_button = event.mouse_button; + break; + case SDLContext::EventType::MOUSEUP: { + if (!mouse_in_viewport) { + break; + } + event_mgr.queue_event<MouseReleaseEvent>(MouseReleaseEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .button = event.mouse_button, + }); + //check if its a click by checking the last button down + int delta_x = world_mouse_x - this->last_mouse_down_position.x; + int delta_y = world_mouse_y - this->last_mouse_down_position.y; + + if (this->last_mouse_button == event.mouse_button + && std::abs(delta_x) <= click_tolerance + && std::abs(delta_y) <= click_tolerance) { + event_mgr.queue_event<MouseClickEvent>(MouseClickEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .button = event.mouse_button, + }); + + this->handle_click(event.mouse_button, world_mouse_x, world_mouse_y); + } + } break; + case SDLContext::EventType::MOUSEMOVE: + if (!mouse_in_viewport) { + break; + } + event_mgr.queue_event<MouseMoveEvent>(MouseMoveEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .delta_x = event.rel_mouse_move.x, + .delta_y = event.rel_mouse_move.y, + }); + this->handle_move(event, world_mouse_x, world_mouse_y); + break; + case SDLContext::EventType::MOUSEWHEEL: + event_mgr.queue_event<MouseScrollEvent>(MouseScrollEvent{ + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, + .scroll_direction = event.scroll_direction, + .scroll_delta = event.scroll_delta, + }); + break; + case SDLContext::EventType::SHUTDOWN: + event_mgr.queue_event<ShutDownEvent>(ShutDownEvent{}); + break; + default: + break; + } + } +} +void InputSystem::handle_move(const SDLContext::EventData & event_data, + const int world_mouse_x, const int world_mouse_y) { + ComponentManager & mgr = this->mediator.component_manager; + + RefVector<Button> buttons = mgr.get_components_by_type<Button>(); + + for (Button & button : buttons) { + RefVector<Transform> transform_vec + = mgr.get_components_by_id<Transform>(button.game_object_id); + Transform & transform(transform_vec.front().get()); + + bool was_hovering = button.hover; + if (button.active + && this->is_mouse_inside_button(world_mouse_x, world_mouse_y, button, transform)) { + button.hover = true; + if (!was_hovering && button.on_mouse_enter) { + button.on_mouse_enter(); + } + } else { + button.hover = false; + // Trigger the on_exit callback if the hover state just changed to false + if (was_hovering && button.on_mouse_exit) { + button.on_mouse_exit(); + } + } + } +} + +void InputSystem::handle_click(const MouseButton & mouse_button, const int world_mouse_x, + const int world_mouse_y) { + ComponentManager & mgr = this->mediator.component_manager; + + RefVector<Button> buttons = mgr.get_components_by_type<Button>(); + + for (Button & button : buttons) { + RefVector<Transform> transform_vec + = mgr.get_components_by_id<Transform>(button.game_object_id); + Transform & transform = transform_vec.front().get(); + + if (button.active + && this->is_mouse_inside_button(world_mouse_x, world_mouse_y, button, transform)) { + this->handle_button_press(button); + } + } +} + +bool InputSystem::is_mouse_inside_button(const int mouse_x, const int mouse_y, + const Button & button, const Transform & transform) { + int actual_x = transform.position.x + button.offset.x; + int actual_y = transform.position.y + button.offset.y; + + int half_width = button.dimensions.x / 2; + int half_height = button.dimensions.y / 2; + + // Check if the mouse is within the button's boundaries + return mouse_x >= actual_x - half_width && mouse_x <= actual_x + half_width + && mouse_y >= actual_y - half_height && mouse_y <= actual_y + half_height; +} + +void InputSystem::handle_button_press(Button & button) { + if (button.is_toggle) { + if (!button.is_pressed && button.on_click) { + button.on_click(); + } + button.is_pressed = !button.is_pressed; + } else if (button.on_click) { + button.on_click(); + } +} diff --git a/src/crepe/system/InputSystem.h b/src/crepe/system/InputSystem.h new file mode 100644 index 0000000..87e86f8 --- /dev/null +++ b/src/crepe/system/InputSystem.h @@ -0,0 +1,85 @@ +#pragma once + +#include "../facade/SDLContext.h" +#include "../types.h" +#include "../util/OptionalRef.h" + +#include "System.h" + +namespace crepe { + +class Camera; +class Button; +class Transform; + +/** + * \brief Handles the processing of input events created by SDLContext + * + * This system processes events such as mouse clicks, mouse movement, and keyboard + * actions. It is responsible for detecting interactions with UI buttons and + * passing the corresponding events to the registered listeners. + */ +class InputSystem : public System { +public: + using System::System; + + /** + * \brief Updates the system, processing all input events. + * This method processes all events and triggers corresponding actions. + */ + void update() override; + +private: + //! Stores the last position of the mouse when the button was pressed. + ivec2 last_mouse_down_position; + // TODO: specify world/hud space and make regular `vec2` + + //! Stores the last mouse button pressed. + MouseButton last_mouse_button = MouseButton::NONE; + + //! The maximum allowable distance between mouse down and mouse up to register as a click. + const int click_tolerance = 5; + + /** + * \brief Handles the mouse click event. + * \param mouse_button The mouse button involved in the click. + * \param world_mouse_x The X coordinate of the mouse in world space. + * \param world_mouse_y The Y coordinate of the mouse in world space. + * + * This method processes the mouse click event and triggers the corresponding button action. + */ + void handle_click(const MouseButton & mouse_button, const int world_mouse_x, + const int world_mouse_y); + + /** + * \brief Handles the mouse movement event. + * \param event_data The event data containing information about the mouse movement. + * \param world_mouse_x The X coordinate of the mouse in world space. + * \param world_mouse_y The Y coordinate of the mouse in world space. + * + * This method processes the mouse movement event and updates the button hover state. + */ + void handle_move(const SDLContext::EventData & event_data, const int world_mouse_x, + const int world_mouse_y); + + /** + * \brief Checks if the mouse position is inside the bounds of the button. + * \param world_mouse_x The X coordinate of the mouse in world space. + * \param world_mouse_y The Y coordinate of the mouse in world space. + * \param button The button to check. + * \param transform The transform component of the button. + * \return True if the mouse is inside the button, false otherwise. + */ + bool is_mouse_inside_button(const int world_mouse_x, const int world_mouse_y, + const Button & button, const Transform & transform); + + /** + * \brief Handles the button press event, calling the on_click callback if necessary. + * \param button The button being pressed. + * + * This method triggers the on_click action for the button when it is pressed. + */ + void handle_button_press(Button & button); +}; + +} // namespace crepe diff --git a/src/crepe/system/ParticleSystem.cpp b/src/crepe/system/ParticleSystem.cpp index 0e62a57..b14c52f 100644 --- a/src/crepe/system/ParticleSystem.cpp +++ b/src/crepe/system/ParticleSystem.cpp @@ -2,17 +2,17 @@ #include <cstdlib> #include <ctime> -#include "api/ParticleEmitter.h" -#include "api/Transform.h" +#include "../api/ParticleEmitter.h" +#include "../api/Transform.h" +#include "../manager/ComponentManager.h" -#include "ComponentManager.h" #include "ParticleSystem.h" using namespace crepe; void ParticleSystem::update() { // Get all emitters - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector<ParticleEmitter> emitters = mgr.get_components_by_type<ParticleEmitter>(); for (ParticleEmitter & emitter : emitters) { diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp index b3adfa1..ebf4439 100644 --- a/src/crepe/system/PhysicsSystem.cpp +++ b/src/crepe/system/PhysicsSystem.cpp @@ -1,17 +1,17 @@ #include <cmath> -#include "../ComponentManager.h" #include "../api/Config.h" #include "../api/Rigidbody.h" #include "../api/Transform.h" #include "../api/Vector2.h" +#include "../manager/ComponentManager.h" #include "PhysicsSystem.h" using namespace crepe; void PhysicsSystem::update() { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector<Rigidbody> rigidbodies = mgr.get_components_by_type<Rigidbody>(); RefVector<Transform> transforms = mgr.get_components_by_type<Transform>(); diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 11c9669..92dba43 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -5,12 +5,12 @@ #include <stdexcept> #include <vector> -#include "../ComponentManager.h" #include "../api/Camera.h" #include "../api/ParticleEmitter.h" #include "../api/Sprite.h" #include "../api/Transform.h" #include "../facade/SDLContext.h" +#include "../manager/ComponentManager.h" #include "RenderSystem.h" @@ -22,7 +22,7 @@ void RenderSystem::clear_screen() { this->context.clear_screen(); } void RenderSystem::present_screen() { this->context.present_screen(); } const Camera & RenderSystem::update_camera() { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector<Camera> cameras = mgr.get_components_by_type<Camera>(); @@ -62,7 +62,7 @@ void RenderSystem::update() { bool RenderSystem::render_particle(const Sprite & sprite, const Camera & cam, const double & scale) { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; vector<reference_wrapper<ParticleEmitter>> emitters = mgr.get_components_by_id<ParticleEmitter>(sprite.game_object_id); @@ -102,7 +102,7 @@ void RenderSystem::render_normal(const Sprite & sprite, const Camera & cam, } void RenderSystem::render() { - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; const Camera & cam = this->update_camera(); RefVector<Sprite> sprites = mgr.get_components_by_type<Sprite>(); diff --git a/src/crepe/system/ScriptSystem.cpp b/src/crepe/system/ScriptSystem.cpp index 20a83f7..d6b2ca1 100644 --- a/src/crepe/system/ScriptSystem.cpp +++ b/src/crepe/system/ScriptSystem.cpp @@ -1,6 +1,6 @@ -#include "../ComponentManager.h" #include "../api/BehaviorScript.h" #include "../api/Script.h" +#include "../manager/ComponentManager.h" #include "ScriptSystem.h" @@ -10,7 +10,7 @@ using namespace crepe; void ScriptSystem::update() { dbg_trace(); - ComponentManager & mgr = this->component_manager; + ComponentManager & mgr = this->mediator.component_manager; RefVector<BehaviorScript> behavior_scripts = mgr.get_components_by_type<BehaviorScript>(); for (BehaviorScript & behavior_script : behavior_scripts) { diff --git a/src/crepe/system/System.cpp b/src/crepe/system/System.cpp index 937a423..f68549b 100644 --- a/src/crepe/system/System.cpp +++ b/src/crepe/system/System.cpp @@ -4,4 +4,4 @@ using namespace crepe; -System::System(ComponentManager & mgr) : component_manager(mgr) { dbg_trace(); } +System::System(const Mediator & mediator) : mediator(mediator) { dbg_trace(); } diff --git a/src/crepe/system/System.h b/src/crepe/system/System.h index 28ea20e..063dfbf 100644 --- a/src/crepe/system/System.h +++ b/src/crepe/system/System.h @@ -1,5 +1,7 @@ #pragma once +#include "../manager/Mediator.h" + namespace crepe { class ComponentManager; @@ -7,9 +9,8 @@ class ComponentManager; /** * \brief Base ECS system class * - * This class is used as the base for all system classes. Classes derived from - * System must implement the System::update() method and copy Script::Script - * with the `using`-syntax. + * This class is used as the base for all system classes. Classes derived from System must + * implement the System::update() method and copy Script::Script with the `using`-syntax. */ class System { public: @@ -19,11 +20,11 @@ public: virtual void update() = 0; public: - System(ComponentManager &); + System(const Mediator & m); virtual ~System() = default; protected: - ComponentManager & component_manager; + const Mediator & mediator; }; } // namespace crepe |