Hazel游戏引擎(011)窗口抽象和GLFW创建窗口

news2024/11/16 7:33:50

文中若有代码、术语等错误,欢迎指正

文章目录

  • 前言
  • 步骤
    • GIT添加GLFW子模块及编译
    • Window类
    • 其它修改
  • 效果
  • Bug记录

前言

  • 此节目的

    为了有窗口效果,但不想使用原生的window32写起,所以用glfw窗口库。

    也为了完成008计划事件系统的创建窗口部分

  • 图示

步骤

GIT添加GLFW子模块及编译

  • 添加glfw子模块

    git add submodule https://github.com/TheCherno/glfw Hazel/vendor/GLFW
    

  • 修改premake

    解决方案下的premake修改

    -- 包含相对解决方案的目录
    IncludeDir = {}
    IncludeDir["GLFW"] = "Hazel/vendor/GLFW/include"
    -- 这个include,相当于把glfw下的premake5.lua内容拷贝到这里
    include "Hazel/vendor/GLFW"
    project "Hazel"		--Hazel项目
    	location "Hazel"--在sln所属文件夹下的Hazel文件夹
    	kind "SharedLib"--dll动态库
    	-- 包含目录
    	includedirs{
    		"%{prj.name}/src",
    		"%{prj.name}/vendor/spdlog/include",
    		"%{IncludeDir.GLFW}"
    	}
    	-- Hazel链接glfw项目
    	links 
    	{ 
    		"GLFW",
    		"opengl32.lib"
    	}
    	filter "system:windows"
    		defines{
    			"HZ_PLATFORM_WINDOWS",
    			"HZ_ENABLE_ASSERTS"
    		}
    
  • 效果

    请添加图片描述

Window类

  • 目前类图

    请添加图片描述

    Application类可以调用创建窗口函数,而窗口类使用glfw库创建真正的窗口。

    窗口类检测glfw窗口的事件,并回调给Application的处理事件函数。

  • 代码

    window.h

    #pragma once
    #include "hzpch.h"
    #include "Hazel/Core.h"
    #include "Hazel/Events/Event.h"
    namespace Hazel {
    	struct WindowProps{// 窗口初始化设置的内容
    		std::string Title;
    		unsigned int Width;
    		unsigned int Height;
    		WindowProps(const std::string& title = "Hazel Engine",
    			unsigned int width = 1280,
    			unsigned int height = 720)
    			: Title(title), Width(width), Height(height){}
    	};
    	class HAZEL_API Window{
    	public:
    		using EventCallbackFn = std::function<void(Event&)>;
    		virtual ~Window() {}
    		virtual void OnUpdate() = 0;
    		virtual unsigned int GetWidth() const = 0;
    		virtual unsigned int GetHeight() const = 0;
    		// Window attributes
    		virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
    		virtual void SetVSync(bool enabled) = 0;
    		virtual bool IsVSync() const = 0;
            // 在Window父类声明创建函数
    		static Window* Create(const WindowProps& props = WindowProps());
    	};
    }
    

    WindowsWindow.h

    #pragma once
    #include "Hazel/Window.h"
    #include <GLFW/glfw3.h>
    namespace Hazel {
    	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; }
    		// 设置Application的回调函数
    		inline void SetEventCallback(const EventCallbackFn& callback) override { m_Data.EventCallback = callback; }
    		void SetVSync(bool enabled) override;
    		bool IsVSync() const override;
    	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;
    	};
    }
    

    WindowsWindow.cpp

    #include "hzpch.h"
    #include "WindowsWindow.h"
    
    namespace Hazel {
    	static bool s_GLFWInitialized = false;
        // 在WindowsWindow子类定义在Window父类声明的函数
    	Window* Window::Create(const WindowProps& props){
    		return new WindowsWindow(props);
    	}
    	WindowsWindow::WindowsWindow(const WindowProps& props){
    		Init(props);
    	}
    	void WindowsWindow::Init(const WindowProps& props){
    		m_Data.Title = props.Title;
    		m_Data.Width = props.Width;
    		m_Data.Height = props.Height;
    		HZ_CORE_INFO("Creating window {0} ({1}, {2})", props.Title, props.Width, props.Height);
    		if (!s_GLFWInitialized){
    			// TODO: glfwTerminate on system shutdown
    			int success = glfwInit();
    			HZ_CORE_ASSERT(success, "Could not intialize GLFW!");// 是Core.h里面预处理器指令定义了HZ_CORE_ASSERT
    			s_GLFWInitialized = true;
    		}
    		// 创建窗口//
    		m_Window = glfwCreateWindow((int)props.Width, (int)props.Height, m_Data.Title.c_str(), nullptr, nullptr);
    		// 设置glfw当前的上下文
    		glfwMakeContextCurrent(m_Window);
    		/*
    			设置窗口关联的用户数据指针。这里GLFW仅做存储,不做任何的特殊处理和应用。
    			window表示操作的窗口句柄。
    			pointer表示用户数据指针。
    		*/
    		glfwSetWindowUserPointer(m_Window, &m_Data);
    		SetVSync(true);
    	}
    	void WindowsWindow::OnUpdate(){
    		glfwPollEvents();			// 轮询事件	
    		glfwSwapBuffers(m_Window);	// 交换缓冲
    	}
    	.....
    }
    
  • HZ_CORE_ASSERT

    在Core.h中

    #ifdef HZ_ENABLE_ASSERTS
    #define HZ_ASSERT(x, ...) { if(!(x)) { HZ_ERROR("Assertion Failed: {0}", __VA_ARGS__); __debugbreak(); } }
    #define HZ_CORE_ASSERT(x, ...) { if(!(x)) { HZ_CORE_ERROR("Assertion Failed: {0}", __VA_ARGS__); __debugbreak(); } }
    #else
    #define HZ_ASSERT(x, ...)
    #define HZ_CORE_ASSERT(x, ...)
    #endif
    
    HZ_CORE_ASSERT(success, "Could not intialize GLFW!");
    // 转换成
    { if(!(success)) { ::Hazel::Log::GetCoreLogger()->error("Assertion Failed: {0}", "Could not intialize GLFW!"); __debugbreak(); } };
    

    可见:…当做参数包被__VA_ARGS__展开;__debugbreak();是在debug模式下的断点

