繁体   English   中英

C ++:游戏引擎的事件系统实现

[英]C++: event system implementation for a game engine

我正在计划一个事件驱动的游戏引擎。 基本的想法是,不是让所有事情都与所有事情交谈,一切都会与事件系统进行对话,事件系统会将消息转发给收件人,而不会将收件人与通知者联系起来,反之亦然。

  • 对象将自己注册到事件系统。 通知ID和指向回调函数的指针作为每个注册命令的参数传递。
  • 对象向事件系统添加通知。 通知的ID作为每个通知的参数传递。 通知将添加到保存所有未决通知的队列中。
  • 此外,事件系统支持计划的通知。 通知ID和将来的执行时间将作为每个通知的参数传递。 然后将计划的通知存储在按照未来执行时间的顺序保存计划通知的数据结构(“计划”)中。
  • 调用者对象命令事件系统处理所有排队的通知。 事件系统按顺序获取通知,并调用已使用与当前通知相同的ID注册自身的每个对象的回调函数。
  • 调用者对象命令事件系统处理一个预定的通知。 从调度中获取最旧的通知,并调用使用相同通知ID注册的所有对象的回调。

class Registration
{
public:
    void callback(void){ callback_(); }
    void setCallback((*callback)(void));
    void addToEventSystem(int ID, EventSystem &eventSystem);
private:
    void (*callback_)(void);
};

class EventSystem
{
public:
    void register(int ID, Registration* registration);
    void unRegister(int ID, Registration* registration);
    void addNotificationToQueue(int ID);
    void addNotificationToSchedule(int ID, int notificationTime);
    void processQueuedNotifications(void);
    void processNextScheduled(void);
    int getCurrentTime(void);
private:
    //placeholder types
    <list> notificationQueue;
    <binaryheap> notificationSchedule;
};

//------------Use:------------------
class ReceiverObject
{
public:
    void doStuff(void);
    void initialize(void){
        keyPressRegistration.setCallback(doStuff);
        //multiple registrations with different ID:s to same eventsystem possible
        keyPressRegistration.addToEventSystem(1234,eventSystem);
        keyPressRegistration.addToEventSystem(42,eventSystem);};
private:
    Registration keyPressRegistration;
};

int main()
{
    ReceiverObject receiverObject;
    EventSystem eventSystem;
    receiverObject.initialize();
    eventSystem.addNotificationToQueue(1234);
    eventSystem.processQueuedNotifications();
}

但是我对这个解决方案并不完全满意,主要是因为系统不允许将参数轻松传递给收件人,而且我对成员函数的回调持怀疑态度,这是一个很好的设计实践吗? 我想出的方法/类/变量名称怎么样? 对这个问题的建设性批评,指导和替代方法是值得欢迎的。

它与你的问题没有严格的关系,但谈到设计,我会避免使用全球通知系统“为所有事情”,因为我看到过去的不良后果。 您将倾向于在一个对象仅对另一个对象调用某种方法的地方使用重事件系统。

专业的模板化系统工作得更好,即允许您控制对象寿命的系统,以及用于处理特定类型事件和其中已知参数的系统。

无论如何,您都会发现难以解决的问题,例如等待中的事件想要传递给已经被杀死的接收者。

我个人会有一个EventHandler的接口类,你可以注册,它将具有一个虚拟action函数(也许是事件系统的一个函数,告诉该类它是未注册的)。 这完全避免了回调,并且EventHandler的实际实现将有可能保存其他数据(或对其他数据的引用)。

对于参数问题 - 您可以定义其派生是模板化的基类ParamList:

class ParamList
{
     const ID_Type& GetParamsType();
     ...
};
template <typename T>
class Params: public ParamList
{
     ...
}

现在回调将是类型:void(* Callback)(ParamList&); 为了安全使用,您可以添加到注册const ID_Type和GetExpectedParamsType(); 并在回电之前使用它

相同的去通知:void addNotificationToQueue(int ID,ParamList&param); void addNotificationToSchedule(int ID,ParamList&param,int notificationTime);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM