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

这篇具有很好参考价值的文章主要介绍了跟着cherno手搓游戏引擎【7】Input轮询。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

创建基类:

YOTO/Input.h:名如其意

#pragma once
#include"YOTO/Core.h"
namespace YOTO {
	class YOTO_API Input {
	public:
		inline static bool IsKeyPressed(int keycode){
			return s_Instance->IsKeyPressedImpl(keycode);
		}
		inline static bool IsMouseButtonPressed(int button) {
			return s_Instance->IsMouseButtonPressedImpl(button);
		}
		inline static float GetMouseX() {
			return s_Instance->GetMouseXImpl();
		}
		inline static float GetMouseY() {
			return s_Instance->GetMouseYImpl();
		}
		inline static std::pair<float,float> GetMousePostion() {
			return s_Instance->GetMousePositionImpl();
		}
	protected:
		virtual bool IsKeyPressedImpl(int keycode )=0;
		virtual bool IsMouseButtonPressedImpl(int button) = 0;
		virtual float GetMouseXImpl() = 0;
		virtual float GetMouseYImpl() = 0;
		virtual  std::pair<float, float>  GetMousePositionImpl() = 0;

	private:
		static  Input* s_Instance;
	};
}

实现基类:

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

#pragma once
#include"YOTO/Input.h"
namespace YOTO {
	class WindowsInput :public Input {
	protected:
		virtual bool IsKeyPressedImpl(int keycode) override;
		virtual bool IsMouseButtonPressedImpl(int button)override;
		virtual  std::pair<float, float>  GetMousePositionImpl()override;
		virtual float GetMouseXImpl()override;
		virtual float GetMouseYImpl() override;
	};
}

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

#include"ytpch.h"
#include"WindowsInput.h"
#include<GLFW/glfw3.h>
#include"YOTO/Application.h"
namespace YOTO {

	Input* Input::s_Instance = new WindowsInput();
	bool WindowsInput::IsKeyPressedImpl(int keycode)
	{// 获取GLFW原生窗口void*,转为GLFWwindow*
		auto window =static_cast<GLFWwindow*>( Application::Get().GetWindow().GetNativeWindow());
		// 用已有的GLFW函数来获取按键状态
		auto state=	glfwGetKey(window, keycode);
		return state==GLFW_PRESS|| state== GLFW_REPEAT;
	}
	bool WindowsInput::IsMouseButtonPressedImpl(int button)
	{
		auto window = static_cast<GLFWwindow*>(Application::Get().GetWindow().GetNativeWindow());
		auto state = glfwGetMouseButton(window, button);
		return state == GLFW_PRESS ;
	}
	std::pair<float, float> WindowsInput::GetMousePositionImpl()
	{
		auto window = static_cast<GLFWwindow*>(Application::Get().GetWindow().GetNativeWindow());
		double xpos, ypos;
		glfwGetCursorPos(window, &xpos, &ypos);
		return {(float)xpos,(float)ypos};
	}
	float WindowsInput::GetMouseXImpl()
	{
		auto [x, y] = GetMousePositionImpl();

		return x;
	}
	float WindowsInput::GetMouseYImpl()
	{
		auto [x, y] = GetMousePositionImpl();

		return y;
	}
}

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

#pragma once

#include"ytpch.h"
#include"YOTO/Core.h"
#include"YOTO/Event/Event.h"
namespace YOTO {
	struct WindowProps {
		std::string Title;
		unsigned int Width;
		unsigned int Height;
		WindowProps(const std::string &title="YOTO Engine",unsigned int width =1280, unsigned int height = 1280 )
			:Title(title),Width(width),Height(height){}
	};
	class YOTO_API Window {
	public:
		//用EventCallbackFn代替std::function<void(Event&)>:输入为Event&返回值为void 的函数
		using EventCallbackFn = std::function<void(Event&)>;
		virtual ~Window(){}
		//=0为纯虚函数
		virtual void OnUpdate() = 0;
		virtual unsigned int GetWidth() const = 0;
		virtual unsigned int GetHeight() const = 0;
		
		virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
		virtual void SetVSync(bool enable)= 0;
		virtual bool IsVSync() const = 0;
		//返回当前窗口
		virtual void* GetNativeWindow() const=0;

		static Window* Creat(const WindowProps& props = WindowProps());

	};
}

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

#pragma once
#include "YOTO/Window.h"
#include<GLFW/glfw3.h>
#include"YOTO/Log.h"
struct GLFWwindow;
namespace YOTO {
	class WindowsWindow :public Window
	{
	public :
		WindowsWindow(const WindowProps& props);
		virtual ~WindowsWindow();
		void OnUpdate() override;
		
