#1 为什么要有层的概念
#2 编写层级类和管理类
#3 处理OpenGL回调事件
#4 premake5开启多线程支持
#5 编写测试实例
#1 为什么要有层的概念
Layer 可处理显示,也可以处理事件;
在一个游戏中,层级可以用于显示不同的内容,不同的层级可以接收独立的事件
// Layer.h
#pragma once
#include "Aurora/Core.h"
#include "Aurora/Events/Event.h"namespace Aurora {
/// <summary>/// Layer 可处理显示,也可以处理事件;/// 在一个游戏中,层级可以用于显示不同的内容,不同的层级可以接收独立的事件/// </summary>class AURORA_API Layer{
public:// 当前层的名称Layer(const std::string& name = "Layer");virtual ~Layer();// 当层被附件到的时候virtual void OnAttach() {
}// 当层被取消的时候virtual void OnDetach() {
}// updatevirtual void OnUpdate() {
}// 当前层有事件的时候virtual void OnEvent(Event& event) {
}// 当前层的名字inline const std::string& GetName() const {
return m_DebugName; }protected:std::string m_DebugName;};
}
// Layer.cpp
#include "aopch.h"
#include "Layer.h"namespace Aurora {
Layer::Layer(const std::string& debugName) : m_DebugName(debugName){
}Layer::~Layer(){
}
}
// LayerStack.h
#pragma once#include "Aurora/Core.h"
#include "Layer.h"namespace Aurora {
/// <summary>/// 用于处理层的管理关系/// </summary>class AURORA_API LayerStack{
public:LayerStack();~LayerStack();/// <summary>/// 从列表的第一个元素添加一个层级/// </summary>/// <param name="layer"></param>void PushLayer(Layer* layer);/// <summary>/// 添加一个层到列表/// </summary>/// <param name="overlay"></param>void PushOverlay(Layer* overlay);/// <summary>/// 将最外的层取出来/// </summary>/// <param name="layer"></param>void PopLayer(Layer* layer);/// <summary>/// 从列表中取出一个层/// </summary>/// <param name="overlay"></param>void PopOverlay(Layer* overlay);/// <summary>/// 开始迭代器/// </summary>/// <returns></returns>std::vector<Layer*>::iterator begin() {
return m_Layers.begin(); }std::vector<Layer*>::iterator end() {
return m_Layers.end(); }private:/// <summary>/// 所有的层列表/// </summary>std::vector<Layer*> m_Layers;std::vector<Layer*>::iterator m_LayerInsert;};
}
#include "aopch.h"
#include "LayerStack.h"namespace Aurora {
LayerStack::LayerStack(){
m_LayerInsert = m_Layers.begin();}LayerStack::~LayerStack(){
for (Layer* layer : m_Layers) delete layer;}// 在指定m_LayerInsert处添加一个数据// emplace 不会产生临时数据void LayerStack::PushLayer(Layer* layer){
m_LayerInsert = m_Layers.emplace(m_LayerInsert, layer);}void LayerStack::PushOverlay(Layer* overlay){
m_Layers.emplace_back(overlay);}void LayerStack::PopLayer(Layer* layer){
// 销毁一个层,操作迭代器,优化效率auto it = std::find(m_Layers.begin(), m_Layers.end(), layer);if (it != m_Layers.end()) {
m_Layers.erase(it);m_LayerInsert--;}}void LayerStack::PopOverlay(Layer* overlay){
auto it = std::find(m_Layers.begin(), m_Layers.end(), overlay);if (it != m_Layers.end()) m_Layers.erase(it);}
}
#3 处理OpenGL回调事件
// WindowsWindow.cpp
#include "aopch.h"
#include "WindowsWindow.h"#include "Aurora/Events/ApplicationEvent.h"
#include "Aurora/Events/MouseEvent.h"
#include "Aurora/Events/KeyEvent.h"namespace Aurora {
static bool s_GLFWInitialized = false;static void GLFWErrorCallback(int error, const char* description){
AO_CORE_ERROR("GLFW Error ({0}): {1}", error, description);}// 游戏窗口的实现,'&'取之前定义的数据,别名// step 1Window* Window::Create(const WindowProps& props){
return new WindowsWindow(props);}// step 2WindowsWindow::WindowsWindow(const WindowProps& props){
Init(props);}WindowsWindow::~WindowsWindow() {
Shutdown();}// step 3void 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!");glfwSetErrorCallback(GLFWErrorCallback);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);// 注册OpenGL回调// 注册窗口缩放回调事件,[](){} C++11 的lambda表达式glfwSetWindowSizeCallback(m_Window, [](GLFWwindow* window, int width, int height){
WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);data.Width = width;data.Height = height;WindowResizeEvent event(width, height);data.EventCallback(event);});// 注册窗口关闭回调事件glfwSetWindowCloseCallback(m_Window, [](GLFWwindow* window){
WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);WindowCloseEvent event;data.EventCallback(event);});// 注册键盘按键回调事件glfwSetKeyCallback(m_Window, [](GLFWwindow* window, int key, int scancode, int action, int mods){
WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);switch (action){
case GLFW_PRESS:{
KeyPressedEvent event(key, 0);data.EventCallback(event);break;}case GLFW_RELEASE:{
KeyReleasedEvent event(key);data.EventCallback(event);break;}case GLFW_REPEAT:{
KeyPressedEvent event(key, 1);data.EventCallback(event);break;}}});// 注册鼠标按键回调事件glfwSetMouseButtonCallback(m_Window, [](GLFWwindow* window, int button, int action, int mods){
WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);switch (action){
case GLFW_PRESS:{
MouseButtonPressedEvent event(button);data.EventCallback(event);break;}case GLFW_RELEASE:{
MouseButtonReleasedEvent event(button);data.EventCallback(event);break;}}});// 注册鼠标滚轮回调事件glfwSetScrollCallback(m_Window, [](GLFWwindow* window, double xOffset, double yOffset){
WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);MouseScrolledEvent event((float)xOffset, (float)yOffset);data.EventCallback(event);});// 注册鼠标位置回调事件glfwSetCursorPosCallback(m_Window, [](GLFWwindow* window, double xPos, double yPos){
WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);MouseMovedEvent event((float)xPos, (float)yPos);data.EventCallback(event);});}void WindowsWindow::Shutdown() {
glfwDestroyWindow(m_Window);}// step 4void 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;}
}
#4 premake5开启多线程支持
filter "configurations:Debug" -- 配置Debug的概述defines "AO_DEBUG" -- 添加Debug的预编译器定义buildoptions "/MDd" -- 开始多线程支持调试symbols "On" -- 设置此宏有效filter "configurations:Release"defines "AO_RELEASE"buildoptions "/MD"optimize "On"filter "configurations:Dist"defines "AO_DIST"buildoptions "/MDd"optimize "On"
#5 编写测试实例
// SandboxApp.cpp
// 附加的包含目录只会对已经设置的目录当前支持
#include <Aurora.h>using namespace Aurora;class ExampleLayer : public Aurora::Layer
{
public:ExampleLayer() : Layer("Example"){
}void OnUpdate() override{
AO_INFO("ExampleLayer::Update");}void OnEvent(Event& event) override{
AO_TRACE("{0}", event);}};class Sandbox : public Application
{
public:Sandbox(){
PushLayer(new ExampleLayer());}~Sandbox(){
}
};Application* Aurora::CreateApplication()
{
AO_CORE_INFO("CREATE");return new Sandbox();
}
Gitea 项目地址