跟着cherno手搓游戏引擎【3】事件系统和预编译头文件

不多说了直接上代码,课程中的架构讲的比较宽泛,而且有些方法写完之后并未测试。所以先把代码写完。理解其原理,未来使用时候会再此完善此博客。

文件架构:

Event.h:核心基类

#pragma once
#include"../Core.h"
#include<string>
#include<functional>
namespace YOTO {// Hazel中的事件当前是阻塞的,这意味着当一个事件发生时,它立即被分派,必须立即处理。//将来,一个更好的策略可能是在事件总线中缓冲事件,并在更新阶段的“事件”部分处理它们。//事件类型enum class EventType{None = 0,WindowClose, WindowResize, WindowFocus, WindowLostFocus, WindowMoved,AppTick, AppUpdate, AppRender,KeyPressed, KeyReleased,MouseButtonPressed, MouseButtonReleased, MouseMoved, MouseScrolled};//事件分类enum EventCategory {None = 0,EventCategoryApplication = BIT(0),EventCategoryInput = BIT(1),EventCategoryKeyboard = BIT(2),EventCategoryMouse = BIT(3),EventCategoryMouseButton = BIT(4)};//定义一些重复的重写的函数,只需要传入固定参数,就能少些一大部分代码
#define EVENT_CLASS_TYPE(type) static EventType GetStaticType(){return EventType::##type; }\virtual EventType GetEventType() const override {return GetStaticType();}\virtual const char* GetName() const override {return #type;}
#define EVENT_CLASS_CATEGORY(category) virtual int GetCategoryFlags() const override {return category; }/// <summary>/// 事件基类,事件需要继承此类/// </summary>class Event{public://获得该事件的具体类型virtual EventType GetEventType() const = 0;//获得事件的名称virtual const char* GetName() const = 0;//获得该事件的大类型virtual int GetCategoryFlags() const = 0;//toString方法,返回事件名virtual std::string ToString() const { return GetName(); }//判断该事件是否是category类inline bool IsInCategory(EventCategory category) {return GetCategoryFlags() & category;}protected://事件是否被处理了bool m_Handled = false;};/// <summary>/// 基于事件类型调度事件的方法(暂时没有测试,不知道怎么用)/// </summary>class EventDispatcher{template <typename T>using EventFn = std::function<bool(T&)>;public:EventDispatcher(Event& event):m_Event(event) {}template <typename T>bool Dispatch(EventFn<T> func) {if (m_Event.GetEventType() == T::GetStaticType()) {m_Event.m_Handled = func(*(T*)&m_Event);return true;}return false;}private:Event& m_Event;};//暂无测试,方便输出inline std::ostream& operator<<(std::ostream& os, const Event& e){return  os << e.ToString();}}

 ApplicationEvent.h:处理appwindow的各种事件

#pragma once
#include"Event.h"
#include<sstream>
namespace YOTO {class YOTO_API WindowResizeEvent :public Event {public:WindowResizeEvent(unsigned int width, unsigned int height) :m_Width(width), m_Height(height) {}inline unsigned int GetWidth() const { return m_Width; }inline unsigned int GetHeight() const { return m_Height; }std::string ToString() const override {std::stringstream ss;ss << "窗口大小改变事件:" << m_Width << "," << m_Height;return ss.str();}EVENT_CLASS_TYPE(WindowResize)EVENT_CLASS_CATEGORY(EventCategoryApplication)private:unsigned int m_Width, m_Height;};class YOTO_API WindowCloseEvent :public Event{public:WindowCloseEvent(){}EVENT_CLASS_TYPE(WindowClose)EVENT_CLASS_CATEGORY(EventCategoryApplication)};class YOTO_API AppTickEvent :public Event {public:AppTickEvent(){}EVENT_CLASS_TYPE(AppTick)EVENT_CLASS_CATEGORY(EventCategoryApplication)};class YOTO_API AppUpdateEvent :public Event {public:AppUpdateEvent(){}EVENT_CLASS_TYPE(AppUpdate)EVENT_CLASS_CATEGORY(EventCategoryApplication)};class YOTO_API AppRenderEvent :public Event {public:AppRenderEvent() {}EVENT_CLASS_TYPE(AppRender)EVENT_CLASS_CATEGORY(EventCategoryApplication)};
}

KeyEvent.h:处理键盘事件

#pragma once
#include"Event.h"
#include<sstream>
namespace YOTO {class YOTO_API KeyEvent:public Event{public:inline int GetKeyCode() const { return m_KeyCode; }EVENT_CLASS_CATEGORY(EventCategoryKeyboard | EventCategoryInput)protected:KeyEvent(int keycode):m_KeyCode(keycode){}int m_KeyCode;};class YOTO_API KeyPressedEvent :public KeyEvent{public:KeyPressedEvent(int keycode, int repeatCount):KeyEvent(keycode),m_RepeatCount(repeatCount){}inline int GetRepeatCount() const { return m_RepeatCount; }std::string ToString() const override{std::stringstream ss;ss << "键盘按下事件:" << m_KeyCode << "(" << m_RepeatCount << "重复)";return ss.str();}//static EventType GetStaticType() { return EventType::KeyPressed; }//virtual EventType GetEventType()const override { return GetStaticType(); }//virtual const char* GetName()const override { return "KeyPressed"; }EVENT_CLASS_TYPE(KeyPressed)private:int m_RepeatCount;};class KeyReleasedEvent:public KeyEvent{public:KeyReleasedEvent(int keycode):KeyEvent(keycode){}std::string ToString()const override {std::stringstream ss;ss << "键盘释放事件:" << m_KeyCode;return ss.str(); }EVENT_CLASS_TYPE(KeyReleased)};}

