diff options
-rw-r--r-- | mwe/.vscode/settings.json | 11 | ||||
-rw-r--r-- | mwe/events/.vscode/c_cpp_properties.json | 15 | ||||
-rw-r--r-- | mwe/events/.vscode/settings.json | 16 | ||||
-rw-r--r-- | mwe/events/CMakeLists.txt | 6 | ||||
-rw-r--r-- | mwe/events/include/event.h | 245 | ||||
-rw-r--r-- | mwe/events/include/eventHandler.h | 35 | ||||
-rw-r--r-- | mwe/events/include/eventManager.h | 63 | ||||
-rw-r--r-- | mwe/events/include/keyCodes.h | 143 | ||||
-rw-r--r-- | mwe/events/include/loopManager.h | 28 | ||||
-rw-r--r-- | mwe/events/include/timer.h | 31 | ||||
-rw-r--r-- | mwe/events/src/event.cpp | 56 | ||||
-rw-r--r-- | mwe/events/src/eventHandler.cpp | 5 | ||||
-rw-r--r-- | mwe/events/src/eventManager.cpp | 108 | ||||
-rw-r--r-- | mwe/events/src/keyCodes.cpp | 140 | ||||
-rw-r--r-- | mwe/events/src/loopManager.cpp | 90 | ||||
-rw-r--r-- | mwe/events/src/main.cpp | 54 | ||||
-rw-r--r-- | mwe/events/src/timer.cpp | 54 | ||||
-rw-r--r-- | mwe/events/src/window.cpp | 3 | ||||
-rw-r--r-- | mwe/gameloop/include/loopManager.h | 1 |
19 files changed, 878 insertions, 226 deletions
diff --git a/mwe/.vscode/settings.json b/mwe/.vscode/settings.json new file mode 100644 index 0000000..c7913ab --- /dev/null +++ b/mwe/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "files.associations": { + "variant": "cpp", + "*.tcc": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "string_view": "cpp", + "ostream": "cpp", + "iostream": "cpp" + } +} diff --git a/mwe/events/.vscode/c_cpp_properties.json b/mwe/events/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..64d3f90 --- /dev/null +++ b/mwe/events/.vscode/c_cpp_properties.json @@ -0,0 +1,15 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [], + "cStandard": "c17", + "cppStandard": "c++17", + "intelliSenseMode": "linux-clang-x64" + } + ], + "version": 4 +}
\ No newline at end of file diff --git a/mwe/events/.vscode/settings.json b/mwe/events/.vscode/settings.json index b2c5be7..816d790 100644 --- a/mwe/events/.vscode/settings.json +++ b/mwe/events/.vscode/settings.json @@ -49,6 +49,20 @@ "streambuf": "cpp", "cinttypes": "cpp", "typeinfo": "cpp", - "valarray": "cpp" + "valarray": "cpp", + "variant": "cpp", + "condition_variable": "cpp", + "ctime": "cpp", + "forward_list": "cpp", + "executor": "cpp", + "io_context": "cpp", + "netfwd": "cpp", + "ratio": "cpp", + "timer": "cpp", + "future": "cpp", + "mutex": "cpp", + "semaphore": "cpp", + "stop_token": "cpp", + "thread": "cpp" } } diff --git a/mwe/events/CMakeLists.txt b/mwe/events/CMakeLists.txt index 3bbda37..585d869 100644 --- a/mwe/events/CMakeLists.txt +++ b/mwe/events/CMakeLists.txt @@ -13,7 +13,13 @@ find_package(SDL2 REQUIRED) add_executable(gameloop src/window.cpp src/main.cpp + #src/eventHandler.cpp src/eventManager.cpp + src/event.cpp + src/loopManager.cpp + src/timer.cpp + src/keyCodes.cpp + src/eventHandler.cpp ) # Link the SDL2 library to your project diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h index f5f426a..802140c 100644 --- a/mwe/events/include/event.h +++ b/mwe/events/include/event.h @@ -4,215 +4,84 @@ #include <string> #include <unordered_map> #include <variant> -using Keycode = uint16_t; -enum : Keycode { - // From glfw3.h - Space = 32, - Apostrophe = 39, /* ' */ - Comma = 44, /* , */ - Minus = 45, /* - */ - Period = 46, /* . */ - Slash = 47, /* / */ - - D0 = 48, /* 0 */ - D1 = 49, /* 1 */ - D2 = 50, /* 2 */ - D3 = 51, /* 3 */ - D4 = 52, /* 4 */ - D5 = 53, /* 5 */ - D6 = 54, /* 6 */ - D7 = 55, /* 7 */ - D8 = 56, /* 8 */ - D9 = 57, /* 9 */ - - Semicolon = 59, /* ; */ - Equal = 61, /* = */ - - A = 65, - B = 66, - C = 67, - D = 68, - E = 69, - F = 70, - G = 71, - H = 72, - I = 73, - J = 74, - K = 75, - L = 76, - M = 77, - N = 78, - O = 79, - P = 80, - Q = 81, - R = 82, - S = 83, - T = 84, - U = 85, - V = 86, - W = 87, - X = 88, - Y = 89, - Z = 90, - - LeftBracket = 91, /* [ */ - Backslash = 92, /* \ */ - RightBracket = 93, /* ] */ - GraveAccent = 96, /* ` */ - - World1 = 161, /* non-US #1 */ - World2 = 162, /* non-US #2 */ - - /* Function keys */ - Escape = 256, - Enter = 257, - Tab = 258, - Backspace = 259, - Insert = 260, - Delete = 261, - Right = 262, - Left = 263, - Down = 264, - Up = 265, - PageUp = 266, - PageDown = 267, - Home = 268, - End = 269, - CapsLock = 280, - ScrollLock = 281, - NumLock = 282, - PrintScreen = 283, - Pause = 284, - F1 = 290, - F2 = 291, - F3 = 292, - F4 = 293, - F5 = 294, - F6 = 295, - F7 = 296, - F8 = 297, - F9 = 298, - F10 = 299, - F11 = 300, - F12 = 301, - F13 = 302, - F14 = 303, - F15 = 304, - F16 = 305, - F17 = 306, - F18 = 307, - F19 = 308, - F20 = 309, - F21 = 310, - F22 = 311, - F23 = 312, - F24 = 313, - F25 = 314, - - /* Keypad */ - KP0 = 320, - KP1 = 321, - KP2 = 322, - KP3 = 323, - KP4 = 324, - KP5 = 325, - KP6 = 326, - KP7 = 327, - KP8 = 328, - KP9 = 329, - KPDecimal = 330, - KPDivide = 331, - KPMultiply = 332, - KPSubtract = 333, - KPAdd = 334, - KPEnter = 335, - KPEqual = 336, - - LeftShift = 340, - LeftControl = 341, - LeftAlt = 342, - LeftSuper = 343, - RightShift = 344, - RightControl = 345, - RightAlt = 346, - RightSuper = 347, - Menu = 348 -}; +#include "keyCodes.h" class UUIDGenerator { public: - static std::uint32_t GetUniqueID() - { + static std::uint32_t getUniqueID() { static std::uint32_t id = 0; return ++id; } }; -#define EVENT_TYPE(event_type) \ - static std::uint32_t GetStaticEventType() \ - { \ - static std::uint32_t type = UUIDGenerator::GetUniqueID(); \ - return type; \ - } \ - std::uint32_t GetEventId() const override \ - { \ - return GetStaticEventType(); \ +#define REGISTER_EVENT_TYPE(ClassName) \ +public: \ + static std::uint32_t getStaticEventType() { \ + static std::uint32_t typeID = UUIDGenerator::getUniqueID(); \ + return typeID; \ + } \ + virtual std::uint32_t getEventType() const override { \ + return getStaticEventType(); \ } class Event { - public: - Event(std::string eventType) { - eventData["eventType"] = eventType; - } - virtual ~Event() = default; - - virtual std::uint32_t GetEventId() const = 0; - virtual std::string toString() const { - return std::to_string(GetEventId()); - } - - void addArgument(const std::string& key, const std::variant<int, std::string, float>& value); - - std::variant<int, std::string, float> getArgument(const std::string& key) const; - - std::string getType() const; - bool isHandled() const; - void markHandled(); - private: - std::unordered_map<std::string, std::variant<int, std::string, float>> eventData; - bool isHandled = false; +public: + Event(std::string eventType); + virtual ~Event() = default; + virtual std::uint32_t getEventType() const = 0; + virtual std::string toString() const; + void addArgument(const std::string& key, const std::variant<int, std::string, float>& value); + + std::variant<int, std::string, float> getArgument(const std::string& key) const; + + std::string getType() const; + bool getHandled() const; + void markHandled(); + +private: + std::unordered_map<std::string, std::variant<int, std::string, float>> eventData; + bool isHandled = false; }; +// KeyPressedEvent class class KeyPressedEvent : public Event { - public: - EVENT_TYPE("KeyPressedEvent"); - KeyPressedEvent(int keyCode); - Keycode getKeyCode() const; - int getRepeatCount() const; - private: - Keycode keycode; +public: + KeyPressedEvent(int keyCode); + + REGISTER_EVENT_TYPE("KeyPressedEvent"); + + Keycode getKeyCode() const; + int getRepeatCount() const; + +private: + Keycode keycode; + public: Keycode key = 0; int repeatCount = 0; }; +// KeyReleasedEvent class class KeyReleasedEvent : public Event { - public: - EVENT_TYPE("KeyReleasedEvent"); - KeyReleasedEvent(int keyCode); - Keycode getKeyCode(); - private: - Keycode keycode; public: + KeyReleasedEvent(int keyCode); + + REGISTER_EVENT_TYPE(KeyReleasedEvent); + + Keycode getKeyCode() const; + +private: Keycode key = 0; }; +// MousePressedEvent class class MousePressedEvent : public Event { - public: - EVENT_TYPE("MousePressedEvent"); - MousePressedEvent(int mouseX,int mouseY); - std::pair<int,int> getMousePosition(); - private: - Keycode keycode; - int mouseX = 0; - int mouseY = 0; - +public: + MousePressedEvent(int mouseX, int mouseY); + + REGISTER_EVENT_TYPE(MousePressedEvent) + + std::pair<int, int> getMousePosition() const; + +private: + int mouseX = 0; + int mouseY = 0; }; diff --git a/mwe/events/include/eventHandler.h b/mwe/events/include/eventHandler.h index 03017dd..e5b99d6 100644 --- a/mwe/events/include/eventHandler.h +++ b/mwe/events/include/eventHandler.h @@ -1,39 +1,48 @@ #pragma once + #include "event.h" -#include <iostream> + #include <functional> +#include <iostream> template<typename EventType> using EventHandler = std::function<void(const EventType& e)>; -class IEventHandlerWrapper{ + +class IEventHandlerWrapper { public: - void Exec(const Event& e) - { - Call(e); - } + virtual ~IEventHandlerWrapper() = default; + + void exec(const Event& e); - virtual std::string GetType() const = 0; + virtual std::string getType() const = 0; + virtual bool isDestroyOnSuccess() const = 0; private: - virtual void Call(const Event& e) = 0; + virtual void call(const Event& e) = 0; }; template<typename EventType> class EventHandlerWrapper : public IEventHandlerWrapper { public: - explicit EventHandlerWrapper(const EventHandler<EventType>& handler) + explicit EventHandlerWrapper(const EventHandler<EventType>& handler, const bool destroyOnSuccess = false) : m_handler(handler) - , m_handlerType(m_handler.target_type().name()) {}; + , m_handlerType(m_handler.target_type().name()) + , m_destroyOnSuccess(destroyOnSuccess) + { + // std::cout << m_handlerType << std::endl; + } private: - void Call(const Event& e) override + void call(const Event& e) override { - if (e.GetEventType() == EventType::GetStaticEventType()) { + if (e.getEventType() == EventType::getStaticEventType()) { m_handler(static_cast<const EventType&>(e)); } } - std::string GetType() const override { return m_handlerType; } + std::string getType() const override { return m_handlerType; } + bool isDestroyOnSuccess() const { return m_destroyOnSuccess; } EventHandler<EventType> m_handler; const std::string m_handlerType; + bool m_destroyOnSuccess { false }; }; diff --git a/mwe/events/include/eventManager.h b/mwe/events/include/eventManager.h index 93def36..709796a 100644 --- a/mwe/events/include/eventManager.h +++ b/mwe/events/include/eventManager.h @@ -2,17 +2,56 @@ #include <unordered_map> #include <memory> #include "event.h" +#include "keyCodes.h" #include "eventHandler.h" -using EventType = int; -using EventId = int; -class EventManager{ - public: - - void subscribe(EventId eventId,std::unique_ptr<IEventHandlerWrapper>&& handler); - void unsubscribe(EventId eventId, const std::string& handlerName); - void dispatchEvents(); - void triggerEvent(EventId eventId); - void queueEvent(); - private: - std::unordered_map<EventType, std::vector<std::unique_ptr<IEventHandlerWrapper>>> m_subscribers; +#include <vector> +// using EventType = std::uint32_t; +// using EventId = std::uint64_t; + +class EventManager { +public: + EventManager(const EventManager&) = delete; + const EventManager& operator=(const EventManager&) = delete; + static EventManager& getInstance() { + static EventManager instance; + return instance; + } + + void shutdown(); + void subscribe(int eventType, std::unique_ptr<IEventHandlerWrapper>&& handler, int eventId); + void unsubscribe(int eventType, const std::string& handlerName, int eventId); + void triggerEvent(const Event& event_, int eventId); + void queueEvent(std::unique_ptr<Event>&& event_, int eventId); + void dispatchEvents(); + +private: + EventManager() = default; + std::vector<std::pair<std::unique_ptr<Event>, int>> m_eventsQueue; + std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>> m_subscribers; + std::unordered_map<int, std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>> m_subscribersByEventId; }; + + +template<typename EventType> +inline void subscribe(const EventHandler<EventType>& callback, int eventId = 0, const bool unsubscribeOnSuccess = false) +{ + std::unique_ptr<IEventHandlerWrapper> handler = std::make_unique<EventHandlerWrapper<EventType>>(callback, unsubscribeOnSuccess); + EventManager::getInstance().subscribe(EventType::getStaticEventType(), std::move(handler), eventId); +} + +template<typename EventType> +inline void unsubscribe(const EventHandler<EventType>& callback, int eventId = 0) +{ + const std::string handlerName = callback.target_type().name(); + EventManager::getInstance().unsubscribe(EventType::getStaticEventType(), handlerName, eventId); +} + +inline void triggerEvent(const Event& triggeredEvent, int eventId = 0) +{ + EventManager::getInstance().triggerEvent(triggeredEvent, eventId); +} + +inline void queueEvent(std::unique_ptr<Event>&& queuedEvent, int eventId = 0) +{ + EventManager::getInstance().queueEvent(std::forward<std::unique_ptr<Event>>(queuedEvent), eventId); +} diff --git a/mwe/events/include/keyCodes.h b/mwe/events/include/keyCodes.h new file mode 100644 index 0000000..c3a7826 --- /dev/null +++ b/mwe/events/include/keyCodes.h @@ -0,0 +1,143 @@ +#pragma once +#include <cstdint> +#include <unordered_map> +#include <SDL2/SDL.h> +using Keycode = uint16_t; +enum : Keycode { + // From glfw3.h + Space = 32, + Apostrophe = 39, /* ' */ + Comma = 44, /* , */ + Minus = 45, /* - */ + Period = 46, /* . */ + Slash = 47, /* / */ + + D0 = 48, /* 0 */ + D1 = 49, /* 1 */ + D2 = 50, /* 2 */ + D3 = 51, /* 3 */ + D4 = 52, /* 4 */ + D5 = 53, /* 5 */ + D6 = 54, /* 6 */ + D7 = 55, /* 7 */ + D8 = 56, /* 8 */ + D9 = 57, /* 9 */ + + Semicolon = 59, /* ; */ + Equal = 61, /* = */ + + A = 65, + B = 66, + C = 67, + D = 68, + E = 69, + F = 70, + G = 71, + H = 72, + I = 73, + J = 74, + K = 75, + L = 76, + M = 77, + N = 78, + O = 79, + P = 80, + Q = 81, + R = 82, + S = 83, + T = 84, + U = 85, + V = 86, + W = 87, + X = 88, + Y = 89, + Z = 90, + + LeftBracket = 91, /* [ */ + Backslash = 92, /* \ */ + RightBracket = 93, /* ] */ + GraveAccent = 96, /* ` */ + + World1 = 161, /* non-US #1 */ + World2 = 162, /* non-US #2 */ + + /* Function keys */ + Escape = 256, + Enter = 257, + Tab = 258, + Backspace = 259, + Insert = 260, + Delete = 261, + Right = 262, + Left = 263, + Down = 264, + Up = 265, + PageUp = 266, + PageDown = 267, + Home = 268, + End = 269, + CapsLock = 280, + ScrollLock = 281, + NumLock = 282, + PrintScreen = 283, + Pause = 284, + F1 = 290, + F2 = 291, + F3 = 292, + F4 = 293, + F5 = 294, + F6 = 295, + F7 = 296, + F8 = 297, + F9 = 298, + F10 = 299, + F11 = 300, + F12 = 301, + F13 = 302, + F14 = 303, + F15 = 304, + F16 = 305, + F17 = 306, + F18 = 307, + F19 = 308, + F20 = 309, + F21 = 310, + F22 = 311, + F23 = 312, + F24 = 313, + F25 = 314, + + /* Keypad */ + KP0 = 320, + KP1 = 321, + KP2 = 322, + KP3 = 323, + KP4 = 324, + KP5 = 325, + KP6 = 326, + KP7 = 327, + KP8 = 328, + KP9 = 329, + KPDecimal = 330, + KPDivide = 331, + KPMultiply = 332, + KPSubtract = 333, + KPAdd = 334, + KPEnter = 335, + KPEqual = 336, + + LeftShift = 340, + LeftControl = 341, + LeftAlt = 342, + LeftSuper = 343, + RightShift = 344, + RightControl = 345, + RightAlt = 346, + RightSuper = 347, + Menu = 348 +}; +// Define the mapping +extern const std::unordered_map<SDL_Keycode, Keycode> sdlToCustom; + +// Function to map SDL_Keycode to custom Keycode +Keycode getCustomKey(SDL_Keycode sdlKey); diff --git a/mwe/events/include/loopManager.h b/mwe/events/include/loopManager.h new file mode 100644 index 0000000..5c519d9 --- /dev/null +++ b/mwe/events/include/loopManager.h @@ -0,0 +1,28 @@ +#pragma once +#include "window.h" +#include <SDL2/SDL.h> +#include "timer.h" +//#include "combinedEvent.h" +#include "eventManager.h" +#include "loopManager.h" +#include "eventHandler.h" +class LoopManager { +public: + LoopManager(); + void setup(); + void loop(); + void setRunning(bool running); +private: + void processInput(); + void update(); + void lateUpdate(); + void fixedUpdate(); + void render(); + bool gameRunning = false; + WindowManager window; + int timeScale = 1; + float accumulator = 0.0; + double currentTime; + double t = 0.0; + double dt = 0.01; +}; diff --git a/mwe/events/include/timer.h b/mwe/events/include/timer.h new file mode 100644 index 0000000..22383b2 --- /dev/null +++ b/mwe/events/include/timer.h @@ -0,0 +1,31 @@ +#pragma once + +#include <SDL2/SDL.h> + +class LoopTimer { +public: + static LoopTimer & getInstance(); + void start(); + void update(); + double getDeltaTime() const; + int getCurrentTime() const; + void advanceFixedUpdate(); + double getFixedDeltaTime() const; + void setFPS(int FPS); + int getFPS() const; + void enforceFrameRate(); + double getLag() const; + +private: + LoopTimer(); + int FPS = 50; + double gameScale = 1; + double maximumDeltaTime = 0.25; + double deltaTime; + double frameTargetTime = FPS / 1000; + double fixedDeltaTime = 0.01; + double elapsedTime; + double elapsedFixedTime; + double time; + uint64_t lastFrameTime; +}; diff --git a/mwe/events/src/event.cpp b/mwe/events/src/event.cpp new file mode 100644 index 0000000..fecae76 --- /dev/null +++ b/mwe/events/src/event.cpp @@ -0,0 +1,56 @@ +#include "event.h" +#include "keyCodes.h" +// Event class methods +Event::Event(std::string eventType) { + eventData["eventType"] = eventType; +} + +void Event::addArgument(const std::string& key, const std::variant<int, std::string, float>& value) { + eventData[key] = value; +} + +std::variant<int, std::string, float> Event::getArgument(const std::string& key) const { + return eventData.at(key); +} + +std::string Event::getType() const { + return std::get<std::string>(eventData.at("eventType")); +} +std::string Event::toString() const { + return std::to_string(getEventType()); +} +bool Event::getHandled() const { + return isHandled; +} + +void Event::markHandled() { + isHandled = true; +} + +// KeyPressedEvent class methods +KeyPressedEvent::KeyPressedEvent(int keycode) + : Event("KeyPressedEvent"), key(keycode), repeatCount(0) {} + +Keycode KeyPressedEvent::getKeyCode() const { + return key; +} + +int KeyPressedEvent::getRepeatCount() const { + return repeatCount; +} + +// KeyReleasedEvent class methods +KeyReleasedEvent::KeyReleasedEvent(int keycode) + : Event("KeyReleasedEvent"), key(keycode) {} + +Keycode KeyReleasedEvent::getKeyCode() const { + return key; +} + +// MousePressedEvent class methods +MousePressedEvent::MousePressedEvent(int mouseX, int mouseY) + : Event("MousePressedEvent"), mouseX(mouseX), mouseY(mouseY) {} + +std::pair<int, int> MousePressedEvent::getMousePosition() const { + return {mouseX, mouseY}; +} diff --git a/mwe/events/src/eventHandler.cpp b/mwe/events/src/eventHandler.cpp new file mode 100644 index 0000000..7040d8d --- /dev/null +++ b/mwe/events/src/eventHandler.cpp @@ -0,0 +1,5 @@ +#include "eventHandler.h" +void IEventHandlerWrapper::exec(const Event& e) + { + call(e); + } diff --git a/mwe/events/src/eventManager.cpp b/mwe/events/src/eventManager.cpp index 8b13789..ce8e940 100644 --- a/mwe/events/src/eventManager.cpp +++ b/mwe/events/src/eventManager.cpp @@ -1 +1,109 @@ +#include "eventManager.h" +void EventManager::shutdown() +{ + m_subscribers.clear(); +} + +void EventManager::subscribe(int eventType, std::unique_ptr<IEventHandlerWrapper>&& handler, int eventId) +{ + if (eventId) { + std::unordered_map<int, std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>>::iterator subscribers = m_subscribersByEventId.find(eventType); + + if (subscribers != m_subscribersByEventId.end()) { + std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>& handlersMap = subscribers->second; + std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator handlers = handlersMap.find(eventId); + if (handlers != handlersMap.end()) { + handlers->second.emplace_back(std::move(handler)); + return; + } + } + m_subscribersByEventId[eventType][eventId].emplace_back(std::move(handler)); + + } else { + std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator subscribers = m_subscribers.find(eventType); + if (subscribers != m_subscribers.end()) { + std::vector<std::unique_ptr<IEventHandlerWrapper>>& handlers = subscribers->second; + for (std::unique_ptr<IEventHandlerWrapper>& it : handlers) { + if (it->getType() == handler->getType()) { + // log for double register + return; + } + } + handlers.emplace_back(std::move(handler)); + } else { + m_subscribers[eventType].emplace_back(std::move(handler)); + } + } +} + +void EventManager::unsubscribe(int eventType, const std::string& handlerName, int eventId) +{ + if (eventId) { + std::unordered_map<int, std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>>::iterator subscribers = m_subscribersByEventId.find(eventType); + if (subscribers != m_subscribersByEventId.end()) { + std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>& handlersMap = subscribers->second; + std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator handlers = handlersMap.find(eventId); + if (handlers != handlersMap.end()) { + std::vector<std::unique_ptr<IEventHandlerWrapper>>& callbacks = handlers->second; + for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it = callbacks.begin(); it != callbacks.end(); ++it) { + if (it->get()->getType() == handlerName) { + it = callbacks.erase(it); + return; + } + } + } + } + } else { + std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator handlersIt = m_subscribers.find(eventType); + if (handlersIt != m_subscribers.end()) { + std::vector<std::unique_ptr<IEventHandlerWrapper>>& handlers = handlersIt->second; + for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it = handlers.begin(); it != handlers.end(); ++it) { + if (it->get()->getType() == handlerName) { + it = handlers.erase(it); + return; + } + } + } + } +} + +void EventManager::triggerEvent(const Event& event_, int eventId) +{ + std::vector<std::unique_ptr<IEventHandlerWrapper>>& handlers = m_subscribers[event_.getEventType()]; + for (std::unique_ptr<IEventHandlerWrapper>& handler : handlers) { + handler->exec(event_); + } + + std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>& handlersMap = m_subscribersByEventId[event_.getEventType()]; + std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator handlersIt = handlersMap.find(eventId); + if (handlersIt != handlersMap.end()) { + std::vector<std::unique_ptr<IEventHandlerWrapper>>& callbacks = handlersIt->second; + for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it = callbacks.begin(); it != callbacks.end();) { + std::unique_ptr<IEventHandlerWrapper>& handler = *it; + handler->exec(event_); + if (handler->isDestroyOnSuccess()) { + it = callbacks.erase(it); + } else { + ++it; + } + } + } +} + +void EventManager::queueEvent(std::unique_ptr<Event>&& event_, int eventId) +{ + m_eventsQueue.emplace_back(std::move(event_), eventId); +} + +void EventManager::dispatchEvents() +{ + for (std::vector<std::pair<std::unique_ptr<Event>, int>>::iterator eventIt = m_eventsQueue.begin(); eventIt != m_eventsQueue.end();) { + if (!eventIt->first.get()->getHandled()) { + triggerEvent(*eventIt->first.get(), eventIt->second); + eventIt = m_eventsQueue.erase(eventIt); + } else { + ++eventIt; + } + } +} diff --git a/mwe/events/src/keyCodes.cpp b/mwe/events/src/keyCodes.cpp new file mode 100644 index 0000000..6f35d11 --- /dev/null +++ b/mwe/events/src/keyCodes.cpp @@ -0,0 +1,140 @@ +#include "keyCodes.h" + +const std::unordered_map<SDL_Keycode, Keycode> sdlToCustom = { + { SDLK_SPACE, Space }, + { SDLK_QUOTE, Apostrophe }, + { SDLK_COMMA, Comma }, + { SDLK_MINUS, Minus }, + { SDLK_PERIOD, Period }, + { SDLK_SLASH, Slash }, + + { SDLK_0, D0 }, + { SDLK_1, D1 }, + { SDLK_2, D2 }, + { SDLK_3, D3 }, + { SDLK_4, D4 }, + { SDLK_5, D5 }, + { SDLK_6, D6 }, + { SDLK_7, D7 }, + { SDLK_8, D8 }, + { SDLK_9, D9 }, + + { SDLK_SEMICOLON, Semicolon }, + { SDLK_EQUALS, Equal }, + + { SDLK_a, A }, + { SDLK_b, B }, + { SDLK_c, C }, + { SDLK_d, D }, + { SDLK_e, E }, + { SDLK_f, F }, + { SDLK_g, G }, + { SDLK_h, H }, + { SDLK_i, I }, + { SDLK_j, J }, + { SDLK_k, K }, + { SDLK_l, L }, + { SDLK_m, M }, + { SDLK_n, N }, + { SDLK_o, O }, + { SDLK_p, P }, + { SDLK_q, Q }, + { SDLK_r, R }, + { SDLK_s, S }, + { SDLK_t, T }, + { SDLK_u, U }, + { SDLK_v, V }, + { SDLK_w, W }, + { SDLK_x, X }, + { SDLK_y, Y }, + { SDLK_z, Z }, + + { SDLK_LEFTBRACKET, LeftBracket }, + { SDLK_BACKSLASH, Backslash }, + { SDLK_RIGHTBRACKET, RightBracket }, + { SDLK_BACKQUOTE, GraveAccent }, + + { SDLK_ESCAPE, Escape }, + { SDLK_RETURN, Enter }, + { SDLK_TAB, Tab }, + { SDLK_BACKSPACE, Backspace }, + { SDLK_INSERT, Insert }, + { SDLK_DELETE, Delete }, + { SDLK_RIGHT, Right }, + { SDLK_LEFT, Left }, + { SDLK_DOWN, Down }, + { SDLK_UP, Up }, + { SDLK_PAGEUP, PageUp }, + { SDLK_PAGEDOWN, PageDown }, + { SDLK_HOME, Home }, + { SDLK_END, End }, + + { SDLK_CAPSLOCK, CapsLock }, + { SDLK_SCROLLLOCK, ScrollLock }, + { SDLK_NUMLOCKCLEAR, NumLock }, + { SDLK_PRINTSCREEN, PrintScreen }, + { SDLK_PAUSE, Pause }, + + { SDLK_F1, F1 }, + { SDLK_F2, F2 }, + { SDLK_F3, F3 }, + { SDLK_F4, F4 }, + { SDLK_F5, F5 }, + { SDLK_F6, F6 }, + { SDLK_F7, F7 }, + { SDLK_F8, F8 }, + { SDLK_F9, F9 }, + { SDLK_F10, F10 }, + { SDLK_F11, F11 }, + { SDLK_F12, F12 }, + { SDLK_F13, F13 }, + { SDLK_F14, F14 }, + { SDLK_F15, F15 }, + { SDLK_F16, F16 }, + { SDLK_F17, F17 }, + { SDLK_F18, F18 }, + { SDLK_F19, F19 }, + { SDLK_F20, F20 }, + { SDLK_F21, F21 }, + { SDLK_F22, F22 }, + { SDLK_F23, F23 }, + { SDLK_F24, F24 }, + + { SDLK_KP_0, KP0 }, + { SDLK_KP_1, KP1 }, + { SDLK_KP_2, KP2 }, + { SDLK_KP_3, KP3 }, + { SDLK_KP_4, KP4 }, + { SDLK_KP_5, KP5 }, + { SDLK_KP_6, KP6 }, + { SDLK_KP_7, KP7 }, + { SDLK_KP_8, KP8 }, + { SDLK_KP_9, KP9 }, + + { SDLK_KP_DECIMAL, KPDecimal }, + { SDLK_KP_DIVIDE, KPDivide }, + { SDLK_KP_MULTIPLY, KPMultiply }, + { SDLK_KP_MINUS, KPSubtract }, + { SDLK_KP_PLUS, KPAdd }, + { SDLK_KP_ENTER, KPEnter }, + { SDLK_KP_EQUALS, KPEqual }, + + { SDLK_LSHIFT, LeftShift }, + { SDLK_LCTRL, LeftControl }, + { SDLK_LALT, LeftAlt }, + { SDLK_LGUI, LeftSuper }, + + { SDLK_RSHIFT, RightShift }, + { SDLK_RCTRL, RightControl }, + { SDLK_RALT, RightAlt }, + { SDLK_RGUI, RightSuper }, + + { SDLK_MENU, Menu } +}; +Keycode getCustomKey(SDL_Keycode sdlKey) { + auto it = sdlToCustom.find(sdlKey); + if (it != sdlToCustom.end()) { + return it->second; + } + return 0; +} diff --git a/mwe/events/src/loopManager.cpp b/mwe/events/src/loopManager.cpp new file mode 100644 index 0000000..6defda0 --- /dev/null +++ b/mwe/events/src/loopManager.cpp @@ -0,0 +1,90 @@ +#include "loopManager.h" + +LoopManager::LoopManager() {} +void LoopManager::processInput() { + SDL_Event event; + SDL_PollEvent(&event); + switch (event.type) { + case SDL_QUIT: + gameRunning = false; + break; + case SDL_KEYDOWN: + triggerEvent(KeyPressedEvent(getCustomKey(event.key.keysym.sym))); + break; + case SDL_MOUSEBUTTONDOWN: + int x, y; + SDL_GetMouseState(&x, &y); + triggerEvent(MousePressedEvent(x, y)); + break; + } +} +void LoopManager::setRunning(bool running){ + this->gameRunning = running; +} +void LoopManager::fixedUpdate() { + //fprintf(stderr, "fixed update\n"); +} +void LoopManager::loop() { + LoopTimer & timer = LoopTimer::getInstance(); + timer.start(); + + while (gameRunning) { + timer.update(); + + while (timer.getLag() >= timer.getFixedDeltaTime()) { + processInput(); + fixedUpdate(); + timer.advanceFixedUpdate(); + } + + update(); + render(); + + timer.enforceFrameRate(); + } + + window.destroyWindow(); +} +void onKey(const KeyPressedEvent& e) +{ + int keyCode = e.getKeyCode(); + std::cout << "keycode pressed: " << keyCode << std::endl; + +} +void onMouse(const MousePressedEvent& e){ + fprintf(stderr, "mouse Position X: %d Y: %d\n", e.getMousePosition().first, e.getMousePosition().second); +} +void LoopManager::setup() { + gameRunning = window.initWindow(); + LoopTimer::getInstance().start(); + LoopTimer::getInstance().setFPS(50); + EventHandler<KeyPressedEvent> callback = onKey; + subscribe<KeyPressedEvent>(callback,false); + EventHandler<MousePressedEvent> mouseCallback = onMouse; + subscribe<MousePressedEvent>(mouseCallback ,false); + EventHandler<KeyPressedEvent> closeWindowCallback = [this](const KeyPressedEvent& e) { + if(e.getKeyCode() == Escape){ + this->setRunning(false); + } + }; + subscribe<KeyPressedEvent>(closeWindowCallback,false); + +} +void LoopManager::render() { + //fprintf(stderr, "**********render********** \n"); + if (gameRunning) { + //window.render(objectList); + } +} + +void LoopManager::update() { + //fprintf(stderr, "**********normal update********** \n"); + LoopTimer & timer = LoopTimer::getInstance(); + + float delta = timer.getDeltaTime(); + + // for (int i = 0; i < objectList.size(); i++) { + // objectList[i]->setX(objectList[i]->getX() + 50 * delta); + // objectList[i]->setY(objectList[i]->getY() + 50 * delta); + // } +} diff --git a/mwe/events/src/main.cpp b/mwe/events/src/main.cpp index 8d8567d..3940c60 100644 --- a/mwe/events/src/main.cpp +++ b/mwe/events/src/main.cpp @@ -1,14 +1,50 @@ #include <SDL2/SDL.h> -#include <stdio.h> +#include <iostream> +#include <memory> +#include "loopManager.h" #include "event.h" +class PlayerDamagedEvent : public Event { +public: + PlayerDamagedEvent(int damage, int playerID) + : Event("PlayerDamaged"), damage(damage), playerID(playerID) {} -int main(int argc, char * args[]) { - - KeyPressedEvent keyEvent(1,1); - KeyReleasedEvent keyRelease(1); - std::cout << keyEvent.GetEventType() << std::endl; - std::cout << keyRelease.GetEventType() << std::endl; - std::cin; - return 0; + REGISTER_EVENT_TYPE(PlayerDamagedEvent); + + int getDamage() const { return damage; } + int getPlayerID() const { return playerID; } + +private: + int damage; + int playerID; +}; +void onPlayerDamaged(const PlayerDamagedEvent& e) { + std::cout << "Player " << e.getPlayerID() << " took " << e.getDamage() << " damage." << std::endl; +} + +void onKeyPressed(const KeyPressedEvent& e) +{ + const int keyCode = e.getKeyCode(); + fprintf(stderr,"KeyCode %d\n",keyCode); +} +int main(int argc, char* args[]) { + LoopManager gameLoop; + // Create an event handler for KeyPressedEvent + // EventHandler<KeyPressedEvent> callback = [](const KeyPressedEvent& e) { + // onKeyPressed(e); + // }; + // custom event class poc + EventHandler<PlayerDamagedEvent> playerDamagedHandler = onPlayerDamaged; + subscribe<PlayerDamagedEvent>(playerDamagedHandler); + + triggerEvent(PlayerDamagedEvent(50, 1)); + //EventHandler<KeyPressedEvent> callback = onKeyPressed; + //subscribe<KeyPressedEvent>(callback,false); + std::unique_ptr<Event> anotherKeyPressEvent = std::make_unique<KeyPressedEvent>(65); + queueEvent(std::move(anotherKeyPressEvent)); + triggerEvent(KeyPressedEvent(42)); + EventManager::getInstance().dispatchEvents(); + gameLoop.setup(); + gameLoop.loop(); + return 0; } diff --git a/mwe/events/src/timer.cpp b/mwe/events/src/timer.cpp new file mode 100644 index 0000000..f4fee23 --- /dev/null +++ b/mwe/events/src/timer.cpp @@ -0,0 +1,54 @@ +#include "timer.h" + +LoopTimer::LoopTimer() {} +LoopTimer & LoopTimer::getInstance() { + static LoopTimer instance; + return instance; +} + +void LoopTimer::start() { + lastFrameTime = SDL_GetTicks64(); + elapsedTime = 0; + elapsedFixedTime = 0; + deltaTime = 0; +} + +// Update the timer, calculate deltaTime +void LoopTimer::update() { + uint64_t currentFrameTime = SDL_GetTicks64(); + deltaTime + = (currentFrameTime - lastFrameTime) / 1000.0; + + if (deltaTime > maximumDeltaTime) { + deltaTime = maximumDeltaTime; + } + + elapsedTime += deltaTime; + lastFrameTime = currentFrameTime; +} + +double LoopTimer::getDeltaTime() const { return deltaTime; } +int LoopTimer::getCurrentTime() const { return SDL_GetTicks(); } + +void LoopTimer::advanceFixedUpdate() { elapsedFixedTime += fixedDeltaTime; } + +double LoopTimer::getFixedDeltaTime() const { return fixedDeltaTime; } + +void LoopTimer::setFPS(int FPS) { + this->FPS = FPS; + frameTargetTime = 1.0 / FPS; +} + +int LoopTimer::getFPS() const { return FPS; } + +void LoopTimer::enforceFrameRate() { + uint64_t currentFrameTime = SDL_GetTicks64(); + double frameDuration = (currentFrameTime - lastFrameTime) / 1000.0; + + if (frameDuration < frameTargetTime) { + uint32_t delayTime + = (uint32_t) ((frameTargetTime - frameDuration) * 1000.0); + SDL_Delay(delayTime); + } +} +double LoopTimer::getLag() const { return elapsedTime - elapsedFixedTime; } diff --git a/mwe/events/src/window.cpp b/mwe/events/src/window.cpp index 61a4105..9cafd57 100644 --- a/mwe/events/src/window.cpp +++ b/mwe/events/src/window.cpp @@ -1,8 +1,5 @@ #include "window.h" WindowManager::WindowManager() { - if (!initWindow()) { - printf("Failed to initialize!\n"); - } } WindowManager::~WindowManager() { destroyWindow(); } SDL_Renderer * WindowManager::getRenderer() { return renderer; } diff --git a/mwe/gameloop/include/loopManager.h b/mwe/gameloop/include/loopManager.h index e202423..dcbfedc 100644 --- a/mwe/gameloop/include/loopManager.h +++ b/mwe/gameloop/include/loopManager.h @@ -2,6 +2,7 @@ #include "gameObject.h" #include "window.h" #include <SDL2/SDL.h> +#include "event.h" class LoopManager { public: LoopManager(); |