当前位置:   article > 正文

跟着cherno手搓游戏引擎【7】Input轮询

跟着cherno手搓游戏引擎【7】Input轮询

在引擎程序中任何时间,任何位置都能知道按键是否按下、鼠标的位置等等信息。

与事件系统的区别:事件系统是在按下时调用并传递按键状态;轮询是每时每刻都能获取按键状态

创建基类:

YOTO/Input.h:名如其意

  1. #pragma once
  2. #include"YOTO/Core.h"
  3. namespace YOTO {
  4. class YOTO_API Input {
  5. public:
  6. inline static bool IsKeyPressed(int keycode){
  7. return s_Instance->IsKeyPressedImpl(keycode);
  8. }
  9. inline static bool IsMouseButtonPressed(int button) {
  10. return s_Instance->IsMouseButtonPressedImpl(button);
  11. }
  12. inline static float GetMouseX() {
  13. return s_Instance->GetMouseXImpl();
  14. }
  15. inline static float GetMouseY() {
  16. return s_Instance->GetMouseYImpl();
  17. }
  18. inline static std::pair<float,float> GetMousePostion() {
  19. return s_Instance->GetMousePositionImpl();
  20. }
  21. protected:
  22. virtual bool IsKeyPressedImpl(int keycode )=0;
  23. virtual bool IsMouseButtonPressedImpl(int button) = 0;
  24. virtual float GetMouseXImpl() = 0;
  25. virtual float GetMouseYImpl() = 0;
  26. virtual std::pair<float, float> GetMousePositionImpl() = 0;
  27. private:
  28. static Input* s_Instance;
  29. };
  30. }

实现基类:

 在Platform/Windows/下创建WindowsInput.h:

  1. #pragma once
  2. #include"YOTO/Input.h"
  3. namespace YOTO {
  4. class WindowsInput :public Input {
  5. protected:
  6. virtual bool IsKeyPressedImpl(int keycode) override;
  7. virtual bool IsMouseButtonPressedImpl(int button)override;
  8. virtual std::pair<float, float> GetMousePositionImpl()override;
  9. virtual float GetMouseXImpl()override;
  10. virtual float GetMouseYImpl() override;
  11. };
  12. }

WindowsInput.cpp:获取window然后用glfw自带的事件检测来 

  1. #include"ytpch.h"
  2. #include"WindowsInput.h"
  3. #include<GLFW/glfw3.h>
  4. #include"YOTO/Application.h"
  5. namespace YOTO {
  6. Input* Input::s_Instance = new WindowsInput();
  7. bool WindowsInput::IsKeyPressedImpl(int keycode)
  8. {// 获取GLFW原生窗口void*,转为GLFWwindow*
  9. auto window =static_cast<GLFWwindow*>( Application::Get().GetWindow().GetNativeWindow());
  10. // 用已有的GLFW函数来获取按键状态
  11. auto state= glfwGetKey(window, keycode);
  12. return state==GLFW_PRESS|| state== GLFW_REPEAT;
  13. }
  14. bool WindowsInput::IsMouseButtonPressedImpl(int button)
  15. {
  16. auto window = static_cast<GLFWwindow*>(Application::Get().GetWindow().GetNativeWindow());
  17. auto state = glfwGetMouseButton(window, button);
  18. return state == GLFW_PRESS ;
  19. }
  20. std::pair<float, float> WindowsInput::GetMousePositionImpl()
  21. {
  22. auto window = static_cast<GLFWwindow*>(Application::Get().GetWindow().GetNativeWindow());
  23. double xpos, ypos;
  24. glfwGetCursorPos(window, &xpos, &ypos);
  25. return {(float)xpos,(float)ypos};
  26. }
  27. float WindowsInput::GetMouseXImpl()
  28. {
  29. auto [x, y] = GetMousePositionImpl();
  30. return x;
  31. }
  32. float WindowsInput::GetMouseYImpl()
  33. {
  34. auto [x, y] = GetMousePositionImpl();
  35. return y;
  36. }
  37. }