其它修改

  • Application

    #pragma once
    #include "Core.h"
    #include "Events/Event.h"
    #include "Window.h"
    namespace Hazel {
    	class HAZEL_API Application{
    	public:
    		Application();
    		virtual ~Application();
    		void Run();
    	private:
    		std::unique_ptr<Window> m_Window;
    		bool m_Running = true;
    	};
    	Application* CreateApplication();
    }
    
    #include "hzpch.h"
    #include "Application.h"
    #include "Hazel/Events/ApplicationEvent.h" // 包含事件
    #include "Hazel/Log.h"
    #include <GLFW/glfw3.h>
    namespace Hazel {
    	Application::Application(){
    		m_Window = std::unique_ptr<Window>(Window::Create()); // 创建窗口
    	}
    	Application::~Application() {}
    	void Application::Run(){
    		while (m_Running){
                // 清屏
    			glClearColor(1, 0, 1, 1);
    			glClear(GL_COLOR_BUFFER_BIT);
    			m_Window->OnUpdate();	// 更新glfw
    		}
    	}
    }
    

效果

请添加图片描述

Bug记录

  • glfw找不到函数定义

  • 解决方法一

    修改GLFW的premake

    filter "configurations:Debug"
        defines "HZ_DEBUG"
        buildoptions "/MTd"
        symbols "On"
    
        filter "configurations:Release"
        defines "HZ_RELEASE"
        buildoptions "/MT"
        symbols "On"
    
        filter "configurations:Dist"
        defines "HZ_DIST"
        buildoptions "/MT"
        symbols "On"
    

    使GLFW项目的运行库,只能是MT或者MTD不能是MD或者MDD

    重新生成项目解决方案才行

    请添加图片描述

    关于运行库选项:

    // 运行库选项是MTD,静态链接MSVCRT.lib库;
    // 运行库选项是MDD,动态链接MSVCRT.dll库;打包后的exe放到另一台电脑上若无这个dll会报错
    
    • 为什么GLFW要改为MT或者MTD才行

      Hazel是MTD静态链接MSVCRT.dll库、而引用GLFW项目却是MDD动态链接MSVCRT.dll库,可能不兼容。如下是Hazel项目的运行库选项

  • 解决方法二

    由于Hazel默认是MTD,GLFW默认是MDD,那么就将Hazel用premake改为MDD动态链接MSVCRT.dll库,符合Hazel作为dll库(SharedLib)的方式

    更改解决方案下的premake5.lua文件

    project "Hazel"
        ......
       filter "configurations:Debug"
    		defines "HZ_DEBUG"
    		buildoptions "/MDd"
    		symbols "On"
    
    	filter "configurations:Release"
    		defines "HZ_RELEASE"
    		buildoptions "/MD"
    		optimize "On"
    
    	filter "configurations:Dist"
    		defines "HZ_DIST"
    		buildoptions "/MD"
    		optimize "On"
    
    project "Sandbox"
    	......
    	filter "configurations:Debug"
    		defines "HZ_DEBUG"
    		buildoptions "/MDd"
    		symbols "On"
    
    	filter "configurations:Release"
    		defines "HZ_RELEASE"
    		buildoptions "/MD"
    		optimize "On"
    
    	filter "configurations:Dist"
    		defines "HZ_DIST"
    		buildoptions "/MD"
    		optimize "On"
    

    重新编译后,Hazel的运行库依旧是MTd,但是添加了命令行/MDd 会覆盖/MTd

    • 后面017节才发现为什么Hazel依旧为MTD,需要添加了命令行/MDd 才会覆盖/MTd

      由于premake设置了staticruntime为on

      -- On:代码生成的运行库选项是MTD,静态链接MSVCRT.lib库;
      -- Off:代码生成的运行库选项是MDD,动态链接MSVCRT.dll库;打包后的exe放到另一台电脑上若无这个dll会报错
      staticruntime "On"	
      

      只需staticruntime 为off即可

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI数据标注工具Doccano

