文中若有代碼、術(shù)語(yǔ)等錯(cuò)誤,歡迎指正
前言
-
此節(jié)目的
為了有窗口效果,但不想使用原生的window32寫起,所以用glfw窗口庫(kù)。
也為了完成008計(jì)劃事件系統(tǒng)的創(chuàng)建窗口部分
-
圖示
步驟
GIT添加GLFW子模塊及編譯
-
添加glfw子模塊
git add submodule https://github.com/TheCherno/glfw Hazel/vendor/GLFW
-
修改premake
解決方案下的premake修改
-- 包含相對(duì)解決方案的目錄 IncludeDir = {} IncludeDir["GLFW"] = "Hazel/vendor/GLFW/include" -- 這個(gè)include,相當(dāng)于把glfw下的premake5.lua內(nèi)容拷貝到這里 include "Hazel/vendor/GLFW" project "Hazel" --Hazel項(xiàng)目 location "Hazel"--在sln所屬文件夾下的Hazel文件夾 kind "SharedLib"--dll動(dòng)態(tài)庫(kù) -- 包含目錄 includedirs{ "%{prj.name}/src", "%{prj.name}/vendor/spdlog/include", "%{IncludeDir.GLFW}" } -- Hazel鏈接glfw項(xiàng)目 links { "GLFW", "opengl32.lib" } filter "system:windows" defines{ "HZ_PLATFORM_WINDOWS", "HZ_ENABLE_ASSERTS" }
-
效果
Window類
-
目前類圖
Application類可以調(diào)用創(chuàng)建窗口函數(shù),而窗口類使用glfw庫(kù)創(chuàng)建真正的窗口。
窗口類檢測(cè)glfw窗口的事件,并回調(diào)給Application的處理事件函數(shù)。
-
代碼
window.h
#pragma once #include "hzpch.h" #include "Hazel/Core.h" #include "Hazel/Events/Event.h" namespace Hazel { struct WindowProps{// 窗口初始化設(shè)置的內(nèi)容 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父類聲明創(chuàng)建函數(shù) 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; } // 設(shè)置Application的回調(diào)函數(shù) 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父類聲明的函數(shù) 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里面預(yù)處理器指令定義了HZ_CORE_ASSERT s_GLFWInitialized = true; } // 創(chuàng)建窗口// m_Window = glfwCreateWindow((int)props.Width, (int)props.Height, m_Data.Title.c_str(), nullptr, nullptr); // 設(shè)置glfw當(dāng)前的上下文 glfwMakeContextCurrent(m_Window); /* 設(shè)置窗口關(guān)聯(lián)的用戶數(shù)據(jù)指針。這里GLFW僅做存儲(chǔ),不做任何的特殊處理和應(yīng)用。 window表示操作的窗口句柄。 pointer表示用戶數(shù)據(jù)指針。 */ 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!"); // 轉(zhuǎn)換成 { if(!(success)) { ::Hazel::Log::GetCoreLogger()->error("Assertion Failed: {0}", "Could not intialize GLFW!"); __debugbreak(); } };
可見:…當(dāng)做參數(shù)包被__VA_ARGS__展開;__debugbreak();是在debug模式下的斷點(diǎn)
其它修改
-
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()); // 創(chuàng)建窗口 } Application::~Application() {} void Application::Run(){ while (m_Running){ // 清屏 glClearColor(1, 0, 1, 1); glClear(GL_COLOR_BUFFER_BIT); m_Window->OnUpdate(); // 更新glfw } } }
效果
Bug記錄
-
glfw找不到函數(shù)定義
-
解決方法一
修改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項(xiàng)目的運(yùn)行庫(kù),只能是MT或者MTD,不能是MD或者M(jìn)DD
重新生成項(xiàng)目解決方案才行
關(guān)于運(yùn)行庫(kù)選項(xiàng):
// 運(yùn)行庫(kù)選項(xiàng)是MTD,靜態(tài)鏈接MSVCRT.lib庫(kù); // 運(yùn)行庫(kù)選項(xiàng)是MDD,動(dòng)態(tài)鏈接MSVCRT.dll庫(kù);打包后的exe放到另一臺(tái)電腦上若無(wú)這個(gè)dll會(huì)報(bào)錯(cuò)
-
為什么GLFW要改為MT或者M(jìn)TD才行
Hazel是MTD靜態(tài)鏈接MSVCRT.dll庫(kù)、而引用GLFW項(xiàng)目卻是MDD動(dòng)態(tài)鏈接MSVCRT.dll庫(kù),可能不兼容。如下是Hazel項(xiàng)目的運(yùn)行庫(kù)選項(xiàng)
-
-
解決方法二
由于Hazel默認(rèn)是MTD,GLFW默認(rèn)是MDD,那么就將Hazel用premake改為MDD動(dòng)態(tài)鏈接MSVCRT.dll庫(kù),符合Hazel作為dll庫(kù)(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的運(yùn)行庫(kù)依舊是MTd,但是添加了命令行/MDd 會(huì)覆蓋/MTd
-
后面017節(jié)才發(fā)現(xiàn)為什么Hazel依舊為MTD,需要添加了命令行/MDd 才會(huì)覆蓋/MTd
由于premake設(shè)置了staticruntime為on文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-636320.html
-- On:代碼生成的運(yùn)行庫(kù)選項(xiàng)是MTD,靜態(tài)鏈接MSVCRT.lib庫(kù); -- Off:代碼生成的運(yùn)行庫(kù)選項(xiàng)是MDD,動(dòng)態(tài)鏈接MSVCRT.dll庫(kù);打包后的exe放到另一臺(tái)電腦上若無(wú)這個(gè)dll會(huì)報(bào)錯(cuò) staticruntime "On"
只需staticruntime 為off即可文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-636320.html
-
到了這里,關(guān)于Hazel游戲引擎(011)窗口抽象和GLFW創(chuàng)建窗口的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!