diff options
Diffstat (limited to 'mwe/events/src')
-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 | 109 | ||||
-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 | 50 | ||||
-rw-r--r-- | mwe/events/src/timer.cpp | 54 | ||||
-rw-r--r-- | mwe/events/src/window.cpp | 30 |
8 files changed, 534 insertions, 0 deletions
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(); +} |