From 55ff0c7905e76b375deaf67d8cd38b5c3b3106f4 Mon Sep 17 00:00:00 2001 From: loic <910041@gmail.com> Date: Thu, 28 Nov 2024 23:30:43 +0800 Subject: [PATCH] chore: refactor input system --- AtmosphericEngine/input.cpp | 27 +++++++- AtmosphericEngine/input.hpp | 69 +++----------------- AtmosphericEngine/window.cpp | 122 ++++++++++++++++++++++++++++++++--- AtmosphericEngine/window.hpp | 61 ++++++++++++++---- Example_HelloWorld/main.cpp | 4 +- Example_MazeWorld/main.cpp | 34 +++++----- 6 files changed, 216 insertions(+), 101 deletions(-) diff --git a/AtmosphericEngine/input.cpp b/AtmosphericEngine/input.cpp index 51de0ed..e36c45b 100644 --- a/AtmosphericEngine/input.cpp +++ b/AtmosphericEngine/input.cpp @@ -9,6 +9,11 @@ Input::Input() throw std::runtime_error("Input is already initialized!"); _instance = this; + + for (int k = static_cast(Key::SPACE); k <= static_cast(Key::ESCAPE); ++k) { + auto key = static_cast(k); + _keyStates[key] = KeyState::UNKNOWN; + } } Input::~Input() @@ -16,16 +21,34 @@ Input::~Input() } -bool Input::GetKeyDown(int key) +void Input::Process(float dt) +{ + for (int k = static_cast(Key::SPACE); k <= static_cast(Key::ESCAPE); ++k) { + auto key = static_cast(k); + _keyStates[key] = Window::Get()->GetKeyState(key); + } +} + +bool Input::GetKeyDown(Key key) { return Window::Get()->GetKeyDown(key); } -bool Input::GetKeyUp(int key) +bool Input::GetKeyUp(Key key) { return Window::Get()->GetKeyUp(key); } +bool Input::IsKeyDown(Key key) +{ + return _keyStates[key] == KeyState::PRESSED; +} + +bool Input::IsKeyUp(Key key) +{ + return _keyStates[key] == KeyState::RELEASED; +} + glm::vec2 Input::GetMousePosition() // In pixel coordinate { return Window::Get()->GetMousePosition(); diff --git a/AtmosphericEngine/input.hpp b/AtmosphericEngine/input.hpp index 64b76a2..11a43ce 100644 --- a/AtmosphericEngine/input.hpp +++ b/AtmosphericEngine/input.hpp @@ -1,41 +1,7 @@ #pragma once #include "globals.hpp" #include "server.hpp" -#include "GLFW/glfw3.h" - -const int KEY_UP = GLFW_KEY_UP; -const int KEY_RIGHT = GLFW_KEY_RIGHT; -const int KEY_LEFT = GLFW_KEY_LEFT; -const int KEY_DOWN = GLFW_KEY_DOWN; -const int KEY_Q = GLFW_KEY_Q; -const int KEY_W = GLFW_KEY_W; -const int KEY_E = GLFW_KEY_E; -const int KEY_R = GLFW_KEY_R; -const int KEY_T = GLFW_KEY_T; -const int KEY_Y = GLFW_KEY_Y; -const int KEY_U = GLFW_KEY_U; -const int KEY_I = GLFW_KEY_I; -const int KEY_O = GLFW_KEY_O; -const int KEY_P = GLFW_KEY_P; -const int KEY_A = GLFW_KEY_A; -const int KEY_S = GLFW_KEY_S; -const int KEY_D = GLFW_KEY_D; -const int KEY_F = GLFW_KEY_F; -const int KEY_G = GLFW_KEY_G; -const int KEY_H = GLFW_KEY_H; -const int KEY_J = GLFW_KEY_J; -const int KEY_K = GLFW_KEY_K; -const int KEY_L = GLFW_KEY_L; -const int KEY_Z = GLFW_KEY_Z; -const int KEY_X = GLFW_KEY_X; -const int KEY_C = GLFW_KEY_C; -const int KEY_V = GLFW_KEY_V; -const int KEY_B = GLFW_KEY_B; -const int KEY_N = GLFW_KEY_N; -const int KEY_M = GLFW_KEY_M; -const int KEY_ESCAPE = GLFW_KEY_ESCAPE; -const int KEY_ENTER = GLFW_KEY_ENTER; -const int KEY_SPACE = GLFW_KEY_SPACE; +#include "window.hpp" class Input : public Server { @@ -52,33 +18,18 @@ class Input : public Server ~Input(); - bool GetKeyDown(int key); + void Process(float dt) override; + + bool GetKeyDown(Key key); + + bool GetKeyUp(Key key); - bool GetKeyUp(int key); + bool IsKeyDown(Key key); + + bool IsKeyUp(Key key); glm::vec2 GetMousePosition(); private: - std::vector keys - { - KEY_UP, - KEY_RIGHT, - KEY_LEFT, - KEY_DOWN, - KEY_Q, - KEY_W, - KEY_E, - KEY_R, - KEY_A, - KEY_S, - KEY_D, - KEY_F, - KEY_Z, - KEY_X, - KEY_C, - KEY_V, - KEY_ESCAPE, - KEY_ENTER, - KEY_SPACE - }; + std::unordered_map _keyStates; }; \ No newline at end of file diff --git a/AtmosphericEngine/window.cpp b/AtmosphericEngine/window.cpp index 5b9c949..1897af0 100644 --- a/AtmosphericEngine/window.cpp +++ b/AtmosphericEngine/window.cpp @@ -259,16 +259,118 @@ glm::vec2 Window::GetMousePosition() return glm::vec2((float)x, (float)y); } -bool Window::GetKeyDown(int key) -{ - bool isDown = (glfwGetKey(static_cast(_internal), key) == GLFW_PRESS); - return isDown; -} - -bool Window::GetKeyUp(int key) -{ - bool isUp = (glfwGetKey(static_cast(_internal), key) == GLFW_RELEASE); - return isUp; +int convertToGlfwKey(Key key) +{ + switch (key) { + case Key::UP: + return GLFW_KEY_UP; + case Key::RIGHT: + return GLFW_KEY_RIGHT; + case Key::LEFT: + return GLFW_KEY_LEFT; + case Key::DOWN: + return GLFW_KEY_DOWN; + case Key::Q: + return GLFW_KEY_Q; + case Key::W: + return GLFW_KEY_W; + case Key::E: + return GLFW_KEY_E; + case Key::R: + return GLFW_KEY_R; + case Key::T: + return GLFW_KEY_T; + case Key::Y: + return GLFW_KEY_Y; + case Key::U: + return GLFW_KEY_U; + case Key::I: + return GLFW_KEY_I; + case Key::O: + return GLFW_KEY_O; + case Key::P: + return GLFW_KEY_P; + case Key::A: + return GLFW_KEY_A; + case Key::S: + return GLFW_KEY_S; + case Key::D: + return GLFW_KEY_D; + case Key::F: + return GLFW_KEY_F; + case Key::G: + return GLFW_KEY_G; + case Key::H: + return GLFW_KEY_H; + case Key::J: + return GLFW_KEY_J; + case Key::K: + return GLFW_KEY_K; + case Key::L: + return GLFW_KEY_L; + case Key::Z: + return GLFW_KEY_Z; + case Key::X: + return GLFW_KEY_X; + case Key::C: + return GLFW_KEY_C; + case Key::V: + return GLFW_KEY_V; + case Key::B: + return GLFW_KEY_B; + case Key::N: + return GLFW_KEY_N; + case Key::M: + return GLFW_KEY_M; + case Key::ESCAPE: + return GLFW_KEY_ESCAPE; + case Key::ENTER: + return GLFW_KEY_ENTER; + case Key::SPACE: + return GLFW_KEY_SPACE; + default: + return GLFW_KEY_UNKNOWN; + } +} + +bool Window::GetKeyDown(Key key) +{ + int glfwKey = convertToGlfwKey(key); + if (glfwKey == GLFW_KEY_UNKNOWN) { + return false; + } + + return glfwGetKey(static_cast(_internal), glfwKey) == GLFW_PRESS; +} + +bool Window::GetKeyUp(Key key) +{ + int glfwKey = convertToGlfwKey(key); + if (glfwKey == GLFW_KEY_UNKNOWN) { + return false; + } + + return glfwGetKey(static_cast(_internal), glfwKey) == GLFW_RELEASE; +} + +KeyState Window::GetKeyState(Key key) +{ + int glfwKey = convertToGlfwKey(key); + if (glfwKey == GLFW_KEY_UNKNOWN) { + return KeyState::UNKNOWN; + } + + int state = glfwGetKey(static_cast(_internal), glfwKey); + switch (state) { + case GLFW_RELEASE: + return KeyState::RELEASED; + case GLFW_PRESS: + return KeyState::PRESSED; + case GLFW_REPEAT: + return KeyState::HELD; + default: + return KeyState::UNKNOWN; + } } std::string Window::GetTitle() diff --git a/AtmosphericEngine/window.hpp b/AtmosphericEngine/window.hpp index 735465d..47c9ca1 100644 --- a/AtmosphericEngine/window.hpp +++ b/AtmosphericEngine/window.hpp @@ -29,15 +29,52 @@ struct ImageSize struct WindowProps { - WindowProps(std::string title = INIT_SCREEN_TITLE, int width = INIT_SCREEN_WIDTH, int height = INIT_SCREEN_HEIGHT) - { - this->title = title; - this->width = width; - this->height = height; - }; - std::string title; - int width; - int height; + std::string title = INIT_SCREEN_TITLE; + int width = INIT_SCREEN_WIDTH; + int height = INIT_SCREEN_HEIGHT; +}; + +enum class KeyState { + PRESSED, + RELEASED, + HELD, + UNKNOWN +}; + +enum class Key { + SPACE, + ENTER, + UP, + RIGHT, + LEFT, + DOWN, + Q, + W, + E, + R, + T, + Y, + U, + I, + O, + P, + A, + S, + D, + F, + G, + H, + J, + K, + L, + Z, + X, + C, + V, + B, + N, + M, + ESCAPE = 256, }; class Window @@ -114,9 +151,11 @@ class Window glm::vec2 GetMousePosition(); - bool GetKeyDown(int key); + bool GetKeyDown(Key key); + + bool GetKeyUp(Key key); - bool GetKeyUp(int key); + KeyState GetKeyState(Key key); std::string GetTitle(); diff --git a/Example_HelloWorld/main.cpp b/Example_HelloWorld/main.cpp index f7f3003..dde550b 100644 --- a/Example_HelloWorld/main.cpp +++ b/Example_HelloWorld/main.cpp @@ -19,10 +19,10 @@ class HelloWorld : public Application { cube->SetPosition(glm::vec3(0.0f, 0.0f, std::cos(time) * 2.0f)); cube->SetRotation(glm::vec3(0.0, time * 0.5, time * 1.0)); - if (input.GetKeyDown(KEY_R)) { + if (input.IsKeyDown(Key::R)) { graphics.ReloadShaders(); } - if (input.GetKeyDown(KEY_ESCAPE)) { + if (input.IsKeyDown(Key::ESCAPE)) { Quit(); } } diff --git a/Example_MazeWorld/main.cpp b/Example_MazeWorld/main.cpp index 6425496..6fdba94 100644 --- a/Example_MazeWorld/main.cpp +++ b/Example_MazeWorld/main.cpp @@ -242,7 +242,7 @@ class MazeGame : public Application { // Input handling glm::vec3 currVel = player->GetVelocity(); - if (input.GetKeyDown(KEY_Q)) { + if (input.GetKeyDown(Key::Q)) { glm::vec3 forward = mainCamera->GetEyeDirection(); glm::vec3 pos = mainCamera->GetEyePosition() + forward * 0.5f; glm::vec3 vel = forward * 20.0f; @@ -252,65 +252,65 @@ class MazeGame : public Application { bullets[currentBulletIndex]->SetPosition(pos); bullets[currentBulletIndex]->SetVelocity(vel); } - if (input.GetKeyDown(KEY_W)) { + if (input.GetKeyDown(Key::W)) { glm::vec3 v = mainCamera->GetMoveVector(Axis::FRONT); player->SetVelocity(glm::vec3(v.x, currVel.y, v.z)); } - if (input.GetKeyDown(KEY_S)) { + if (input.GetKeyDown(Key::S)) { glm::vec3 v = mainCamera->GetMoveVector(Axis::FRONT); player->SetVelocity(glm::vec3(-v.x, currVel.y, -v.z)); } - if (input.GetKeyDown(KEY_D)) { + if (input.GetKeyDown(Key::D)) { mainCamera->Yaw(0.3 * CAMERA_ANGULAR_OFFSET); glm::vec3 v = mainCamera->GetMoveVector(Axis::RIGHT); player->SetVelocity(glm::vec3(v.x, currVel.y, v.z)); } - if (input.GetKeyDown(KEY_A)) { + if (input.GetKeyDown(Key::A)) { mainCamera->Yaw(-0.3 * CAMERA_ANGULAR_OFFSET); glm::vec3 v = mainCamera->GetMoveVector(Axis::RIGHT); player->SetVelocity(glm::vec3(-v.x, currVel.y, -v.z)); } - if (input.GetKeyDown(KEY_UP)) { + if (input.GetKeyDown(Key::UP)) { mainCamera->Pitch(CAMERA_ANGULAR_OFFSET); } - if (input.GetKeyDown(KEY_DOWN)) { + if (input.GetKeyDown(Key::DOWN)) { mainCamera->Pitch(-CAMERA_ANGULAR_OFFSET); } - if (input.GetKeyDown(KEY_RIGHT)) { + if (input.GetKeyDown(Key::RIGHT)) { mainCamera->Yaw(CAMERA_ANGULAR_OFFSET); } - if (input.GetKeyDown(KEY_LEFT)) { + if (input.GetKeyDown(Key::LEFT)) { mainCamera->Yaw(-CAMERA_ANGULAR_OFFSET); } - if (input.GetKeyDown(KEY_SPACE) && !isPlayerJumping) { + if (input.GetKeyDown(Key::SPACE) && !isPlayerJumping) { currVel = player->GetVelocity(); // update velcoity to reflect current horizontal speed glm::vec3 v = mainCamera->GetMoveVector(Axis::UP); player->SetVelocity(glm::vec3(currVel.x, v.y, currVel.z)); isPlayerJumping = true; } - if (input.GetKeyDown(KEY_X)) { + if (input.GetKeyDown(Key::X)) { isLightFlashing = !isLightFlashing; } - if (input.GetKeyDown(KEY_Z)) { + if (input.GetKeyDown(Key::Z)) { player->SetPhysicsActivated(false); } - if (input.GetKeyDown(KEY_I)) { + if (input.GetKeyDown(Key::I)) { physics.EnableDebugUI(!isPhysicsDebugUIEnabled); isPhysicsDebugUIEnabled = !isPhysicsDebugUIEnabled; } - if (input.GetKeyDown(KEY_O)) { + if (input.GetKeyDown(Key::O)) { graphics.EnableWireframe(!isWireframeEnabled); isWireframeEnabled = !isWireframeEnabled; } - if (input.GetKeyDown(KEY_P)) { + if (input.GetKeyDown(Key::P)) { graphics.EnablePostProcess(!isPostProcessEnabled); isPostProcessEnabled = !isPostProcessEnabled; } - if (input.GetKeyDown(KEY_R)) { + if (input.GetKeyDown(Key::R)) { graphics.ReloadShaders(); } - if (input.GetKeyDown(KEY_ESCAPE)) { + if (input.GetKeyDown(Key::ESCAPE)) { Quit(); } }