		inline unsigned int GetWidth() const override { return m_Data.Width; };
		inline unsigned int GetHeight() const override { return m_Data.Height; };

		inline void SetEventCallback(const EventCallbackFn& callback)override
		{ m_Data.EventCallback = callback; };
		void SetVSync(bool enable) ;
		bool IsVSync()const;
		//返回window
		inline virtual void* GetNativeWindow() const { return m_Window; }
	private: 
		virtual void Init(const WindowProps& props);
		virtual void ShutDown();
	private:
		GLFWwindow* m_Window;
		struct WindowData {
			std::string Title;
			unsigned int Width, Height;
			bool VSync;
			EventCallbackFn EventCallback;
		};
		WindowData m_Data;
	};
}


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

#include"ytpch.h"
#include "Application.h"

#include"Log.h"
#include<glad/glad.h>
#include"Input.h"
namespace YOTO {
#define BIND_EVENT_FN(x) std::bind(&x, this, std::placeholders::_1)

	 Application* Application::s_Instance = nullptr;

	Application::Application() {

		YT_CORE_ASSERT(!s_Instance, "Application需要为空!")
		s_Instance = this;
		//智能指针
		m_Window = std::unique_ptr<Window>(Window::Creat());
		//设置回调函数
		m_Window->SetEventCallback(BIND_EVENT_FN(Application::OnEvent));
		unsigned int id;
		glGenBuffers(1, &id);
	}
	Application::~Application() {

	}
	/// <summary>
	/// 所有的Window事件都会在这触发,作为参数e
	/// </summary>
	/// <param name="e"></param>
	void Application::OnEvent(Event& e) {
		//根据事件类型绑定对应事件
		EventDispatcher dispatcher(e);
		dispatcher.Dispatch<WindowCloseEvent>(BIND_EVENT_FN(Application::OnWindowClosed));
		//输出事件信息
		YT_CORE_INFO("{0}",e);
		for (auto it = m_LayerStack.end(); it != m_LayerStack.begin();) {
			(*--it)->OnEvent(e);
			if (e.m_Handled)
				break;
		}
	}

	bool Application::OnWindowClosed(WindowCloseEvent& e) {
		m_Running = false;
		return true;
	}
	void Application::Run() {
		WindowResizeEvent e(1280, 720);
		if (e.IsInCategory(EventCategoryApplication)) {
			YT_CORE_TRACE(e);
		}
		if (e.IsInCategory(EventCategoryInput)) {
			YT_CORE_ERROR(e);
		}

		while (m_Running)
		{
			glClearColor(1,0,1,1);
			glClear(GL_COLOR_BUFFER_BIT);

			for (Layer* layer : m_LayerStack) {
				layer->OnUpdate();
			}
			auto [x, y] = Input::GetMousePostion();
			YT_CORE_TRACE("{0},{1}",x, y);
			m_Window->OnUpdate();
		}
	}
	void Application::PushLayer(Layer* layer) {
		m_LayerStack.PushLayer(layer);
		layer->OnAttach();
	}
	void Application::PushOverlay(Layer* layer) {
		m_LayerStack.PushOverlay(layer);
		layer->OnDetach();
	}
}

测试: 

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

小改动:

Core.h:

#pragma once
//用于dll的宏
#ifdef YT_PLATFORM_WINDOWS
#ifdef YT_BUILD_DLL
#define YOTO_API __declspec(dllexport) 
#else
#define YOTO_API __declspec(dllimport) 

#endif // DEBUG
#else
#error YOTO_ONLY_SUPPORT_WINDOWS
#endif // YOTO_PLATFORM_WINDOWS

#ifdef YT_DEBUG
#define YT_ENABLE_ASSERTS
#endif

#ifdef YT_ENABLE_ASSERTS
#define YT_CLIENT_ASSERT(x,...) {if(!(x)){YT_CLIENT_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}
#define YT_CORE_ASSERT(x,...) {if(!(x)){YT_CORE_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}
#else
#define YT_CLIENT_ASSERT(x,...)
#define YT_CORE_ASSERT(x,...)

#endif // YT_ENABLE_ASSERTS



#define BIT(x)(1<<x)
//绑定事件定义
#define YT_BIND_EVENT_FN(fn) std::bind(&fn, this, std::placeholders::_1)

SRC下的premake5.lua:文章来源地址https://www.toymoban.com/news/detail-797776.html

