【发布时间】:2017-03-31 00:07:55
【问题描述】:
我正在将 SDL 包装到 C++ 对象中。基本上,我只是厌倦了在我的代码中看到 SDL_。我至少想要命名空间... SDL::Window。我已经做到了,它或多或少都很好。
问题与事件有关。我希望它是事件驱动的(回调),而不是我必须轮询事件队列。 (为了让 SDL_Event 符合我设计的抽象,您必须编写传播例程是很痛苦的)。
以 Window 类为例。它的构造函数调用
SDL_AddEventWatch(window_events, this);
其中 window_events 是 Window 类的静态成员。它捕获任何 SDL_WINDOWEVENT 类型的东西。
int Window::window_events(void* data, SDL::Events::Event* ev)
{
if (ev->type == SDL::Events::Window::Any)
{
auto win = static_cast<Window *>(data);
if (ev->window.windowID == SDL_GetWindowID(win->mWindow))
{
std::vector<event_callback> callbacks = win->mWindowCallbacks;
for (const auto cbk : callbacks)
{
cbk(*ev);
}
}
}
return 0;
}
我的 Window 类还包含 hook 和 unhook 方法。每个都需要一个 std::function。这就是 mWindowCallbacks 的集合。任何对事件感兴趣的外部例程都会收到一份副本转发给它。
//...
using event_callback = std::function<void(SDL::Events::Event)>;
//...
template<typename T> bool
find_func(const T & object,
const std::vector<T> & list,
int * location=nullptr)
{
int offset = 0;
for (auto single : list)
{
if (single.target<T>() ==
object.target<T>())
{
if (location != nullptr) *location = offset;
return true;
}
offset++;
}
return false;
}
void
Window::hook(event_callback cbk)
{
if (!find_func(cbk, mWindowCallbacks))
{
mWindowCallbacks.push_back(cbk);
}
}
void
Window::unhook(event_callback cbk)
{
int offset = 0;
if (find_func(cbk, mWindowCallbacks, &offset))
{
mWindowCallbacks.erase(mWindowCallbacks.begin() + offset);
}
}
用法:
///...
void cbk_close(SDL::Events::Event e)
{
if (e.window.event == SDL::Events::Window::Close)
{
window.close();
quit = true;
}
}
///...
std::function<void(SDL::Events::Event)> handler = cbk_close;
SDL::Window window;
window.hook(handler);
关闭:
void Window::close()
{
SDL_DelEventWatch(window_events, this);
SDL_DestroyWindow(mWindow);
mWindowCallbacks.clear();
}
对我来说,这似乎不是糟糕的设计。 一旦你在窗口上按下关闭,cbk_close 就会被调用,它会调用关闭,它会设置退出标志……然后它会返回到 window_events 循环。正如预期的那样......但是该函数似乎没有将控制权返回给程序。
这是我需要帮助的。我真的不明白为什么。我认为它劫持了主线程,因为如果您有一个窗口,程序将在该函数退出后退出,或者......如果您有两个窗口,则崩溃。
我的观点是否正确?我已经坚持了一周。实在是太气人了。对于任何愿意玩它的人;这是完整代码的 git repo。
Windows、Visual Studio 2015/VC 解决方案。
https://bitbucket.org/andywm/sdl_oowrapper/
【问题讨论】:
-
allegro 5 是事件驱动的。
-
@sailfish009 - 虽然我很欣赏 SDL 的替代品。那不是我要问的问题。不过还是谢谢。
标签: c++ sdl-2 event-driven