 MouseEvent.h:处理鼠标事件

#pragma once
#include"Event.h"
#include<sstream>
namespace YOTO {class YOTO_API MouseMovedEvent :public Event{public:MouseMovedEvent(float x, float y):m_MouseX(x), m_MouseY(y) {}inline float GetX() const { return m_MouseX; }inline float GetY() const { return m_MouseY; }std::string ToString() const override {std::stringstream ss;ss << "鼠标移动事件:" << m_MouseX << "," << m_MouseY;return ss.str();}EVENT_CLASS_TYPE(MouseMoved)EVENT_CLASS_CATEGORY(EventCategoryMouse |EventCategoryInput )private:float m_MouseX, m_MouseY;};class YOTO_API MouseScrolledEvent :public Event{public:MouseScrolledEvent(float x, float y):m_XOffset(x), m_YOffset(y) {}inline float GetXOffset() const { return m_XOffset; }inline float GetYOffset() const { return m_YOffset; }std::string ToString() const override {std::stringstream ss;ss << "鼠标滚动事件:" << GetXOffset() << "," << GetYOffset();return ss.str();}EVENT_CLASS_TYPE(MouseScrolled)EVENT_CLASS_CATEGORY(EventCategoryMouse | EventCategoryInput)private:float m_XOffset, m_YOffset;};class YOTO_API MouseButtonEvent :public Event{public:inline int GetMouseButton() const { return m_Button; }EVENT_CLASS_CATEGORY(EventCategoryMouse | EventCategoryInput)protected:MouseButtonEvent(int button):m_Button(button){}int m_Button;};class YOTO_API MouseButtonPressedEvent :public MouseButtonEvent{public:MouseButtonPressedEvent(int button) :MouseButtonEvent(button) {}std::string ToString() const override {std::stringstream ss;ss << "鼠标按下事件:" << m_Button;return ss.str();}EVENT_CLASS_TYPE(MouseButtonPressed)};class YOTO_API MouseButtonReleasedEvent :public MouseButtonEvent{public:MouseButtonReleasedEvent(int button):MouseButtonEvent(button) {}std::string ToString() const override {std::stringstream ss;ss << "鼠标松开事件:" << m_Button;return ss.str();}EVENT_CLASS_TYPE(MouseButtonReleased)};
}

说白了就是写了个基类,然后写了实现类。

修改:

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
#define BIT(x)(1<<x)

记得加Event.h的头文件

premake5.lua

workspace "YOTOEngine"		-- sln文件名architecture "x64"	configurations{"Debug","Release","Dist"}
-- https://github.com/premake/premake-core/wiki/Tokens#value-tokens
-- 组成输出目录:Debug-windows-x86_64
outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"project "YOTOEngine"		--Hazel项目location "YOTOEngine"--在sln所属文件夹下的Hazel文件夹kind "SharedLib"--dll动态库language "C++"targetdir ("bin/" .. outputdir .. "/%{prj.name}") -- 输出目录objdir ("bin-int/" .. outputdir .. "/%{prj.name}")-- 中间目录-- 包含的所有h和cpp文件files{"%{prj.name}/src/**.h","%{prj.name}/src/**.cpp"}-- 包含目录includedirs{"%{prj.name}/src","%{prj.name}/vendor/spdlog-1.x/include"}-- 如果是window系统filter "system:windows"cppdialect "C++17"-- On:代码生成的运行库选项是MTD,静态链接MSVCRT.lib库;-- Off:代码生成的运行库选项是MDD,动态链接MSVCRT.dll库;打包后的exe放到另一台电脑上若无这个dll会报错staticruntime "On"	systemversion "latest"	-- windowSDK版本-- 预处理器定义defines{"YT_PLATFORM_WINDOWS","YT_BUILD_DLL"}-- 编译好后移动Hazel.dll文件到Sandbox文件夹下postbuildcommands{("{COPY} %{cfg.buildtarget.relpath} ../bin/" .. outputdir .. "/Sandbox")}-- 不同配置下的预定义不同filter "configurations:Debug"defines "YT_DEBUG"symbols "On"filter "configurations:Release"defines "YT_RELEASE"optimize "On"filter "configurations:Dist"defines "YT_DIST"optimize "On"project "Sandbox"location "Sandbox"kind "ConsoleApp"language "C++"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"}-- 引用hazellinks{"YOTOEngine"}filter "system:windows"cppdialect "C++17"staticruntime "On"systemversion "latest"defines{"YT_PLATFORM_WINDOWS"}filter "configurations:Debug"defines "YT_DEBUG"symbols "On"filter "configurations:Release"defines "YT_RELEASE"optimize "On"filter "configurations:Dist"defines "YT_DIST"optimize "On"

测试: 

Application.cpp

#include "Application.h"
#include"Event/ApplicationEvent.h"
#include"Log.h"
namespace YOTO {Application::Application() {}Application::~Application() {}void Application::Run() {WindowResizeEvent e(1280, 720);if (e.IsInCategory(EventCategoryApplication)) {YT_CORE_TRACE(e);}if (e.IsInCategory(EventCategoryInput)) {YT_CORE_ERROR(e);}while (true){}}
}

 预编译头文件:

ytpch.h

#pragma once
#include<iostream>
#include<memory>
#include<utility>
#include<algorithm>
#include<functional>
#include<string>
#include<vector>
#include<unordered_map>
#include<unordered_set>
#include<sstream>
#ifdef YT_PLATFORM_WINDOWS
#include<Windows.h>
#endif // YT_PLATFORM_WINDOWS

ytpch.cpp

#include "ytpch.h"

premake5.lua:

workspace "YOTOEngine"		-- sln文件名architecture "x64"	configurations{"Debug","Release","Dist"}
-- https://github.com/premake/premake-core/wiki/Tokens#value-tokens
-- 组成输出目录:Debug-windows-x86_64
outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"project "YOTOEngine"		--Hazel项目location "YOTOEngine"--在sln所属文件夹下的Hazel文件夹kind "SharedLib"--dll动态库language "C++"targetdir ("bin/" .. outputdir .. "/%{prj.name}") -- 输出目录objdir ("bin-int/" .. outputdir .. "/%{prj.name}")-- 中间目录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"}-- 如果是window系统filter "system:windows"cppdialect "C++17"-- On:代码生成的运行库选项是MTD,静态链接MSVCRT.lib库;-- Off:代码生成的运行库选项是MDD,动态链接MSVCRT.dll库;打包后的exe放到另一台电脑上若无这个dll会报错staticruntime "On"	systemversion "latest"	-- windowSDK版本-- 预处理器定义defines{"YT_PLATFORM_WINDOWS","YT_BUILD_DLL"}-- 编译好后移动Hazel.dll文件到Sandbox文件夹下postbuildcommands{("{COPY} %{cfg.buildtarget.relpath} ../bin/" .. outputdir .. "/Sandbox")}-- 不同配置下的预定义不同filter "configurations:Debug"defines "YT_DEBUG"symbols "On"filter "configurations:Release"defines "YT_RELEASE"optimize "On"filter "configurations:Dist"defines "YT_DIST"optimize "On"project "Sandbox"location "Sandbox"kind "ConsoleApp"language "C++"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"}-- 引用hazellinks{"YOTOEngine"}filter "system:windows"cppdialect "C++17"staticruntime "On"systemversion "latest"defines{"YT_PLATFORM_WINDOWS"}filter "configurations:Debug"defines "YT_DEBUG"symbols "On"filter "configurations:Release"defines "YT_RELEASE"optimize "On"filter "configurations:Dist"defines "YT_DIST"optimize "On"

把所有使用库文件的地方都换成#include"ytpch.h"即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/314684.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大二第17周总结——2023年的最后一天

本周&#xff0c;学校安排的是数据结构的程序设计&#xff0c;设计是挺好设计的&#xff0c;小半天搞完了&#xff0c;然后帮室友也搞了。内容在上一个博客。 学习上嘛~ 学了一下websocket,看了下微信小程序........ 今天早上做了一套小米的面试题&#xff0c;不做不知道&…

【数据库原理】(1)数据库技术的发展

数据与信息 数据&#xff1a;数据并非只是数字&#xff0c;像文字、符号、图像、影音等都属于数据的范畴。但一般会用数字来表述客观事物的数量、质量、关系等&#xff0c;便于更加直观的看待问题。 语义&#xff1a;数据还需要结合关联的语义解释才能够清晰的描述事物&#…

CMake入门教程【基础篇】CMake+vs2022+nmake构建项目

文章目录 1.vs编译器下载安装2.运行nmake测试3.CMake下载安装4.运行CMake测试5.使用CMakeNMake构建项目代码目录代码实现 6.运行项目 1.vs编译器下载安装 下载地址 :https://visualstudio.microsoft.com/zh-hans/vs/ 点击截图处下载 勾选红框的内容即可 安装 2.运行nmak…

【Matlab】LSTM长短期记忆神经网络时序预测算法(附代码)

资源下载&#xff1a; https://download.csdn.net/download/vvoennvv/88688439 一&#xff0c;概述 LSTM&#xff08;Long Short-Term Memory&#xff09;是一种常用的循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;结构&#xff0c;由于其对于…

【解决复杂链式任务打造全能助手】大模型思维链 CoT 应用:LangChain 大模型 结合 做 AutoGPT

大模型思维链 CoT 应用&#xff1a;langchain 大模型 结合 做 AutoGPT&#xff0c;解决复杂链式任务打造全能助手 思维链 CoTLangChain基础层&#xff1a;models、LLMs、index能力层&#xff1a;Chains、Memory、Tools应用层&#xff1a;文档问答、数据库问答、智能体Agents La…

航芯ACM32G103开发板评测 03 RT-Thread Nano移植 线程管理测试

航芯ACM32G103开发板评测 07 RT-Thread Nano移植 线程管理测试 1. 软硬件平台 ACM32G103 Board开发板MDK-ARM KeilRT-Thread Nano 源码 2. 物联网RTOS—RT-Thread ​ RT-Thread诞生于2006年&#xff0c;是一款以开源、中立、社区化发展起来的物联网操作系统。 RT-Thread主…

FL Studio Producer Edition 21.2.2中文版所有插件版及使用教程

FL Studio 21.2.2中文版惯称水果编曲, 是一个完整的电音软件音乐制作环境或数字音频工作站。是现在流行的数字音频工作站之一,包括撰写,整理,记录,编辑,电音,混音和掌握专业品质的音乐。 FL Studio Producer Edition 21.2.2.3914 所有插件版是一款功能强大的软件音乐制作环境或…

TF-IDF(Term Frequency-Inverse Document Frequency)算法 简介

TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09;是一种用于信息检索和文本挖掘的常用算法。它用于评估一个词对于一个文档集合中某个文档的重要性。 这个算法的基本思想是&#xff1a;如果一个词在一个文档中频繁出现&#xff0c;并且在整个文档集合…

rime中州韵 help lua Translator

lua 是 Rime中州韵/小狼毫输入法强大的武器&#xff0c;掌握如何在Rime中州韵/小狼毫中使用lua&#xff0c;你将体验到什么叫 随心所欲。 先看效果 在 rime中州韵 输入效果一览 中的 &#x1f447; help效果 一节中&#xff0c; 我们看到了在Rime中州韵/小狼毫输入法中输入 h…

项目 杂碎 知识点 汇总!!!

Vue !!! setup生命周期 使用 nextTick &#xff01;&#xff01;获取节点 onMounted中可以使用JS&#xff0c;获取节点&#xff0c;setup生命周期无法获取节点 vue实现文本粘贴复制 Vue遍历对象 1、使用v-for指令&#xff1a;可以直接遍历对象的键和值 2、使用 Object.keys…

您的项目应该选用哪一种编程语言?深入对比PHP与Python

在软件开发领域&#xff0c;PHP与Python之间正在进行一场战斗。它似乎永远不会结束。 开发一个成功的网站或应用程序首先要选择一种可靠的编程语言。 随着生产高性能、可扩展、可靠、安全和灵活的网络产品的激烈竞争&#xff0c;有必要选择一个明智的技术基础&#xff0c;包括…

1. Spring概述

概述 Spring 是一个开源框架Spring 为简化企业级开发而生&#xff0c;使用 Spring&#xff0c;JavaBean 就可以实现很多以前要靠 EJB 才能实现的功能。同样的功能&#xff0c;在 EJB 中要通过繁琐的配置和复杂的代码才能够实现&#xff0c;而在 Spring 中却非常的优雅和简洁。…