C++ 创建一个C++;事件系统

C++ 创建一个C++;事件系统,c++,events,game-engine,C++,Events,Game Engine,我最近决定开始制作游戏引擎。我知道大多数人不会完成他们的任务,如果我说实话,我也可能不会。我这样做是因为我讨厌Google“酷C++项目”,并且做每一个用户给出的3个答案(那就是一个地址簿或类似的东西,TIC Tac趾,和一个报告卡生成器或类似的东西)。我喜欢编程,但不幸的是我没有真正的用途。我想用它做的每件事都可以用另一种方式做得更快、更容易,或者已经有了解决方案。然而,为了学习更多的C++基础知识,做一些能真正深入的事情,我撤销了这个政策,决定开始游戏引擎,因为这是我一直感兴趣的东西。我决定

我最近决定开始制作游戏引擎。我知道大多数人不会完成他们的任务,如果我说实话,我也可能不会。我这样做是因为我讨厌Google“酷C++项目”,并且做每一个用户给出的3个答案(那就是一个地址簿或类似的东西,TIC Tac趾,和一个报告卡生成器或类似的东西)。我喜欢编程,但不幸的是我没有真正的用途。我想用它做的每件事都可以用另一种方式做得更快、更容易,或者已经有了解决方案。然而,为了学习更多的C++基础知识,做一些能真正深入的事情,我撤销了这个政策,决定开始游戏引擎,因为这是我一直感兴趣的东西。我决定在亚马逊的木板引擎上轻松地模拟它,因为它几乎完全是C++的,它给了我一个很好的学习基础,因为我总是可以去那里做一些事情来看看它的行为。 现在谈谈实际问题:

我已经有了一个工作实体组件系统(yay),尽管它还处于早期阶段,功能还不是非常强大,但我非常自豪。老实说,我从没想过我能走这么远。我目前正在使用事件总线系统。现在,我真的很喜欢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;
 };
我只是不明白你怎么能仅仅通过向NewEbusDealio添加一个虚拟函数就完成这么多事情。非常感谢您在这方面的任何帮助。很抱歉有这么多的文字墙,但我真的很想从中得到一些东西,我在这一点上碰到了一个巨大的砖墙。这可能对我正在做的工作来说是一种过度的杀伤力,而且它也可能是如此之多的工作,以至于一个人在合理的时间内不可能完成,但是如果一个简单的版本是可能的,我想尝试一下


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

不熟悉你给出的
EBus
,但是事件总线应该是类似的:一方创建一个事件并将其放入列表,另一方逐个拾取事件并做出反应

现代C++为我们提供了封闭的特性,现在实现事件总线更加容易。 接下来,我将给出一个简单的示例,其中looper是一个事件总线

请注意,mutex和条件变量对于生产中的此活套是必需的

#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};
};
#包括
#包括
#包括
#包括
类线程包装器{
公众:
ThreadWrapper()=默认值;
~ThreadWrapper(){Detach();}
内联无效附加(std::thread&&th)无异常{
分离();
例行程序=标准:正向(th);
}
内联void Detach()无异常{
if(routine.joinable()){
例程。join();
}
}
私人:
std::线程例程{};
};
类活套{
公众:
//返回true退出循环,返回false继续
typedef-std::函数任务;
typedef std::list MsgQueue;
Looper()=默认值;
~Looper(){
去激活();
}
//张贴方法
无效岗位(施工任务和tsk)无例外{
邮政(tsk,假);
}
//张贴方法
无效Post(施工任务和tsk、bool flush)无例外{
如果(!正在运行){
返回;
}
if(flush)msg_queue.clear();
消息队列。推回(tsk);
}
//开始循环
void Activate()无异常{
如果(正在运行){
返回;
}
msg_queue.clear();
循环=真;
Attach(std::thread{&Looper::Entry,this});
运行=真;
}
//停止循环
void Deactivate()无异常{
{
如果(!正在运行){
返回;
}
循环=假;
Post([]{;},true);
worker.Detach();
运行=错误;
}
}
bool IsActive()const noexcept{return running;}
私人:
void Entry()无例外{
任务tsk;
while(循环){
//如果(msg_queue.empty())继续;
tsk=msg_queue.front();
msg_queue.pop_front();
tsk();
}
}
MsgQueue msg_queue{};
线程包装工人{};
volatile bool运行{false};
易失性布尔循环{false};
};
使用此活套的示例:

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;
  }
};
类MySpeaker:公共循环器{
公众:
//调用SayHi而不阻塞当前线程
void sayiasync(const std::string和msg){
Post([这个,msg]{
早喜(味精),;
});
}
私人:
//SayHi将在工作线程中被调用
void SayHi(){
这个问题是关于“LY的EBus系统”是如何工作的,而不是关于游戏引擎。这个库的链接或信息可能对这个问题有益。
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;
  }
};