从零开发游戏引擎系列(七)窗口
2021-02-24 本文已影响0人
zaintan
该系列教程源自youtube的cherno的视频-GAME ENGINE series!
视频地址: https://www.youtube.com/watch?v=vtWdgtMo1T4
引擎源代码地址: https://github.com/TheCherno/Hazel
将使用第三方库glfw: https://github.com/glfw/glfw
当前cmd目录下E:\GitResp\GameEngine\Hazel 执行
git submodule add https://github.com/glfw/glfw Hazel/vendor/glfw
premake5.lua 中projectHazel增加链接库配置
links
{
"glfw",
"opengl32.lib"
}
includedirs增加glfw的头文件包含路径
includedirs
{
"%{prj.name}/src",
"%{prj.name}/vendor/spdlog/include"
"%{prj.name}/vendor/glfw/include"
}
新增配置工程Hazel/vendor/glfw/premake5.lua
project "glfw"
kind "StaticLib"
language "C"
targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}")
files
{
"include/GLFW/glfw3.h",
"include/GLFW/glfw3native.h",
"src/glfw_config.h",
"src/context.c",
"src/init.c",
"src/input.c",
"src/monitor.c",
"src/vulkan.c",
"src/window.c"
}
filter "system:linux"
pic "On"
systemversion "latest"
staticruntime "On"
files
{
"src/x11_init.c",
"src/x11_monitor.c",
"src/x11_window.c",
"src/xkb_unicode.c",
"src/posix_time.c",
"src/posix_thread.c",
"src/glx_context.c",
"src/egl_context.c",
"src/osmesa_context.c",
"src/linux_joystick.c"
}
defines
{
"_GLFW_X11"
}
filter "system:windows"
systemversion "latest"
staticruntime "On"
files
{
"src/win32_init.c",
"src/win32_joystick.c",
"src/win32_monitor.c",
"src/win32_time.c",
"src/win32_thread.c",
"src/win32_window.c",
"src/wgl_context.c",
"src/egl_context.c",
"src/osmesa_context.c"
}
defines
{
"_GLFW_WIN32",
"_CRT_SECURE_NO_WARNINGS"
}
filter "configurations:Debug"
runtime "Debug"
symbols "on"
filter "configurations:Release"
runtime "Release"
optimize "on"
Hazel/src/hzpch.h 增加
#include "Hazel/Log.h"
Hazel/src/Hazel/Core.h 增加 自定义assert宏
#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
新增文件Hazel/src/Hazel/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)
{
}
};
// Interface representing a desktop system based Window
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;
static Window* Create(const WindowProps& props = WindowProps());
};
}
实现windows平台的窗口类:
Hazel/src/Platform/Windows/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; }
// Window attributes
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;
};
}
Hazel/src/Platform/Windows/WindowsWindow.cpp
#include "hzpch.h"
#include "WindowsWindow.h"
namespace Hazel {
static bool s_GLFWInitialized = false;
Window* Window::Create(const WindowProps& props)
{
return new WindowsWindow(props);
}
WindowsWindow::WindowsWindow(const WindowProps& props)
{
Init(props);
}
WindowsWindow::~WindowsWindow()
{
Shutdown();
}
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!");
s_GLFWInitialized = true;
}
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);
}
void WindowsWindow::OnUpdate()
{
glfwPollEvents();
glfwSwapBuffers(m_Window);
}
void WindowsWindow::SetVSync(bool enabled)
{
if (enabled)
glfwSwapInterval(1);
else
glfwSwapInterval(0);
m_Data.VSync = enabled;
}
bool WindowsWindow::IsVSync() const
{
return m_Data.VSync;
}
}
在Application类中 创建窗口,分发事件:
Hazel/src/Hazel/Application.h
#include "Window.h"
...
private:
std::unique_ptr<Window> m_Window;
bool m_Running = true;
Hazel/src/Hazel/Application.cpp
#include <GLFW/glfw3.h>
...
Application::Application()
{
m_Window = std::unique_ptr<Window>(Window::Create());
}
...
void Application::Run()
{
while (m_Running)
{
glClearColor(1, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
m_Window->OnUpdate();
}
}