aboutsummaryrefslogtreecommitdiff
path: root/mwe
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-10-24 10:53:02 +0200
committerLoek Le Blansch <loek@pipeframe.xyz>2024-10-24 10:53:02 +0200
commita8a7ff90dfd626ea76dd9e9fe00c7854a7b9f31f (patch)
tree2724ddce9d181770e7ca745900af76ed64194451 /mwe
parent39054829fa69bcfa2b468015dc3852a2f8deac9f (diff)
parentb5e83d076f356c6d01b7bbc1f033db4850356c0d (diff)
Merge branch 'wouter/events-poc' of github.com:lonkaars/crepe
Diffstat (limited to 'mwe')
-rw-r--r--mwe/.vscode/settings.json11
-rw-r--r--mwe/events/.vscode/c_cpp_properties.json15
-rw-r--r--mwe/events/.vscode/settings.json68
-rw-r--r--mwe/events/CMakeLists.txt31
-rw-r--r--mwe/events/imgs/demo.bmpbin0 -> 7998698 bytes
-rw-r--r--mwe/events/imgs/demo.jpgbin0 -> 903706 bytes
-rw-r--r--mwe/events/include/event.h87
-rw-r--r--mwe/events/include/eventHandler.h48
-rw-r--r--mwe/events/include/eventManager.h57
-rw-r--r--mwe/events/include/keyCodes.h143
-rw-r--r--mwe/events/include/loopManager.h28
-rw-r--r--mwe/events/include/timer.h31
-rw-r--r--mwe/events/include/window.h19
-rw-r--r--mwe/events/src/event.cpp56
-rw-r--r--mwe/events/src/eventHandler.cpp5
-rw-r--r--mwe/events/src/eventManager.cpp109
-rw-r--r--mwe/events/src/keyCodes.cpp140
-rw-r--r--mwe/events/src/loopManager.cpp90
-rw-r--r--mwe/events/src/main.cpp50
-rw-r--r--mwe/events/src/timer.cpp54
-rw-r--r--mwe/events/src/window.cpp30
-rw-r--r--mwe/events/versions/delayBased.cpp56
-rw-r--r--mwe/gameloop/include/eventManager.h6
-rw-r--r--mwe/gameloop/include/loopManager.h1
24 files changed, 1134 insertions, 1 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
new file mode 100644
index 0000000..816d790
--- /dev/null
+++ b/mwe/events/.vscode/settings.json
@@ -0,0 +1,68 @@
+{
+ "files.associations": {
+ "iostream": "cpp",
+ "array": "cpp",
+ "atomic": "cpp",
+ "bit": "cpp",
+ "*.tcc": "cpp",
+ "cctype": "cpp",
+ "clocale": "cpp",
+ "cmath": "cpp",
+ "compare": "cpp",
+ "concepts": "cpp",
+ "cstdarg": "cpp",
+ "cstddef": "cpp",
+ "cstdint": "cpp",
+ "cstdio": "cpp",
+ "cstdlib": "cpp",
+ "cwchar": "cpp",
+ "cwctype": "cpp",
+ "deque": "cpp",
+ "list": "cpp",
+ "map": "cpp",
+ "string": "cpp",
+ "unordered_map": "cpp",
+ "vector": "cpp",
+ "exception": "cpp",
+ "algorithm": "cpp",
+ "functional": "cpp",
+ "iterator": "cpp",
+ "memory": "cpp",
+ "memory_resource": "cpp",
+ "numeric": "cpp",
+ "optional": "cpp",
+ "random": "cpp",
+ "string_view": "cpp",
+ "system_error": "cpp",
+ "tuple": "cpp",
+ "type_traits": "cpp",
+ "utility": "cpp",
+ "initializer_list": "cpp",
+ "iosfwd": "cpp",
+ "istream": "cpp",
+ "limits": "cpp",
+ "new": "cpp",
+ "numbers": "cpp",
+ "ostream": "cpp",
+ "sstream": "cpp",
+ "stdexcept": "cpp",
+ "streambuf": "cpp",
+ "cinttypes": "cpp",
+ "typeinfo": "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
new file mode 100644
index 0000000..585d869
--- /dev/null
+++ b/mwe/events/CMakeLists.txt
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION 3.5)
+project(gameloop)
+
+# Set the C++ standard (optional, but good practice)
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
+set(CMAKE_BUILD_TYPE Debug)
+
+# Find the SDL2 package
+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
+target_link_libraries(gameloop ${SDL2_LIBRARIES})
+
+# Include SDL2 header files and project headers
+target_include_directories(gameloop PRIVATE ${SDL2_INCLUDE_DIRS})
+target_include_directories(gameloop PRIVATE ${CMAKE_SOURCE_DIR}/include)
+
diff --git a/mwe/events/imgs/demo.bmp b/mwe/events/imgs/demo.bmp
new file mode 100644
index 0000000..65354fe
--- /dev/null
+++ b/mwe/events/imgs/demo.bmp
Binary files differ
diff --git a/mwe/events/imgs/demo.jpg b/mwe/events/imgs/demo.jpg
new file mode 100644
index 0000000..f534e1b
--- /dev/null
+++ b/mwe/events/imgs/demo.jpg
Binary files differ
diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h
new file mode 100644
index 0000000..802140c
--- /dev/null
+++ b/mwe/events/include/event.h
@@ -0,0 +1,87 @@
+#pragma once
+#include <cstdint>
+#include <iostream>
+#include <string>
+#include <unordered_map>
+#include <variant>
+#include "keyCodes.h"
+
+class UUIDGenerator {
+public:
+ static std::uint32_t getUniqueID() {
+ static std::uint32_t id = 0;
+ return ++id;
+ }
+};
+#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);
+ 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:
+ 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:
+ KeyReleasedEvent(int keyCode);
+
+ REGISTER_EVENT_TYPE(KeyReleasedEvent);
+
+ Keycode getKeyCode() const;
+
+private:
+ Keycode key = 0;
+};
+
+// MousePressedEvent class
+class MousePressedEvent : public Event {
+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
new file mode 100644
index 0000000..e5b99d6
--- /dev/null
+++ b/mwe/events/include/eventHandler.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include "event.h"
+
+#include <functional>
+#include <iostream>
+template<typename EventType>
+using EventHandler = std::function<void(const EventType& e)>;
+
+class IEventHandlerWrapper {
+public:
+ virtual ~IEventHandlerWrapper() = default;
+
+ void exec(const Event& e);
+
+ virtual std::string getType() const = 0;
+ virtual bool isDestroyOnSuccess() const = 0;
+
+private:
+ virtual void call(const Event& e) = 0;
+};
+
+template<typename EventType>
+class EventHandlerWrapper : public IEventHandlerWrapper {
+public:
+ explicit EventHandlerWrapper(const EventHandler<EventType>& handler, const bool destroyOnSuccess = false)
+ : m_handler(handler)
+ , m_handlerType(m_handler.target_type().name())
+ , m_destroyOnSuccess(destroyOnSuccess)
+ {
+ // std::cout << m_handlerType << std::endl;
+ }
+
+private:
+ void call(const Event& e) override
+ {
+ if (e.getEventType() == EventType::getStaticEventType()) {
+ m_handler(static_cast<const EventType&>(e));
+ }
+ }
+
+ 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
new file mode 100644
index 0000000..709796a
--- /dev/null
+++ b/mwe/events/include/eventManager.h
@@ -0,0 +1,57 @@
+#pragma once
+#include <unordered_map>
+#include <memory>
+#include "event.h"
+#include "keyCodes.h"
+#include "eventHandler.h"
+#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/include/window.h b/mwe/events/include/window.h
new file mode 100644
index 0000000..9020b1a
--- /dev/null
+++ b/mwe/events/include/window.h
@@ -0,0 +1,19 @@
+#pragma once
+#include <SDL2/SDL.h>
+#include <iostream>
+#include <vector>
+class WindowManager {
+public:
+ WindowManager();
+ virtual ~WindowManager();
+ bool initWindow();
+ void destroyWindow();
+
+ SDL_Renderer * getRenderer();
+
+private:
+ const int SCREEN_WIDTH = 800;
+ const int SCREEN_HEIGHT = 600;
+ SDL_Window * window = NULL;
+ SDL_Renderer * renderer = NULL;
+};
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
new file mode 100644
index 0000000..ce8e940
--- /dev/null
+++ b/mwe/events/src/eventManager.cpp
@@ -0,0 +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
new file mode 100644
index 0000000..3940c60
--- /dev/null
+++ b/mwe/events/src/main.cpp
@@ -0,0 +1,50 @@
+#include <SDL2/SDL.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) {}
+
+ 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
new file mode 100644
index 0000000..9cafd57
--- /dev/null
+++ b/mwe/events/src/window.cpp
@@ -0,0 +1,30 @@
+#include "window.h"
+WindowManager::WindowManager() {
+}
+WindowManager::~WindowManager() { destroyWindow(); }
+SDL_Renderer * WindowManager::getRenderer() { return renderer; }
+
+bool WindowManager::initWindow() {
+ if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
+ fprintf(stderr, "Error inititalising SDL.\n");
+ return false;
+ }
+ window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH,
+ SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
+ if (!window) {
+ fprintf(stderr, "Error creating SDL Window. \n");
+ return false;
+ }
+ renderer = SDL_CreateRenderer(window, -1, 0);
+ if (!renderer) {
+ fprintf(stderr, "Error creating SDL renderer. \n");
+ return false;
+ }
+ return true;
+}
+void WindowManager::destroyWindow() {
+ SDL_DestroyRenderer(renderer);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+}
diff --git a/mwe/events/versions/delayBased.cpp b/mwe/events/versions/delayBased.cpp
new file mode 100644
index 0000000..253a03a
--- /dev/null
+++ b/mwe/events/versions/delayBased.cpp
@@ -0,0 +1,56 @@
+#include "loopManager.h"
+#include "timer.h"
+LoopManager::LoopManager() {}
+void LoopManager::processInput() {
+ SDL_Event event;
+ SDL_PollEvent(&event);
+ switch (event.type) {
+ case SDL_QUIT:
+ gameRunning = false;
+ break;
+ case SDL_KEYDOWN:
+ if (event.key.keysym.sym == SDLK_ESCAPE) {
+ gameRunning = false;
+ }
+ break;
+ }
+}
+void LoopManager::loop() {
+ fprintf(stderr, "loop. \n");
+ while (gameRunning) {
+ //Timer::getInstance().update();
+ //deltaTime = Timer::getInstance().getDeltaTime();
+ processInput();
+ update();
+ render();
+ }
+ window.destroyWindow();
+}
+void LoopManager::setup() {
+ gameRunning = window.initWindow();
+ LoopTimer::getInstance().start();
+ LoopTimer::getInstance().setFPS(210);
+
+ for (int i = 0; i < 2; i++) {
+ GameObject * square2
+ = new GameObject("square2", i * 40, i * 40, 20, 20, 0, 0);
+ objectList.push_back(square2);
+ }
+}
+void LoopManager::render() {
+ if (gameRunning) {
+ window.render(objectList);
+ }
+}
+
+void LoopManager::update() {
+ LoopTimer & timer = LoopTimer::getInstance();
+ timer.enforceFrameRate();
+ timer.update();
+ 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/gameloop/include/eventManager.h b/mwe/gameloop/include/eventManager.h
index 69c6801..ba1ca32 100644
--- a/mwe/gameloop/include/eventManager.h
+++ b/mwe/gameloop/include/eventManager.h
@@ -1 +1,5 @@
-class EventManager {};
+#pragma once
+class EventManager {
+ public:
+ EventManager();
+};
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();