Hazel游戏引擎(013)Layers游戏的层级

这篇具有很好参考价值的文章主要介绍了Hazel游戏引擎(013)Layers游戏的层级。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

文中若有代码、术语等错误,欢迎指正

前言

  • 此节目的

    • 为完成008事件系统设计的第四步,将事件从Application传递分发给Layer层。

      Hazel游戏引擎(013)Layers游戏的层级,Hazel游戏引擎,游戏引擎,游戏,ui,glfw,软件工程

    • 使引擎事件系统模块完整

  • Layer的理解

    想象同Ps中一张图有多个层级,可以在层级上绘制图画

  • Layer的设计

    • 数据结构:vector

    • 渲染顺序

      从前往后渲染各个层的图像,这样后面渲染的会覆盖前面渲染的图像,在屏幕的最顶层。

    • 处理事件顺序

      从后往前依次处理事件,当一个事件被一个层处理完不会传递给前一个层,结合渲染顺序,这样在屏幕最顶层的(也就是在vector最后的layer)图像最先处理事件。

    • 例子解释

      比如常见的3D游戏有UI。

      渲染顺序:将3D图形先渲染,再渲染2DUI,这样屏幕上2DUI永远在3D图形上方,显示正确;

      事件顺序:点击屏幕的图形,应该是2DUI最先处理,如果是相应UI事件,处理完后不传递给前一个3D层,若不是自己的UI事件,才传递给前一个3D层。

    Hazel游戏引擎(013)Layers游戏的层级,Hazel游戏引擎,游戏引擎,游戏,ui,glfw,软件工程

增加Layer后的主要类图

Hazel游戏引擎(013)Layers游戏的层级,Hazel游戏引擎,游戏引擎,游戏,ui,glfw,软件工程

注意区分LayerStack、Layer以及ExampleLayer

  • LayerStack

    管理Layer层的类

  • Layer

    所有层的父类,定义了虚函数

  • Examplayer

    真正需要更新和处理事件的层,被添加到LayerStack的vector中

项目相关

代码

  • Layer

    #pragma once
    #include "Hazel/Core.h"
    #include "Hazel/Events/Event.h"
    namespace Hazel {
    	class HAZEL_API Layer
    	{
    	public:
    		Layer(const std::string& name = "Layer");
    		virtual ~Layer();
    		virtual void OnAttach() {} // 应用添加此层执行
    		virtual void OnDetach() {} // 应用分离此层执行
    		virtual void OnUpdate() {} // 每层更新
    		virtual void OnEvent(Event& event) {}// 每层处理事件
    		inline const std::string& GetName() const { return m_DebugName; }
    	protected:
    		std::string m_DebugName;
    	};
    }
    
  • LayerStack

    #pragma once
    namespace Hazel {
    	class HAZEL_API LayerStack{
    	public:
    		LayerStack();
    		~LayerStack();
    		void PushLayer(Layer* layer);	// vector在头部添加一个层
    		void PushOverlay(Layer* overlay);// 在vector末尾添加一个覆盖层,在屏幕的最上方的层
    		void PopLayer(Layer* layer);	// vector弹出指定层
    		void PopOverlay(Layer* overlay);// vector弹出覆盖层
    		std::vector<Layer*>::iterator begin() { return m_Layers.begin(); }
    		std::vector<Layer*>::iterator end() { return m_Layers.end(); }
    	private:
    		std::vector<Layer*> m_Layers;
    		std::vector<Layer*>::iterator m_LayerInsert;
    	};
    }
    
    namespace Hazel {
    	LayerStack::LayerStack(){
    		m_LayerInsert = m_Layers.begin();
    	}
    	LayerStack::~LayerStack(){
    		for (Layer* layer : m_Layers)
    			delete layer;
    	}
    	void LayerStack::PushLayer(Layer* layer){
    		// emplace在vector容器指定位置之前插入一个新的元素。返回插入元素的位置
    		// 插入 1 2 3,vector是 3 2 1
    		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--;	// 指向Begin
    		}
    	}
    	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);
    	}
    }
    
  • SandboxApp

    class ExampleLayer : public Hazel::Layer{
    public:
    	ExampleLayer()
    		: Layer("Example"){}
    	void OnUpdate() override{
    		HZ_INFO("ExampleLayer::Update");	// 最终会被输出
    	}
    	void OnEvent(Hazel::Event& event) override{
    		HZ_TRACE("{0}", event);	// 最终会被输出
    	}
    };
    class Sandbox : public Hazel::Application{
    public:
    	Sandbox(){
    		PushLayer(new ExampleLayer());
    	}
    	~Sandbox(){}
    };
    
  • Application

    void Application::PushLayer(Layer* layer){
        m_LayerStack.PushLayer(layer);
    }
    
    void Application::PushOverlay(Layer* layer){
        m_LayerStack.PushOverlay(layer);
    }
    // 回调glfw窗口事件的函数
    void Application::OnEvent(Event& e){
        // 4.用事件调度器,拦截自己层想要拦截的事件并处理
        EventDispatcher dispatcher(e);
        dispatcher.Dispatch<WindowCloseEvent>(BIND_EVENT_FN(OnWindowClose));
    
        // 从后往前顺序处理事件
        for (auto it = m_LayerStack.end(); it != m_LayerStack.begin(); ){
            (*--it)->OnEvent(e);
            if (e.Handled)// 处理完就不要传入前一个层
                break;
        }
    }
    void Application::Run(){
        while (m_Running){
            glClearColor(1, 0, 1, 1);
            glClear(GL_COLOR_BUFFER_BIT);
    
            // 从前往后顺序更新层
            for (Layer* layer : m_LayerStack)
                layer->OnUpdate();
    
            m_Window->OnUpdate();	// 更新glfw
        }
    }
    