Doccano是一款开源的标注工具&#xff0c;用于自然语言处理和机器学习任务。它提供了用户友好的界面&#xff0c;使用户能够轻松地标注文本、序列标注、文本分类和文本配对等任务。doccano支持多种标注格式&#xff0c;并且可以方便地与其他机器学习工具集成。它的简单性和灵活…

基于 MySQL 事务、隔离级别及 MVCC 机制详细剖析

前言事务特性事务并发引发的问题脏读不可重复读幻读 隔离级别如何更改事务隔离级别 事务基本操作MVCC版本链ReadViewREAD COMMITTED脏读问题不可重复读问题 REPEATABLE READ不可重复读问题幻读问题 小结 总结 前言 MySQL 事务是比较重要且核心的一部分&#xff0c;在操作数据库…

碳排放预测模型 | Python实现基于Prophet网络的碳排放预测模型(预测未来发展趋势)

文章目录 效果一览文章概述研究内容环境准备源码设计学习总结参考资料效果一览 文章概述 碳排放预测模型 | Python实现基于Prophet网络的碳排放预测模型(预测未来发展趋势) 研究内容 这是数据集的链接:https://github.com/owid/co2-data/blob/master/owid-co2-data.csv 使用…

读书:《指数型组织》

《指数型组织》是Salim Ismail在2015年发表的一本著作&#xff0c;它探讨了在今天这个信息时代&#xff0c;一些组织为何能够在极短的时间内取得显著的成绩。他发现这些成功的组织都有一些共享的属性&#xff0c;这些属性使得他们能够比传统组织更快、更有效地扩展业务。他把这…

LiangGaRy-学习笔记-Day21

1、LVM介绍 1.1、LVM是什么 对于生产环境下的服务器来说&#xff0c;如果存储数据的分区磁盘空间不足&#xff0c;应该如何处理&#xff1f; 添加一块硬盘–>可以满足需要再添加一块硬盘也可以满足需求&#xff1b;问题就是拷贝的速度慢&#xff1b; 这里就引入一个技术…

Kubernetes小感

从容器到容器云&#xff0c;谈谈 Kubernetes 的本质&#xff1a; 一个“容器”&#xff0c;实际上是一个由 Linux Namespace、Linux Cgroups 和 rootfs 三种技术构建出来的进程的隔离环境。 作为一名开发者&#xff0c;我并不关心容器运行时的差异。因为&#xff0c;在整个“…

【深入浅出Docker原理及实战】「原理实战体系」零基础+全方位带你学习探索Docker容器开发实战指南(核心组件说明)

零基础全方位带你学习探索Docker容器开发实战指南&#xff08;核心组件说明&#xff09; 核心组件镜像定义概念与容器的关联文件系统root文件系统 bootfs启动文件系统分层存储分层覆盖处理模式镜像的写时复制机制 容器容器进程隔离性容器进程隔离性容器存储层数据卷绑定镜像和容…

Spring6-01

Spring6启示录 OCP开闭原则 什么是开闭原则&#xff1f; 在软件开发过程中应当对扩展开放&#xff0c;对修改关闭。也就是说如果在进行功能扩展的时候&#xff0c;添加额外的类是没有问题的&#xff0c;但因为功能扩展而修改之前运行正常的程序&#xff0c;这是不被允许的。因…

Elasticsearch:二进制数据类型 - binary field

二进制&#xff08;binary&#xff09;类型接受二进制值作为 Base64 编码字符串。 该字段默认不存储且不可搜索。Base64 编码的二进制值不得嵌入换行符 \n。 这听起来像是&#xff0c;将二进制对象存储在 Elasticsearch 中的单个字段中 PUT my-index-000001 {"mappings&…

