当前位置: 代码迷 >> 综合 >> Aurora Engine 游戏引擎入门 08(为游戏添加层 Layer)
  详细解决方案

Aurora Engine 游戏引擎入门 08(为游戏添加层 Layer)

热度:17   发布时间:2024-03-09 13:23:02.0

#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 项目地址


  相关解决方案