aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/crepe/api/Button.cpp0
-rw-r--r--src/crepe/api/Button.h17
-rw-r--r--src/crepe/api/Event.h10
-rw-r--r--src/crepe/api/LoopManager.cpp4
-rw-r--r--src/crepe/api/UiObject.h14
-rw-r--r--src/crepe/facade/SDLContext.cpp80
-rw-r--r--src/crepe/facade/SDLContext.h40
-rw-r--r--src/crepe/system/InputSystem.cpp107
-rw-r--r--src/crepe/system/InputSystem.h23
-rw-r--r--src/example/gameloop.cpp33
-rw-r--r--src/test/inputTest.cpp53
-rw-r--r--src/test/loopTimerTest.cpp32
12 files changed, 404 insertions, 9 deletions
diff --git a/src/crepe/api/Button.cpp b/src/crepe/api/Button.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/crepe/api/Button.cpp
diff --git a/src/crepe/api/Button.h b/src/crepe/api/Button.h
new file mode 100644
index 0000000..5035729
--- /dev/null
+++ b/src/crepe/api/Button.h
@@ -0,0 +1,17 @@
+#include <functional>
+
+#include "Component.h"
+#include "api/EventHandler.h"
+#include "api/UiObject.h"
+namespace crepe {
+class Button : public UiObject{
+public:
+ ~Button(){};
+ bool interactable = true;
+ bool is_toggle = false;
+ bool is_pressed = false;
+ std::function<void()> on_click;
+public:
+virtual int get_instances_max() const { return 1; }
+};
+}
diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h
index b267e3e..bac8701 100644
--- a/src/crepe/api/Event.h
+++ b/src/crepe/api/Event.h
@@ -88,6 +88,10 @@ public:
//! Y-coordinate of the mouse position at the time of the event.
int mouse_y = 0;
+ // Relative movement in x
+ int rel_x;
+ // Relative movement in y
+ int rel_y;
};
/**
@@ -107,6 +111,8 @@ public:
/**
* \brief Event triggered to indicate the application is shutting down.
*/
-class ShutDownEvent : public Event {};
+class ShutDownEvent : public Event {
+public:
+};
-} // namespace crepe
+}
diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp
index 7edf4d1..9599943 100644
--- a/src/crepe/api/LoopManager.cpp
+++ b/src/crepe/api/LoopManager.cpp
@@ -6,6 +6,7 @@
#include "../system/PhysicsSystem.h"
#include "../system/RenderSystem.h"
#include "../system/ScriptSystem.h"
+#include "../system/InputSystem.h"
#include "LoopManager.h"
#include "LoopTimer.h"
@@ -20,10 +21,11 @@ LoopManager::LoopManager() {
this->load_system<PhysicsSystem>();
this->load_system<RenderSystem>();
this->load_system<ScriptSystem>();
+ this->load_system<InputSystem>();
}
void LoopManager::process_input() {
- SDLContext::get_instance().handle_events(this->game_running);
+ this->get_system<InputSystem>().update();
}
void LoopManager::start() {
diff --git a/src/crepe/api/UiObject.h b/src/crepe/api/UiObject.h
new file mode 100644
index 0000000..f57f7ef
--- /dev/null
+++ b/src/crepe/api/UiObject.h
@@ -0,0 +1,14 @@
+#include <functional>
+
+#include "Component.h"
+#include "api/EventHandler.h"
+namespace crepe {
+class UiObject : public Component{
+public:
+ ~UiObject(){};
+ int width = 0;
+ int height = 0;
+public:
+virtual int get_instances_max() const { return 1; }
+};
+}
diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp
index b3298a7..ff7c9f0 100644
--- a/src/crepe/facade/SDLContext.cpp
+++ b/src/crepe/facade/SDLContext.cpp
@@ -11,14 +11,15 @@
#include <memory>
#include <stdexcept>
#include <string>
+#include <array>
#include "../api/Camera.h"
#include "../api/Sprite.h"
#include "../api/Texture.h"
#include "../api/Transform.h"
-#include "../api/Vector2.h"
#include "../util/Log.h"
+
#include "SDLContext.h"
using namespace crepe;
@@ -72,6 +73,7 @@ SDLContext::~SDLContext() {
IMG_Quit();
SDL_Quit();
}
+
void SDLContext::handle_events(bool & running) {
//TODO: wouter i need events
/*
@@ -192,3 +194,79 @@ int SDLContext::get_height(const Texture & ctx) const {
return h;
}
void SDLContext::delay(int ms) const { SDL_Delay(ms); }
+
+std::vector<SDLContext::EventData> SDLContext::get_events(){
+ std::vector<SDLContext::EventData> event_list;
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ switch (event.type) {
+ case SDL_QUIT:
+ event_list.push_back(EventData{
+ .event_type = SDLContext::Event::SHUTDOWN,
+ });
+ break;
+ case SDL_KEYDOWN:
+ event_list.push_back(EventData{
+ .event_type = SDLContext::Event::KEYDOWN,
+ .key = sdl_to_keycode(event.key.keysym.scancode),
+ .key_repeat = (event.key.repeat != 0),
+ });
+ break;
+ case SDL_KEYUP:
+ event_list.push_back(EventData{
+ .event_type = SDLContext::Event::KEYUP,
+ .key = sdl_to_keycode(event.key.keysym.scancode),
+ });
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ {
+ int x,y;
+ SDL_GetMouseState(&x, &y);
+ event_list.push_back(EventData{
+ .event_type = SDLContext::Event::MOUSEDOWN,
+ .mouse_button = sdl_to_mousebutton(event.button.button),
+ .mouse_position = {x,y},
+ });
+ }
+ break;
+ case SDL_MOUSEBUTTONUP:
+ {
+ int x,y;
+ SDL_GetMouseState(&x, &y);
+ event_list.push_back(EventData{
+ .event_type = SDLContext::Event::MOUSEUP,
+ .mouse_button = sdl_to_mousebutton(event.button.button),
+ .mouse_position = {x,y},
+ });
+ }
+ break;
+
+ case SDL_MOUSEMOTION:
+ {
+ int x,y;
+ SDL_GetMouseState(&x, &y);
+ event_list.push_back(EventData{
+ .event_type = SDLContext::Event::MOUSEMOVE,
+ .mouse_position = {x,y},
+ });
+ }
+ break;
+
+ case SDL_MOUSEWHEEL:
+ {
+ int x, y;
+ SDL_GetMouseState(&x, &y);
+
+ event_list.push_back(EventData{
+ .event_type = SDLContext::Event::MOUSEWHEEL,
+ .mouse_position = {event.motion.x,event.motion.y},
+ .wheel_delta = event.wheel.y,
+ .rel_mouse_move {event.motion.yrel,event.motion.xrel},
+ });
+ }
+ break;
+ }
+ }
+ return event_list;
+}
+
diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h
index 20e30b3..5b6b093 100644
--- a/src/crepe/facade/SDLContext.h
+++ b/src/crepe/facade/SDLContext.h
@@ -1,5 +1,5 @@
#pragma once
-
+#include <SDL2/SDL.h>
#include <SDL2/SDL_keycode.h>
#include <SDL2/SDL_rect.h>
#include <SDL2/SDL_render.h>
@@ -10,7 +10,10 @@
#include <string>
#include "../api/Sprite.h"
+#include "../api/KeyCodes.h"
#include "../api/Transform.h"
+#include "../api/Vector2.h"
+#include "../api/Event.h"
#include "api/Camera.h"
#include "types.h"
@@ -19,8 +22,9 @@ namespace crepe {
// TODO: SDL_Keycode is defined in a header not distributed with crepe, which means this
// typedef is unusable when crepe is packaged. Wouter will fix this later.
-typedef SDL_Keycode CREPE_KEYCODES;
-
+//typedef SDL_Keycode CREPE_KEYCODES;
+class LoopManager;
+class InputSystem;
/**
* \class SDLContext
* \brief Facade for the SDL library
@@ -31,6 +35,26 @@ typedef SDL_Keycode CREPE_KEYCODES;
class SDLContext {
public:
+ enum Event{
+ NONE = 0,
+ MOUSEDOWN,
+ MOUSEUP,
+ MOUSEMOVE,
+ MOUSEWHEEL,
+ KEYUP,
+ KEYDOWN,
+ SHUTDOWN
+
+ };
+ struct EventData {
+ SDLContext::Event event_type = SDLContext::Event::NONE;
+ Keycode key = Keycode::NONE;
+ bool key_repeat = false;
+ MouseButton mouse_button = MouseButton::NONE;
+ std::pair<int,int> mouse_position = {-1,-1};
+ int wheel_delta = -1;
+ std::pair<int,int> rel_mouse_move = {-1,-1};
+ };
/**
* \brief Gets the singleton instance of SDLContext.
* \return Reference to the SDLContext instance.
@@ -44,13 +68,18 @@ public:
private:
//! will only use handle_events
- friend class LoopManager;
+ friend class InputSystem;
/**
* \brief Handles SDL events such as window close and input.
* \param running Reference to a boolean flag that controls the main loop.
*/
void handle_events(bool & running);
-
+ std::vector<SDLContext::EventData> get_events();
+
+ Keycode get_key();
+ Keycode get_mouse();
+ Keycode sdl_to_keycode(SDL_Keycode sdlKey);
+ MouseButton sdl_to_mousebutton(Uint8 sdl_button);
private:
//! Will only use get_ticks
friend class AnimatorSystem;
@@ -168,4 +197,5 @@ private:
SDL_Rect viewport = {0, 0, 640, 480};
};
+
} // namespace crepe
diff --git a/src/crepe/system/InputSystem.cpp b/src/crepe/system/InputSystem.cpp
new file mode 100644
index 0000000..c61a80f
--- /dev/null
+++ b/src/crepe/system/InputSystem.cpp
@@ -0,0 +1,107 @@
+#include "ComponentManager.h"
+#include "../api/Button.h"
+#include "../api/EventManager.h"
+#include "../api/Transform.h"
+#include "../facade/SDLContext.h"
+#include "../api/Event.h"
+
+#include "system/InputSystem.h"
+
+using namespace crepe;
+
+
+
+void InputSystem::update() {
+ EventManager& event_mgr = EventManager::get_instance();
+ std::vector<SDLContext::EventData> event_list = SDLContext::get_instance().get_events();
+
+ for (SDLContext::EventData event : event_list) {
+ switch (event.event_type) {
+ case SDLContext::Event::KEYDOWN: {
+ event_mgr.queue_event(KeyPressEvent{
+ .key = event.key,
+ .repeat = event.key_repeat,
+ });
+ break;
+ }
+ case SDLContext::Event::KEYUP: {
+ event_mgr.queue_event(KeyReleaseEvent{
+ .key = event.key,
+ });
+ break;
+ }
+ case SDLContext::Event::MOUSEDOWN: {
+ event_mgr.queue_event(MousePressEvent{
+ .mouse_x = event.mouse_position.first,
+ .mouse_y = event.mouse_position.second,
+ .button = event.mouse_button,
+ });
+ break;
+ }
+ case SDLContext::Event::MOUSEMOVE: {
+ event_mgr.queue_event(MouseMoveEvent{
+ .mouse_x = event.mouse_position.first,
+ .mouse_y = event.mouse_position.second,
+ .rel_x = event.rel_mouse_move.first,
+ .rel_y = event.rel_mouse_move.second,
+ });
+ break;
+ }
+ case SDLContext::Event::MOUSEUP: {
+ event_mgr.queue_event(MouseReleaseEvent{
+ .mouse_x = event.mouse_position.first,
+ .mouse_y = event.mouse_position.second,
+ .button = event.mouse_button,
+ });
+ int delta_x = event.mouse_position.first - last_mouse_down_position.first;
+ int delta_y = event.mouse_position.second - last_mouse_down_position.second;
+ if (last_mouse_button == event.mouse_button &&
+ std::abs(delta_x) <= click_tolerance &&
+ std::abs(delta_y) <= click_tolerance) {
+ event_mgr.queue_event(MouseClickEvent{
+ .mouse_x = event.mouse_position.first,
+ .mouse_y = event.mouse_position.second,
+ .button = event.mouse_button,
+ });
+ }
+ break;
+ }
+ case SDLContext::Event::MOUSEWHEEL: {
+ event_mgr.queue_event(MouseScrollEvent{
+ .scroll_x = event.mouse_position.first,
+ .scroll_y = event.mouse_position.second,
+ .direction = event.wheel_delta,
+ });
+ break;
+ }
+ case SDLContext::Event::SHUTDOWN: {
+ event_mgr.queue_event(ShutDownEvent{});
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+bool InputSystem::handle_click(const MouseClickEvent &event) {
+ ComponentManager &mgr = this->component_manager;
+
+ std::vector<std::reference_wrapper<Button>> buttons =
+ mgr.get_components_by_type<Button>();
+
+ std::vector<std::reference_wrapper<Transform>> transforms =
+ mgr.get_components_by_type<Transform>();
+ for (Button &button : buttons) {
+ for(Transform& transform : transforms){
+ if(button.game_object_id != transform.game_object_id){continue;}
+ if (!button.interactable) {break;}
+ if (event.mouse_x >= transform.position.x && event.mouse_x <= transform.position.x + button.width &&
+ event.mouse_y >= transform.position.y && event.mouse_y <= transform.position.y + button.height) {
+ button.on_click();
+ }
+ }
+ }
+ return false;
+}
+
diff --git a/src/crepe/system/InputSystem.h b/src/crepe/system/InputSystem.h
new file mode 100644
index 0000000..231aa45
--- /dev/null
+++ b/src/crepe/system/InputSystem.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "System.h"
+#include "../api/Event.h"
+namespace crepe {
+
+class InputSystem : public System {
+public:
+ using System::System;
+ void update() override;
+ void process_events();
+
+private:
+ std::pair<int, int> last_mouse_down_position{-1, -1};
+ MouseButton last_mouse_button = MouseButton::NONE;
+ const int click_tolerance = 5;
+ bool handle_click(const MouseClickEvent &event);
+ bool handle_move(const MouseMoveEvent &event);
+ bool handle_key_press(const KeyPressEvent &event);
+ bool handle_key_release(const KeyReleaseEvent &event);
+};
+
+} // namespace crepe
diff --git a/src/example/gameloop.cpp b/src/example/gameloop.cpp
index a676f20..d45b3ce 100644
--- a/src/example/gameloop.cpp
+++ b/src/example/gameloop.cpp
@@ -1,7 +1,40 @@
+#include <iostream>
#include "crepe/api/LoopManager.h"
+#include <crepe/api/EventManager.h>
+#include <crepe/api/GameObject.h>
+#include <crepe/api/IKeyListener.h>
+#include <crepe/api/IMouseListener.h>
using namespace crepe;
+class TestKeyListener : public IKeyListener {
+public:
+ bool on_key_pressed(const KeyPressEvent & event) override {
+ std::cout << "TestKeyListener: Key Pressed - Code: " << static_cast<int>(event.key)
+ << std::endl;
+ if(event.key == Keycode::ESCAPE){
+
+ }
+ return false;
+ }
+ bool on_key_released(const KeyReleaseEvent & event) override {
+ std::cout << "TestKeyListener: Key Released - Code: " << static_cast<int>(event.key)
+ << std::endl;
+ return false;
+ }
+};
+bool on_key_pressed(const KeyPressEvent & event){
+ std::cout << "TestKeyListener: Key Pressed - Code: " << static_cast<int>(event.key)
+ << std::endl;
+ if(event.key == Keycode::ESCAPE){
+ return true;
+ }
+ return false;
+ }
int main() {
LoopManager gameloop;
+ TestKeyListener key_listener;
+ EventManager::get_instance().subscribe<KeyPressEvent>(on_key_pressed);
gameloop.start();
+
+
return 1;
}
diff --git a/src/test/inputTest.cpp b/src/test/inputTest.cpp
new file mode 100644
index 0000000..0f02410
--- /dev/null
+++ b/src/test/inputTest.cpp
@@ -0,0 +1,53 @@
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_keycode.h>
+#include "system/InputSystem.h"
+#include "api/EventManager.h"
+#include "api/KeyCodes.h"
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace std::chrono_literals;
+using namespace crepe;
+
+class InputTest : public ::testing::Test {
+public:
+InputSystem input_system;
+EventManager& event_manager = EventManager::get_instance();
+protected:
+ void SetUp() override {
+ }
+
+ void TearDown() override {
+
+ }
+void simulate_mouse_click(int mouse_x, int mouse_y, Uint8 mouse_button) {
+ SDL_Event event;
+
+ // Simulate Mouse Button Down event
+ SDL_zero(event);
+ event.type = SDL_MOUSEBUTTONDOWN;
+ event.button.x = mouse_x;
+ event.button.y = mouse_y;
+ event.button.button = mouse_button;
+ SDL_PushEvent(&event);
+ SDL_zero(event);
+ event.type = SDL_MOUSEBUTTONUP;
+ event.button.x = mouse_x;
+ event.button.y = mouse_y;
+ event.button.button = mouse_button;
+ SDL_PushEvent(&event);
+}
+
+};
+
+TEST_F(InputTest, KeyDown) {
+
+ SDL_Event event;
+ SDL_zero(event);
+ event.type = SDL_MOUSEBUTTONDOWN;
+ event.button.x = 10;
+ event.button.y = 10;
+ event.button.button = mouse_bu;
+ SDL_PushEvent(&event); // Push event into the SDL event queue
+}
diff --git a/src/test/loopTimerTest.cpp b/src/test/loopTimerTest.cpp
new file mode 100644
index 0000000..a3b1646
--- /dev/null
+++ b/src/test/loopTimerTest.cpp
@@ -0,0 +1,32 @@
+#define private public
+#define protected public
+#include "api/LoopManager.h"
+#include "api/LoopTimer.h"
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace std::chrono_literals;
+using namespace crepe;
+
+class LoopTimerTest : public ::testing::Test {
+public:
+LoopTimer loop_timer = LoopTimer::get_instance();
+protected:
+ void SetUp() override {
+ loop_timer.start();
+ }
+
+ void TearDown() override {
+
+ }
+};
+TEST_F(LoopTimerTest, TestDeltaTime) {
+ auto start_time = std::chrono::steady_clock::now();
+
+ loop_timer.update();
+ double delta_time = loop_timer.get_delta_time();
+
+ auto elapsed_time = std::chrono::steady_clock::now() - start_time;
+ EXPECT_LE(delta_time, std::chrono::duration<double>(elapsed_time).count());
+}