Jupyter Notebook 插件和其他小技巧

好用的插件 安装插件代码自动补全变量查看高亮代码折叠显示行号执行时间多行打印规范化代码模块快速获取jupyter notebook中安装包快捷键 安装插件 1.pip直接安装 pip install jupyter_contrib_nbextensions jupyter contrib nbextension install --user2.方法1不成功就用ano…

STM32踩坑:UCOSIII下串口中断服务中使用OSIntEnter函数使程序卡死解决方案

UCOSIII下串口中断服务中使用OSIntEnter函数使程序卡死解决方案 本文侧重于 STM32 标准库&#xff0c;HAL 库可以借鉴&#xff0c;因为该项目是基于标准库做的&#xff08;因为涉及到保密&#xff0c;这里我就张贴源码进行描述了&#xff09;。 因项目需求&#xff0c;需要使用…

广域网技术——ppp,pppoe

目录 PPP协议概述 PPP协议原理 PPP协议三大组件&#xff1a; PPP链路建立流程 PPP连接建立接口状态&#xff1a; LCP协议报文格式 PPP协议报文格式&#xff1a; 1&#xff0c;链路层建立连接过程 LCP协商过程-正常协商 LCP协商-参数不一致 LCP协商-参数不识别 2&#xf…

JVM调优工具及其相关配置

1.查看JVM配置及其应用使用情况 1.1在启动应用中进行测试 1jsp命令的使用 1.jsp查看当前启动的程序 2.查看相关堆中对象的使用情况 jmap -histo 16700>./log.txtnum&#xff1a;序号instances&#xff1a;实例数量bytes&#xff1a;占用空间大小class name&#xff1a;类…

记录 | 将Word生成的静态网页部署到Github Page

任务描述 使用Word, 可以直接获得 一个静态的网页XXX.html和对应的文件夹XXX.files问题&#xff1a;如何将它托管在github上&#xff1f; 步骤 使用github pages进行托管和发布 步骤1&#xff1a;创建仓库 创建一个新的GitHub仓库&#xff1a;访问 https://github.com 并使用…

matplotlib模块

目录 ❤ 条形图 ❤ 直方图 ❤ 折线图 ❤ 散点图直线图 ❤ 饼图 ❤ 箱型图 ❤ plot函数参数 ❤ 图像标注参数 ❤ Matplolib应用 python从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article/details/129328397?spm1001.2014.3001.5502 …

物联网Lora模块从入门到精通(九)Flash的读取与存储--结题

一、前言 这将是"物联网Lora模块从入门到精通"系列的最后一篇文章&#xff0c;相信各位同僚通过前面八篇文章的分享已经极好的掌握了Lora模块的编程&#xff0c;本文的Flash的读取与存储将是Lora模块开发的最后一块&#xff0c;感谢大家的陪伴与支持&#xff01; 希望…

SpringCloud(五)

文章目录 负载均衡策略自定义负载均衡策略饥饿加载 负载均衡策略 负载均衡的规则都定义在IRule接口中&#xff0c;而IRule有很多不同的实现类&#xff1a; 不同规则的含义如下&#xff1a; 内置负载均衡规则类规则描述RoundRobinRule简单轮询服务列表来选择服务器。它是Ribb…

Redis高级特性之慢查询的基本概念

慢查询概念 作为存储系统&#xff0c;Mysql等等&#xff0c;提供慢查询日志帮助开发和运维人员定位系统存在的满操作。慢查询日志就是系统在命令执行前后计算每条命令的执行时间&#xff0c;当超过预期阈值&#xff0c;便会将这条命令的相关信息。例如发生的时间&#xff0c;耗…

【零基础学JS - 10 】javaScript 中的比较和逻辑运算符

&#x1f468;‍&#x1f4bb; 作者简介&#xff1a;程序员半夏 , 一名全栈程序员&#xff0c;擅长使用各种编程语言和框架&#xff0c;如JavaScript、React、Node.js、Java、Python、Django、MySQL等.专注于大前端与后端的硬核干货分享,同时是一个随缘更新的UP主. 你可以在各个…

mysql8安装【含mysql安装包】

mysql8安装【含mysql安装包】 安装包等资源安装流程 安装包等资源 安装包下载地址【CSDN免费】&#xff1a;https://download.csdn.net/download/qq_47168235/87881866 如果上面的个下载不了&#xff0c;就通过百度网盘吧 百度网盘连接&#xff1a;https://pan.baidu.com/s/1G…