为了能在任何时候获取到GLFWwindow,在Window.h中创建方法获取Window

  1. #pragma once
  2. #include"ytpch.h"
  3. #include"YOTO/Core.h"
  4. #include"YOTO/Event/Event.h"
  5. namespace YOTO {
  6. struct WindowProps {
  7. std::string Title;
  8. unsigned int Width;
  9. unsigned int Height;
  10. WindowProps(const std::string &title="YOTO Engine",unsigned int width =1280, unsigned int height = 1280 )
  11. :Title(title),Width(width),Height(height){}
  12. };
  13. class YOTO_API Window {
  14. public:
  15. //用EventCallbackFn代替std::function<void(Event&)>:输入为Event&返回值为void 的函数
  16. using EventCallbackFn = std::function<void(Event&)>;
  17. virtual ~Window(){}
  18. //=0为纯虚函数
  19. virtual void OnUpdate() = 0;
  20. virtual unsigned int GetWidth() const = 0;
  21. virtual unsigned int GetHeight() const = 0;
  22. virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
  23. virtual void SetVSync(bool enable)= 0;
  24. virtual bool IsVSync() const = 0;
  25. //返回当前窗口
  26. virtual void* GetNativeWindow() const=0;
  27. static Window* Creat(const WindowProps& props = WindowProps());
  28. };
  29. }

WindowsWindow.h :实现返回window的方法:

  1. #pragma once
  2. #include "YOTO/Window.h"
  3. #include<GLFW/glfw3.h>
  4. #include"YOTO/Log.h"
  5. struct GLFWwindow;
  6. namespace YOTO {
  7. class WindowsWindow :public Window
  8. {
  9. public :
  10. WindowsWindow(const WindowProps& props);
  11. virtual ~WindowsWindow();
  12. void OnUpdate() override;
  13. inline unsigned int GetWidth() const override { return m_Data.Width; };
  14. inline unsigned int GetHeight() const override { return m_Data.Height; };
  15. inline void SetEventCallback(const EventCallbackFn& callback)override
  16. { m_Data.EventCallback = callback; };
  17. void SetVSync(bool enable) ;
  18. bool IsVSync()const;
  19. //返回window
  20. inline virtual void* GetNativeWindow() const { return m_Window; }
  21. private:
  22. virtual void Init(const WindowProps& props);
  23. virtual void ShutDown();
  24. private:
  25. GLFWwindow* m_Window;
  26. struct WindowData {
  27. std::string Title;
  28. unsigned int Width, Height;
  29. bool VSync;
  30. EventCallbackFn EventCallback;
  31. };
  32. WindowData m_Data;
  33. };
  34. }

