首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++:游戏引擎的事件系统实现

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

Stack Overflow用户
提问于 2013-07-30 12:03:50
回答 3查看 9.3K关注 1票数 2

我正在计划一个事件驱动的游戏引擎。其基本思想是,不让所有的东西都与所有事物对话,而是与事件系统对话,事件系统将消息转发给他们的接收者,而不将接收者耦合到通知程序或相反的方式。

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

代码语言:javascript
运行
复制
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();
}

然而,我对这个解决方案并不完全满意,主要是因为系统不允许将参数轻易传递给接收者,而且我对回调成员函数表示怀疑,这是否好的设计实践?我想出的方法/类/变量名呢?对这一问题的建设性批评、指导和替代办法是值得欢迎的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-07-30 13:17:11

这与你的问题没有严格的关系,但是说到设计,我会避免使用全局通知系统,因为我在过去已经看到了不好的后果。您将倾向于在一个对象只对另一个对象调用某个方法的地方使用一个重事件系统。

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

无论如何,您都会发现很难解决问题,例如等待发送给已经死亡的收件人的未决事件。

票数 6
EN

Stack Overflow用户

发布于 2013-07-30 12:29:11

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

票数 1
EN

Stack Overflow用户

发布于 2013-07-30 14:14:45

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

代码语言:javascript
运行
复制
class ParamList
{
     const ID_Type& GetParamsType();
     ...
};
template <typename T>
class Params: public ParamList
{
     ...
}

现在回调的类型是: void (*Callback)(ParamList&);为了安全使用,您可以添加到类Registration ID_Type& GetExpectedParamsType()中,并在调用回调之前使用它。

sames用于通知: void addNotificationToQueue(int ID,ParamList& param);void addNotificationToSchedule(int ID,ParamList& param,int notificationTime);

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17946525

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档