跳转至

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分堆使用会报错,需要进行多线程的编译