Application.cpp:在Run中获取鼠标位置:

  1. #include"ytpch.h"
  2. #include "Application.h"
  3. #include"Log.h"
  4. #include<glad/glad.h>
  5. #include"Input.h"
  6. namespace YOTO {
  7. #define BIND_EVENT_FN(x) std::bind(&x, this, std::placeholders::_1)
  8. Application* Application::s_Instance = nullptr;
  9. Application::Application() {
  10. YT_CORE_ASSERT(!s_Instance, "Application需要为空!")
  11. s_Instance = this;
  12. //智能指针
  13. m_Window = std::unique_ptr<Window>(Window::Creat());
  14. //设置回调函数
  15. m_Window->SetEventCallback(BIND_EVENT_FN(Application::OnEvent));
  16. unsigned int id;
  17. glGenBuffers(1, &id);
  18. }
  19. Application::~Application() {
  20. }
  21. /// <summary>
  22. /// 所有的Window事件都会在这触发,作为参数e
  23. /// </summary>
  24. /// <param name="e"></param>
  25. void Application::OnEvent(Event& e) {
  26. //根据事件类型绑定对应事件
  27. EventDispatcher dispatcher(e);
  28. dispatcher.Dispatch<WindowCloseEvent>(BIND_EVENT_FN(Application::OnWindowClosed));
  29. //输出事件信息
  30. YT_CORE_INFO("{0}",e);
  31. for (auto it = m_LayerStack.end(); it != m_LayerStack.begin();) {
  32. (*--it)->OnEvent(e);
  33. if (e.m_Handled)
  34. break;
  35. }
  36. }
  37. bool Application::OnWindowClosed(WindowCloseEvent& e) {
  38. m_Running = false;
  39. return true;
  40. }
  41. void Application::Run() {
  42. WindowResizeEvent e(1280, 720);
  43. if (e.IsInCategory(EventCategoryApplication)) {
  44. YT_CORE_TRACE(e);
  45. }
  46. if (e.IsInCategory(EventCategoryInput)) {
  47. YT_CORE_ERROR(e);
  48. }
  49. while (m_Running)
  50. {
  51. glClearColor(1,0,1,1);
  52. glClear(GL_COLOR_BUFFER_BIT);
  53. for (Layer* layer : m_LayerStack) {
  54. layer->OnUpdate();
  55. }
  56. auto [x, y] = Input::GetMousePostion();
  57. YT_CORE_TRACE("{0},{1}",x, y);
  58. m_Window->OnUpdate();
  59. }
  60. }
  61. void Application::PushLayer(Layer* layer) {
  62. m_LayerStack.PushLayer(layer);
  63. layer->OnAttach();
  64. }
  65. void Application::PushOverlay(Layer* layer) {
  66. m_LayerStack.PushOverlay(layer);
  67. layer->OnDetach();
  68. }
  69. }

测试: 

小改动:

Core.h:

  1. #pragma once
  2. //用于dll的宏
  3. #ifdef YT_PLATFORM_WINDOWS
  4. #ifdef YT_BUILD_DLL
  5. #define YOTO_API __declspec(dllexport)
  6. #else
  7. #define YOTO_API __declspec(dllimport)
  8. #endif // DEBUG
  9. #else
  10. #error YOTO_ONLY_SUPPORT_WINDOWS
  11. #endif // YOTO_PLATFORM_WINDOWS
  12. #ifdef YT_DEBUG
  13. #define YT_ENABLE_ASSERTS
  14. #endif
  15. #ifdef YT_ENABLE_ASSERTS
  16. #define YT_CLIENT_ASSERT(x,...) {if(!(x)){YT_CLIENT_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}
  17. #define YT_CORE_ASSERT(x,...) {if(!(x)){YT_CORE_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}
  18. #else
  19. #define YT_CLIENT_ASSERT(x,...)
  20. #define YT_CORE_ASSERT(x,...)
  21. #endif // YT_ENABLE_ASSERTS
  22. #define BIT(x)(1<<x)
  23. //绑定事件定义
  24. #define YT_BIND_EVENT_FN(fn) std::bind(&fn, this, std::placeholders::_1)

