Aurora Engine 游戏引擎入门 07(OpenGL创建游戏窗体)

    科技2023-10-04  81


    #1 导入基于windows平台的GLFW=OpenGL Framwork #2 premake5.lua添加项目相关引用 #3 编写窗体公共头文件定义Window.h #4 编写游戏窗体类WindowsWindow #5 修改Application.cpp进行测试


    #1 导入第三方已经使用premake5封装好的GLFW库

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

    #2 premake5.lua修改

    -- lua 声明一个table IncludeDir = {} -- 给table赋值一个GLFW定义 IncludeDir["GLFW"] = "Aurora/vendor/GLFW/include" -- 当前的workspace需要导入第三方的项目 -- 因为第三方的项目也是premake5来配置的,所以可以直接导入 -- 见Aurora\Aurora\vendor\GLFW\premake5.lua include "Aurora/vendor/GLFW" -- 当前项目需要附加的包含库 includedirs { -- 包含的文件最好使用%{prj.name}相对路径 "%{prj.name}/src", "%{prj.name}/vendor/spdlog/include", "%{IncludeDir.GLFW}" } links { -- 引用GLFW库 "GLFW", "opengl32.lib" }
    // Window.h #pragma once #include "aopch.h" #include "Aurora/Core.h" #include "Aurora/Events/Event.h" namespace Aurora { // 定义window属性 struct WindowProps { std::string Title; unsigned int Width; unsigned int Height; WindowProps(const std::string& title = "Aurora Engine", unsigned int width = 1280, unsigned int height = 720) :Title(title), Width(width), Height(height) { } }; // 定义窗口基类 class AURORA_API Window { public: // 窗口事件,缩放,拉扯等,C++11新语法 using EventCallbackFn = std::function<void(Event&)>; virtual ~Window() {} // 当前制作的引擎是基于PC窗口来实现,最外层的是窗体,窗体update // -> 内容update -> 游戏 virtual void OnUpdate() = 0; // virtual + =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; // 这里定义一个静态的Create方法,参数为WindowProps,全部使用的默认数据 // 这个方法在WindowsWindow.cpp里面实现 static Window* Create(const WindowProps& prop = WindowProps()); }; }
    // WindowsWindow.h #pragma once #include "Aurora/Window.h" #include <GLFW/glfw3.h> namespace Aurora { // 游戏的窗口 class WindowsWindow : public Window { public: // const 方法里面不能修改props的数据 WindowsWindow(const WindowProps& props); virtual ~WindowsWindow(); // override 这个方法从父类重写,不加默认新定义的方法 void OnUpdate() override; // inline 编译期优化,减少栈内存开销,编译时候代码替换 // const 在方法的后面,这个方法里面的数据不能修改类的其他数据 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) override; bool IsVSync() const override; private: virtual void Init(const WindowProps& props); virtual void Shutdown(); private: // OpenGL 声明一个窗体 GLFWwindow* m_Window; struct WindowData { std::string Title; unsigned int Width, Height; bool VSync; EventCallbackFn EventCallback; }; WindowData m_Data; }; } // WindowsWindow.cpp #include "aopch.h" #include "WindowsWindow.h" namespace Aurora { static bool s_GLFWInitialized = false; // 游戏窗口的实现,'&'取之前定义的数据,别名 // step 1 Window* Window::Create(const WindowProps& props) { return new WindowsWindow(props); } // step 2 WindowsWindow::WindowsWindow(const WindowProps& props) { Init(props); } WindowsWindow::~WindowsWindow() { Shutdown(); } // step 3 void WindowsWindow::Init(const WindowProps& props) { m_Data.Title = props.Title; m_Data.Width = props.Width; m_Data.Height = props.Height; AO_CORE_INFO("Creating window {0} ({1}, {2})", props.Title, props.Width, props.Height); if (!s_GLFWInitialized) { int success = glfwInit(); AO_CORE_ASSERT(success, "Could not initialize GLFW!"); s_GLFWInitialized = true; } // std::string 转 c语言的字符串 char* 使用c_str() // nullptr C++11 指针关键字 m_Window = glfwCreateWindow((int)props.Width, (int)props.Height, m_Data.Title.c_str(), nullptr, nullptr); glfwMakeContextCurrent(m_Window); glfwSetWindowUserPointer(m_Window, &m_Data); SetVSync(true); } void WindowsWindow::Shutdown() { glfwDestroyWindow(m_Window); } // step 4 void WindowsWindow::OnUpdate() { glfwPollEvents(); glfwSwapBuffers(m_Window); } void WindowsWindow::SetVSync(bool enable) { if (enable) glfwSwapInterval(1); else glfwSwapInterval(0); m_Data.VSync = enable; } bool WindowsWindow::IsVSync() const { return m_Data.VSync; } }

    #5 修改测试

    // Application.h #pragma once #include "Core.h" #include "Events/Event.h" #include "Window.h" namespace Aurora { class AURORA_API Application { public: Application(); virtual ~Application(); void Run(); private: // 唯一指针对象,内存中唯一 // shared_ptr拥有自动计数引用的功能 std::unique_ptr<Window> m_Window; bool m_Running = true; }; // 第一次定义全局函数,表示我有这个函数 Application* CreateApplication(); } // Application.cpp #include "aopch.h" #include "Application.h" #include "Aurora/Events/ApplicationEvent.h" #include "Aurora/Log.h" #include "GLFW/glfw3.h" namespace Aurora { 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(); } } }

    更多修改的内容见Gitea


    效果展示,Thanks for watching!


    Processed: 0.012, SQL: 8