项目流程

  • 文字

    1. Application定义了LayerStack对象m_LayerStack
    2. 在Sandbox构造函数中,执行PushLayer(new ExampleLayer());,将ExampleLayer放入m_LayerStack的vector中
    3. Application的OnEvent函数从后往前顺序遍历m_LayerStack的vector,得到ExampleLayer对象,并把事件e作为参数执行它的OnEvent函数,所以一直在控制台输出窗口事件
    4. Application的OnUpdate函数从前往后遍历m_LayerStack的vector,得到ExampleLayer对象,并执行它的OnUpdate函数,所以一直在控制台输出**“ExampleLayer::Update”**
  • 图示

    以下是以活动图的样子绘制的,并不符合活动图的规范,但大意是这样

    Hazel游戏引擎(013)Layers游戏的层级,Hazel游戏引擎,游戏引擎,游戏,ui,glfw,软件工程

效果

Hazel游戏引擎(013)Layers游戏的层级,Hazel游戏引擎,游戏引擎,游戏,ui,glfw,软件工程

LayerStack类的错误

LayerStack的vector管理layer有错

  • 简化的例子

    #include <iostream>
    #include <vector>
    using namespace std;
    
    void Test1() {
    	vector<int> vec;
    	std::vector<int>::iterator m_LayerInsertIndex = vec.begin();// 头部插入位置
    	// 在头部插入1 2,此时vector 2 1
    	m_LayerInsertIndex = vec.emplace(m_LayerInsertIndex, 1);
    	m_LayerInsertIndex = vec.emplace(m_LayerInsertIndex, 2);
    	// 在尾部插入4,  此时vector 2 1 4
    	vec.emplace_back(4);
    	// 在头部插入3,   此时vector并不是 3 2 1 4,而是会报错
    	//m_LayerInsertIndex = vec.emplace(m_LayerInsertIndex, 3);
    	for (int i = 0; i < vec.size(); i++) {
    		cout << vec[i] << endl; 
    	}
    }
    int main() {
    	Test1();
    	return 0;
    }
    
    
  • 报错结果

    Hazel游戏引擎(013)Layers游戏的层级,Hazel游戏引擎,游戏引擎,游戏,ui,glfw,软件工程

  • 分析原因

    不太准确,个人猜测可能在尾部插入元素(emplace_back)使vector在内存位置发生改变,会破坏m_LayerInsertIndex这个迭代器无效吧

  • 解决方法

    在尾部插入元素(emplace_back)后让m_LayerInsertIndex迭代器重新指向头部

    #include <iostream>
    #include <vector>
    using namespace std;
    
    void Test1() {
    	vector<int> vec;
    	std::vector<int>::iterator m_LayerInsertIndex = vec.begin();// 头部插入位置
    	// 在头部插入1 2,此时vector 2 1
    	m_LayerInsertIndex = vec.emplace(m_LayerInsertIndex, 1);
    	m_LayerInsertIndex = vec.emplace(m_LayerInsertIndex, 2);
    	// 在尾部插入4,  此时vector 2 1 4
    	vec.emplace_back(4);
    	// 在头部插入3,   此时vector并不是 3 2 1 4,而是会报错
    	m_LayerInsertIndex = vec.begin(); // 需要重新让头部迭代器指向头部
    	m_LayerInsertIndex = vec.emplace(m_LayerInsertIndex, 3);
    	for (int i = 0; i < vec.size(); i++) {
    		cout << vec[i] << endl; 
    	}
    }
    int main() {
    	Test1();
    	return 0;
    }
    

    Hazel游戏引擎(013)Layers游戏的层级,Hazel游戏引擎,游戏引擎,游戏,ui,glfw,软件工程文章来源地址https://www.toymoban.com/news/detail-684976.html

