好的,我已经创建了一个系统来监听和处理事件,如下所示。我创建了一个事件结构和几个更具体的结构来保存事件数据。我还为接收事件数据的监听器创建了一个 typedef。内部事件处理程序接收事件并在该事件的适当 vector 中运行所有用户定义的监听器。但是,由于 Event 类仅包含 EventType,因此特定事件数据被切掉了。有没有办法解决这个问题,这样我就不必重写几乎所有的代码。我曾尝试通过引用传递事件,但这并没有解决问题。这是到目前为止的代码...
编辑:我知道我可以使用 static_cast 来使用事件中的其他数据,但是由于我正在尝试为开发人员创建一个简单的 API,所以我不想强制用户在每个监听器中使用 static_cast。
结构
struct Event {
EventType type;
};
struct MouseEvent : Event {
int x;
int y;
bool down;
uint8_t which;
};
typedef function<void(MYCLASS&, Event&)> Listener;
typedef vector<Listener*> Listeners;
处理程序
void MYCLASS::eventHandler(Event& event, Listeners* listeners) {
for(auto it = listeners->begin(); it != listeners->end(); ++it) {
(**it)(*this,event);
}
}
示例用户定义的监听器
instance.addListener(MOUSEMOVE, [](MYCLASS& a, Event& e) {
cout << e.x << endl; //THIS LINE DOES NOT WORK
});
最佳答案
受到积极反馈的鼓舞,我在这里发布我的答案。
主要思想是分别处理每个回调类型,例如鼠标和键盘。
instance.addMouseListener([](MYCLASS& a, MouseEvent& e) {
cout << e.x << endl;
});
instance.addKeyboardListener([](MYCLASS& a, KeyboardEvent& e) {
cout << e.button << endl;
});
它有点凌乱,但它运行良好(至少对于我的游戏而言)。
而且,我相信这是一个标准的解决方法。
(参见:addMouseListener for a JPanel、SDL Mouse Click)
但我更喜欢另一种方式。它可能适合也可能不适合你。
我创建了一个鼠标/键盘实例,并将它们视为全局变量。
然后用户可以查询它:-
//in game loop : e.g. System_UpdateRocket.h
MousePtr* mouse=getMouseGlobal();
KeyboardPtr* keyboard=getKeyboardGlobal();
if(mouse->getMouseMovementDelta().x < 0 &&
keyboard->justPressThisFrame(KEYBOARD::SPACE_BUTTON)){
//do something e.g. myRocket->pewPew();
}
在这种方法中,需要有一个库级别的中央系统,它在每个时间步更新每个类似全局的实例(如 MousePtr*
)。
关于c++ - 回调参数 C++ 中的协方差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57532753/