workspace "YOTOEngine"		-- sln文件名
	architecture "x64"	
	configurations{
		"Debug",
		"Release",
		"Dist"
	}
startproject "Sandbox"
-- https://github.com/premake/premake-core/wiki/Tokens#value-tokens
-- 组成输出目录:Debug-windows-x86_64
outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"
-- 包含相对解决方案的目录
IncludeDir={}
IncludeDir["GLFW"]="YOTOEngine/vendor/GLFW/include"
IncludeDir["Glad"]="YOTOEngine/vendor/Glad/include"
IncludeDir["ImGui"] ="YOTOEngine/vendor/imgui"
--项目中包含某包
include "YOTOEngine/vendor/GLFW"
include "YOTOEngine/vendor/Glad"
include "YOTOEngine/vendor/imgui"

project "YOTOEngine"		--YOTOEngine项目
	location "YOTOEngine"--在sln所属文件夹下的YOTOEngine文件夹
	kind "SharedLib"--dll动态库
	language "C++"
	targetdir ("bin/" .. outputdir .. "/%{prj.name}") -- 输出目录
	objdir ("bin-int/" .. outputdir .. "/%{prj.name}")-- 中间目录

	staticruntime "Off"

	pchheader "ytpch.h"
	pchsource "YOTOEngine/src/ytpch.cpp"
	-- 包含的所有h和cpp文件
	files{
		"%{prj.name}/src/**.h",
		"%{prj.name}/src/**.cpp"
	}
	-- 包含目录
	includedirs{
		"%{prj.name}/src",
		"%{prj.name}/vendor/spdlog-1.x/include",
		"%{IncludeDir.GLFW}",
		"%{IncludeDir.Glad}",
		"%{IncludeDir.ImGui}"
	}
	links{
		"GLFW",-- GLFW.lib库链接到YOTOEngine项目中
		"Glad",-- Glad.lib库链接到YOTOEngine项目中
		"ImGui",-- ImGui.lib库链接到YOTOEngine项目中
		"opengl32.lib"
	}
	-- 如果是window系统
	filter "system:windows"
		cppdialect "C++17"
		-- On:代码生成的运行库选项是MTD,静态链接MSVCRT.lib库;
		-- Off:代码生成的运行库选项是MDD,动态链接MSVCRT.dll库;打包后的exe放到另一台电脑上若无这个dll会报错
		systemversion "latest"	-- windowSDK版本
		-- 预处理器定义
		defines{
			"YT_PLATFORM_WINDOWS",
			"YT_BUILD_DLL",
			-- "YT_ENABLE_ASSERTS",
			"GLFW_INCLUDE_NONE"-- 让GLFW不包含OpenGL
		}
		-- 编译好后移动Hazel.dll文件到Sandbox文件夹下
		postbuildcommands{
			("{COPY} %{cfg.buildtarget.relpath} ../bin/" .. outputdir .. "/Sandbox")
		}
	-- 不同配置下的预定义不同
	filter "configurations:Debug"
		defines "YT_DEBUG"
		runtime "Debug"
		symbols "On"

	filter "configurations:Release"
		defines "YT_RELEASE"
		runtime "Release"
		optimize "On"

	filter "configurations:Dist"
		defines "YT_DIST"
		runtime "Release"
		optimize "On"

project "Sandbox"
	location "Sandbox"
	kind "ConsoleApp"
	language "C++"
	staticruntime "Off"
	targetdir ("bin/" .. outputdir .. "/%{prj.name}")
	objdir ("bin-int/" .. outputdir .. "/%{prj.name}")

	files{
		"%{prj.name}/src/**.h",
		"%{prj.name}/src/**.cpp"
	}
	-- 同样包含spdlog头文件
	includedirs{
		"YOTOEngine/vendor/spdlog-1.x/include",
		"YOTOEngine/src"
	}
	-- 引用YOTOEngine
	links{
		"YOTOEngine",
		"GLFW",
		"opengl32.lib"
	}

	filter "system:windows"
		cppdialect "C++17"
		systemversion "latest"

		defines{
			"YT_PLATFORM_WINDOWS"
		}

	filter "configurations:Debug"
		defines "YT_DEBUG"
		runtime "Debug"
		symbols "On"

	filter "configurations:Release"
		defines "YT_RELEASE"
		runtime "Release"
		optimize "On"

	filter "configurations:Dist"
		defines "YT_DIST"
		runtime "Release"
		optimize "On"

