1.渲染¶
这一讲的 Layer 层系统,我们希望在进行游戏循环的时候,每个被启用的层(Layer)都会按照层栈顺序更新。通过这种更新循环,可以在层上进行渲染。显然因为层栈是有顺序的,这很重要。意味着你可以把层放在其他层的上面,这会决定绘制顺序。层栈对于构建、覆层系统也很有用。覆层能让你把层推至层栈的后半部分。
基本上就是说,我们有一个连续的层列表,但是覆层总会在列表的最后,因此总在最后渲染。
2.事件¶
但是在进行事件的时候,比如角色开枪,其点击了一下屏幕的按钮,我们希望这个事件直接被按钮处理了,而不是传播到之后的开枪处理中。因此我们要有正向遍历列表和反向遍历列表——正向遍历列表来渲染、更新等等,然后反向遍历来处理事件。
如果我们按一个按钮,那个按钮在所有东西被渲染出来的层后再渲染,此时接收到事件的是那个按钮,是最后一层,并且我们也不希望下面的角色也被点中,所以得反向向下传递事件,
反向的意思是说从最上层开始向下处理,而不是像渲染一样自底向上。
1.Layer基类¶
class CRYDUST_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;
};
2.LayerStack层栈基类¶
存储Layer,并提供迭代器和数据结构的API
class HENGINE_API LayerStack
{
public:
LayerStack();
~LayerStack();
void PushLayer(Layer* layer);
void PushOverlay(Layer* overlay);
void PopLayer(Layer* layer);
void PopOverlay(Layer* overlay);
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;
};
3.LayerStack层栈实现¶
emplace可以做到正常push的Layer中是以LayerInsert作为最后一个迭代的。 而PushOverlay直接在容器的最后新增层,迭代器不会发生变化,OverLay的Layer便和普通的Layer成功分开
LayerStack::LayerStack()
{
m_LayerInsert = m_Layers.begin();
}
LayerStack::~LayerStack()
{
for (Layer* layer : m_Layers)
delete layer;
}
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);
}
4.Application调用层栈。¶
渲染顺序顺着来一遍,事件倒着来一遍。
5.外部接口提供Layer的调用¶
CryDust.h引用、
6.多线程库编译调试/MD,/MDd¶
SPDLOG被SandBox和引擎核心Crydust分堆使用会报错,需要进行多线程的编译