SRC下的premake5.lua:

  1. workspace "YOTOEngine" -- sln文件名
  2. architecture "x64"
  3. configurations{
  4. "Debug",
  5. "Release",
  6. "Dist"
  7. }
  8. startproject "Sandbox"
  9. -- https://github.com/premake/premake-core/wiki/Tokens#value-tokens
  10. -- 组成输出目录:Debug-windows-x86_64
  11. outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"
  12. -- 包含相对解决方案的目录
  13. IncludeDir={}
  14. IncludeDir["GLFW"]="YOTOEngine/vendor/GLFW/include"
  15. IncludeDir["Glad"]="YOTOEngine/vendor/Glad/include"
  16. IncludeDir["ImGui"] ="YOTOEngine/vendor/imgui"
  17. --项目中包含某包
  18. include "YOTOEngine/vendor/GLFW"
  19. include "YOTOEngine/vendor/Glad"
  20. include "YOTOEngine/vendor/imgui"
  21. project "YOTOEngine" --YOTOEngine项目
  22. location "YOTOEngine"--在sln所属文件夹下的YOTOEngine文件夹
  23. kind "SharedLib"--dll动态库
  24. language "C++"
  25. targetdir ("bin/" .. outputdir .. "/%{prj.name}") -- 输出目录
  26. objdir ("bin-int/" .. outputdir .. "/%{prj.name}")-- 中间目录
  27. staticruntime "Off"
  28. pchheader "ytpch.h"
  29. pchsource "YOTOEngine/src/ytpch.cpp"
  30. -- 包含的所有h和cpp文件
  31. files{
  32. "%{prj.name}/src/**.h",
  33. "%{prj.name}/src/**.cpp"
  34. }
  35. -- 包含目录
  36. includedirs{
  37. "%{prj.name}/src",
  38. "%{prj.name}/vendor/spdlog-1.x/include",
  39. "%{IncludeDir.GLFW}",
  40. "%{IncludeDir.Glad}",
  41. "%{IncludeDir.ImGui}"
  42. }
  43. links{
  44. "GLFW",-- GLFW.lib库链接到YOTOEngine项目中
  45. "Glad",-- Glad.lib库链接到YOTOEngine项目中
  46. "ImGui",-- ImGui.lib库链接到YOTOEngine项目中
  47. "opengl32.lib"
  48. }
  49. -- 如果是window系统
  50. filter "system:windows"
  51. cppdialect "C++17"
  52. -- On:代码生成的运行库选项是MTD,静态链接MSVCRT.lib库;
  53. -- Off:代码生成的运行库选项是MDD,动态链接MSVCRT.dll库;打包后的exe放到另一台电脑上若无这个dll会报错
  54. systemversion "latest" -- windowSDK版本
  55. -- 预处理器定义
  56. defines{
  57. "YT_PLATFORM_WINDOWS",
  58. "YT_BUILD_DLL",
  59. -- "YT_ENABLE_ASSERTS",
  60. "GLFW_INCLUDE_NONE"-- 让GLFW不包含OpenGL
  61. }
  62. -- 编译好后移动Hazel.dll文件到Sandbox文件夹下
  63. postbuildcommands{
  64. ("{COPY} %{cfg.buildtarget.relpath} ../bin/" .. outputdir .. "/Sandbox")
  65. }
  66. -- 不同配置下的预定义不同
  67. filter "configurations:Debug"
  68. defines "YT_DEBUG"
  69. runtime "Debug"
  70. symbols "On"
  71. filter "configurations:Release"
  72. defines "YT_RELEASE"
  73. runtime "Release"
  74. optimize "On"
  75. filter "configurations:Dist"
  76. defines "YT_DIST"
  77. runtime "Release"
  78. optimize "On"
  79. project "Sandbox"
  80. location "Sandbox"
  81. kind "ConsoleApp"
  82. language "C++"
  83. staticruntime "Off"
  84. targetdir ("bin/" .. outputdir .. "/%{prj.name}")
  85. objdir ("bin-int/" .. outputdir .. "/%{prj.name}")
  86. files{
  87. "%{prj.name}/src/**.h",
  88. "%{prj.name}/src/**.cpp"
  89. }
  90. -- 同样包含spdlog头文件
  91. includedirs{
  92. "YOTOEngine/vendor/spdlog-1.x/include",
  93. "YOTOEngine/src"
  94. }
  95. -- 引用YOTOEngine
  96. links{
  97. "YOTOEngine",
  98. "GLFW",
  99. "opengl32.lib"
  100. }
  101. filter "system:windows"
  102. cppdialect "C++17"
  103. systemversion "latest"
  104. defines{
  105. "YT_PLATFORM_WINDOWS"
  106. }
  107. filter "configurations:Debug"
  108. defines "YT_DEBUG"
  109. runtime "Debug"
  110. symbols "On"
  111. filter "configurations:Release"
  112. defines "YT_RELEASE"
  113. runtime "Release"
  114. optimize "On"
  115. filter "configurations:Dist"
  116. defines "YT_DIST"
  117. runtime "Release"
  118. optimize "On"

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/40746?site
推荐阅读
相关标签
  

闽ICP备14008679号