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(); +} |