gpt4 book ai didi

c++ - 创建 C++ 事件系统

转载 作者:行者123 更新时间:2023-11-28 04:32:50 27 4
gpt4 key购买 nike

最近我决定开始制作游戏引擎。我知道大多数人都不会完成他们的任务,老实说,我也可能不会。我这样做是因为我厌倦了谷歌搜索“Cool C++ projects”并做每个用户给出的 3 个答案(那是地址簿或类似的东西,井字游戏和报告卡生成器或类似的东西那)。我喜欢编程,但不幸的是我对它没有实际用处。我会用它来做的一切我都可以用另一种方式更快更容易地做,或者解决方案已经存在。然而,为了学习比 C++ 基础水平更多的东西,并做一些真正深入的东西,我已经撤销了这个政策并决定开始一个游戏引擎,因为它是我一直感兴趣的东西in。我决定在 Amazon 的 Lumberyard 引擎之后对其进行松散建模,因为它几乎完全是 C++,为我提供了一个很好的学习基础,因为我总是可以去那里做一些事情,看看它的行为。

现在进入实际问题:

我有一个可用的实体组件系统(是的),尽管它处于早期阶段并且功能不是非常好,但我为此感到非常自豪。老实说,我从没想过我会走到这一步。我目前正在使用事件总线系统。现在,我真的很喜欢 LY 的 EBus 系统。它非常易于使用且非常直接,但在编程新手看来,它是黑魔法和巫术。我不知道他们是如何做某些事情的,所以希望你知道!

制作 EBus 是这样的:

 #include <EBusThingy.h>

class NewEbusDealio
: public EbusThingy
{
public:
//Normally there's some setup work involved here, but I'm excluding it as I don't really feel that it's necessary for now. I can always add it later (see the footnote for details on what these actually are).

//As if by magic, this is all it takes to do it (I'd like to clarify that I'm aware that this is a pure virtual function, I just don't get how they generate so much usage out of this one line):
virtual void OnStuffHappening(arguments can go here if you so choose) = 0;
};

就是这样...就像变魔术一样,当你去使用它时,你所要做的就是:

 #include "NewEbusDealio.h"

class ComponentThatUsesTheBus
: public NewEbusDealio::Handler
{
public:
void Activate() override
{
NewEbusDealio::Handler::BusConnect();
}
protected:
void OnStuffHappening(arguments so chosen)
{
//Do whatever you want to happen when the event fires
}
};

class ComponentThatSendsEvents
{
public:
void UpdateOrWhatever()
{
NewEbusDealio::Broadcast(NewEbusDealio::Events::OnStuffHappening, arguments go here)
}
};

我只是不明白如何通过向 NewEbusDealio 添加一个虚拟函数来完成这么多事情。非常感谢对此的任何帮助。抱歉有这么多文字墙,但我真的很想从中得到一些东西,而且我在这方面遇到了一堵巨大的砖墙。这对于我正在做的事情来说可能有点过头了,而且它也可能会因为工作量太大而超出一个人在合理时间内完成的可能性范围,但是如果这个的简单版本有可能我想试一试。

我把它放在这里是为了让人们知道设置工作是什么。您所要做的就是定义一个静态常量 EBusHandlerPolicy 和 EBusAddressPolicy,它们定义了总线上每个地址可以连接多少个处理程序,以及总线是否在单个地址上工作(事件调用中不需要地址),或者您是否可以使用地址将事件发送给监听特定地址的处理程序。现在,我想要一个简单的总线,如果您发送一个事件,所有处理程序都会收到它。

最佳答案

不熟悉您给出的 EBus,但事件总线应该类似:一侧创建一个事件并将其放入列表,另一侧一个接一个地拾取事件并使用react。

由于现代 C++ 为我们提供了闭包功能,现在实现事件总线要容易得多。

下面我举一个简单的例子,其中looper就是一个事件总线。

请注意,互斥锁和条件变量对于生产环境中的循环程序是必需的。

#include <queue>
#include <list>
#include <thread>
#include <functional>

class ThreadWrapper {
public:
ThreadWrapper() = default;

~ThreadWrapper() { Detach(); }

inline void Attach(std::thread &&th) noexcept {
Detach();
routine = std::forward<std::thread &&>(th);
}

inline void Detach() noexcept {
if (routine.joinable()) {
routine.join();
}
}

private:
std::thread routine{};
};

class Looper {
public:

// return ture to quit the loop, false to continue
typedef std::function<void()> Task;
typedef std::list<Task> MsgQueue;


Looper() = default;

~Looper() {
Deactivate();
}

// Post a method
void Post(const Task &tsk) noexcept {
Post(tsk, false);
}

// Post a method
void Post(const Task &tsk, bool flush) noexcept {
if(!running) {
return;
}
if (flush) msg_queue.clear();
msg_queue.push_back(tsk);
}

// Start looping
void Activate() noexcept {
if (running) {
return;
}

msg_queue.clear();
looping = true;
worker.Attach(std::thread{&Looper::Entry, this});
running = true;
}

// stop looping
void Deactivate() noexcept {
{
if(!running) {
return;
}

looping = false;
Post([] { ; }, true);
worker.Detach();
running = false;
}
}

bool IsActive() const noexcept { return running; }

private:
void Entry() noexcept {
Task tsk;
while (looping) {
//if(msg_queue.empty()) continue;
tsk = msg_queue.front();
msg_queue.pop_front();

tsk();
}
}

MsgQueue msg_queue{};
ThreadWrapper worker{};
volatile bool running{false};
volatile bool looping{false};
};

使用这个 Looper 的例子:

class MySpeaker: public Looper{
public:
// Call SayHi without blocking current thread
void SayHiAsync(const std::string &msg){
Post([this, msg] {
SayHi(msg);
});
}

private:

// SayHi will be called in the working thread
void SayHi() {
std::cout << msg << std::endl;
}
};

关于c++ - 创建 C++ 事件系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52421688/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com