到了这里,关于跟着cherno手搓游戏引擎【7】Input轮询的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 跟着cherno手搓游戏引擎【8】按键和鼠标的KeyCode

    先把glfw3.h里的KeyCode的定义抄到咱这里来。 在YOTO下创建KeyCode.h:  MouseButtonCodes.h:和KeyCode.h一样作用,把GLFW改成自己的 YOTO.h: SandboxApp.cpp:在ExampleLayer测试轮询和KeyCode  明日继续更新数学和ImGui停靠和视口

    2024年01月18日
    浏览(32)
  • 跟着cherno手搓游戏引擎【4】窗口抽象、GLFW配置、窗口事件

    在vendor里创建GLFW文件夹: 在github上下载,把包下载到GLFW包下。 GitHub - TheCherno/glfw: A multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input修改SRC/premake5.lua的配置:12、13、15、36、37、38、39、40行的代码是新加上去的: GLFW中的premake5.lua:  如出现此BUG:请找GLFW中的premake5文件,

    2024年01月21日
    浏览(40)
  • input[type=“number“]鼠标滚动时值跟着改变

    原因:table里面嵌入input[type=\\\"number\\\"]输入框,鼠标滚动时值跟着改变 需求:鼠标滚动时,不改变input值,只页面滚动 思路: * 1.监听mousewheel事件; * 2.获取input输入框元素; * 3.当监听到鼠标滚动事件时,设置input元素失去光标 使用: *(1)在DOM上加上v-stopMousewheel即可      

    2024年02月11日
    浏览(33)
  • 【用unity实现100个游戏之4】手搓一个网格放置功能,及装修建造种植功能(2d3d通用,附源码)

    参考原视频链接 【视频】:https://www.youtube.com/watch?v=l0emsAHIBjU 注意 :本文为学习笔记记录,推荐支持原作者,去看原视频自己手敲代码理解更加深入

    2024年02月13日
    浏览(40)
  • 无敌!我用【C语言】手搓出了一个体系完整的【员工管理系统】还能玩游戏听音乐?(超详细,附完整源码)

    博主简介: Hello大家好呀,我是陈童学,一个与你一样正在慢慢前行的人。 博主主页: @陈童学哦 所属专栏: C语言程序设计实验项目 如果本文对你有所帮助的话,还希望可以点赞👍收藏📂支持一下哦! 前言:员工管理系统是一款面向公司管理员的管理工具,旨在提供员工

    2024年02月08日
    浏览(47)
  • 【Unity_Input System】Input System新输入系统(三)——在游戏中更换按键绑定

    Binding只由一个部分组成,一般绑定单个按键或者摇杆 CompositeBinding由两个以上部分组成,一般是用于将多个按键组成虚拟轴 更换按键绑定时,Binding和Composite Binding需要分别处理,对Composite Binding需要循环各个部分进行修改。 可以用InputBinding.isComposite来判断是否是Composite Bind

    2024年02月04日
    浏览(44)
  • 了解游戏引擎,游戏引擎的选择:2D3D游戏开发

    常用的游戏开发引擎有很多,以下是一些在游戏开发领域中较为流行和广泛应用的引擎: 1. Unity游戏引擎 特点: 强大的跨平台支持,可以发布到多个平台,包括PC、移动设备和主机。 大量的插件和资产商店,便于开发者获取各种功能和资源。 相对易学易用,拥有大量的教程

    2024年03月10日
    浏览(53)
  • HTML5游戏引擎(一)-egret引擎简介——一个开源免费的游戏框架

    游戏行业发展迅速, 给程序员提供了大量就业 (斗鱼, 微派, 腾讯, 蓝月, 网易 等等) 游戏开发薪资普遍比较高 (王者荣耀 , 蓝月) 游戏已经普遍被大众所认可,并且发展成一种竞技体育 重点学习Egret Typescrit 语法学习 一笔带过Cocos2d-x Egret跨平台,入手容易,性能较好,更

    2024年02月05日
    浏览(72)
  • 游戏引擎架构-游戏支持的系统

    本篇知识点来源于《游戏引擎架构》第五章,此章节主要讨论多数游戏引擎中都会出现的底层支持系统。 C++静态初始化次序是无法使用的,原因是我们无法预引擎子系统的构造函数调用次序和析构函数调用次序。比如我要启动引擎的A,B,C系统,无法保证这些系统是按照规定

    2024年01月16日
    浏览(44)
  • 游戏引擎架构01__引擎架构图

    根据游戏引擎架构预设的引擎架构来构建运行时引擎架构 ​

    2024年04月09日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包