到了这里,关于Hazel游戏引擎(013)Layers游戏的层级的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 跟着cherno手搓游戏引擎【4】窗口抽象、GLFW配置、窗口事件

    在vendor里创建GLFW文件夹: 在github上下载,把包下载到GLFW包下。 GitHub - TheCherno/glfw: A multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input修改SRC/premake5.lua的配置:12、13、15、36、37、38、39、40行的代码是新加上去的: GLFW中的premake5.lua:  如出现此BUG:请找GLFW中的premake5文件,

    2024年01月21日
    浏览(25)
  • Hazel 引擎学习笔记

    https://youtu.be/etdSXlVjXss 我感觉自己照抄视频中的脚本还是有点慢了 因为你不知道他什么时候加了什么东西,或者自己照抄就很容易抄错 我觉得最好的方法就是自己快速过一遍他的视频,知道他大概的思路是怎么样的,然后自己再拉取那个 commit 的代码,用 diff 方便看他具体修

    2024年02月13日
    浏览(38)
  • 2022版本unity-2D游戏官方案例--带视频案例(1)(层级渲染,物理碰撞,粒子动画,UI等多位基础一体化)

      👨‍💻个人主页:@元宇宙-秩沅 hallo  欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由  秩沅  原创 收录于专栏 unity实战入门  ⭐相关文章⭐ ——————————————————— -[本站最全-unity常用API大全(万字详解),不信你不收藏] -[关于游戏剧情模式中用到的

    2024年02月03日
    浏览(53)
  • 软件工程毕设分享(含算法) 基于python的搜索引擎设计与实现

    今天学长向大家分享一个毕业设计项目 毕业设计 基于python的搜索引擎设计与实现 项目运行效果: 毕业设计 基于python的搜索引擎 项目获取: https://gitee.com/sinonfin/algorithm-sharing 随着互联网和宽带上网的普及, 搜索引擎在中国异军突起, 并日益渗透到人们的日常生活中, 在互

    2024年01月21日
    浏览(57)
  • unity的UI元素层级调整的方法

    UI的渲染层级决定了最终显示效果,先渲染的在底层,后渲染的上层。层级按照如下优先级确定: 相机深度,通过Camera控件中的Depth属性设置,值越大的后渲染; Canvas的Sorting Layer,约靠下的后渲染; Canvas的Order in layer,在同一个Sorting Layer时,值越大越后渲染; UI节点的层级

    2024年02月11日
    浏览(27)
  • Android手机如何查看UI渲染层级,过度绘制

    最近在调试一个UI问题时,怎么也找不到错误原因。 于是就想着通过手机的过度绘制查看模式观察一下每个控件的位置,从而定位问题。 但是由于太久没有调试过过度绘制问题了,所以在网上搜了搜,最终又捡起来了调试方法。 针对于不同型号的手机,路径可能有略微差别

    2023年04月08日
    浏览(36)
  • 软件UI工程师的职责模板

      软件UI工程师的职责模板1 职责: 1.负责产品的UI视觉设计(手机软件界面 网站界面 图标设计产品广告及 企业文化的创意设计等); 2.负责公司各种客户端软件客户端的UI界面及相关图标制作; 3.设定产品界面的整体视觉风格; 4.为开发工程师创建详细的界面说明文档,保证工程师

    2024年02月13日
    浏览(34)
  • element-ui / element-plus dialog 自定义层级

    背景:          微前端集成后主子应用的dialog 层级冲突导致主应用的弹窗被覆盖, 主子应用的弹窗都是append 到body 下的,  z-index 自动生成   尝试方案:          1. 根据官方Api 给弹窗添加自定义class, 并通过设置自定义 class 样式来控制;                  == 无效, 因为生

    2024年02月11日
    浏览(47)
  • 快速解决element ui的组件的版本z-index层级问题

    怎么快速解决 element ui 的组件的版本z-index层级问题 首先你要清楚, element ui 组件( select / dialog ) z-index 的层级从哪里来的。 你看源码就会知道,每次都会混入个 minxin:[Popper] 可以知道,他的层级是从这个 Popper 这里来的, 我们在写组件的时候,只需要获取他的Popper混入方法就

    2024年02月02日
    浏览(487)
  • element ui 层级选择器el-cascader只能选最后一级多选

    在element ui 中el-cascader多选: 每个层级都可以选择,但并不是我需要的,我需要多选只能选最后一级,在网上找了很久都复杂的,最终自己选择用css样式对checkbox进行隐藏。 实现方法: 在css 中加入 关键点在于利用属性选择器,遇到属性是 aria-haspopup (表示点击的时候是否会

    2024年02月11日
    浏览(64)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包