目前,在我正在进行的游戏中,我有一个窗口类:
class UserWindow{
*interface here*
};
我已经竭尽全力避免暴露此窗口的实现细节;特别是它在引擎盖下使用GLFW的事实。在我最终最终删除/替换它的情况下,我不想向客户端暴露任何GLFW。一切都很好,直到我最终处理窗口的键输入。你看,GLFW使用宏来识别密钥,如下所示:
auto GLFWKeyPressCallback(GLFWwindow* wind, int key, int, int, int) -> void {
if(key == GLFW_KEY_???)
*do stuff*
}
正如大多数C ++程序员所知,宏是有毒的,应该避免。这里的问题是我提供了一个UserWindowEventListener接口,供用户连接和接收事件。问题是,如何在不暴露整个GLFW API本身的情况下公开这些GLFW键的标识符?由于GLFW使用前面提到的(邪恶的)宏来识别它们,它们会渗透到全局命名空间中,这破坏了拥有内部"命名空间。我想到的唯一的另一个解决方案就是拥有一个简单的ol'包含每个键的静态整数的struct,并将它们分配到.cpp文件中,如下所示:
.HPP:
struct UserWindowKey{
static const int up, down, left, right... (repeat ad nauseam)
};
的.cpp:
const int UserWindowKey::up = GLFW_KEY_UP...
然而,这看起来很乏味,难以管理,而且通常感觉就像是糟糕的做法。有什么想法吗?
编辑:psuedocode中的一些实现细节,以消除任何含糊之处:
UserWindow:
//constructor
UserWindow(){
//key_func just fires the signal that's in the event handler below.
glfwSetKeyCallback(window_handle, key_func);
}
UserWindowEventListener:
struct UserWindowEventListener{
key_signal_type key_signal;
};
用法:
auto main() -> int {
UserWindow wind;
wind.event_listener.key_signal.connect(*MY_FUNC*);
wind.event_listener.poll();
}
答案 0 :(得分:2)
我会创建一个中间方法,将GLFW键转换为您自己的键,以您感觉舒适且感觉清醒的方式定义。就个人而言,我会像这样列举:
enum MyKeys
{
UP,
DOWN,
LEFT,
RIGHT,
// the rest
}
然后用户会为您提供回调,并且您将为GLFW提供不同的回调。当GLFW调用您的回调时,您将密钥转换为公共枚举,然后触发用户提供的回调。
回调的伪代码可能类似于:
auto GLFWKeyPressCallback(GLFWwindow* wind, int glfwKey, int a, int b, int c) -> void
{
auto myKey = ConvertGlfwKeyToMyKey(glfwKey);
user_callback(myKey, a, b, c);
}
user_callback签名看起来像:
void user_callback(MyKeys, int, int, int);
ConvertGlfwKeyToMyKey可能如下所示:
MyKeys ConvertGlfwKeyToMyKey(glfwKey)
{
switch (glfwKey)
{
case GLFW_KEY_UP:
return MyKeys.UP;
case GLFW_KEY_DOWN:
return MyKeys.DOWN;
// the rest
}
}
这个系统的明显缺点是你必须经历并填写转换功能。优点是你已经从用户那里抽象掉了所有的GLFW内容,而不必使用任何宏或用一堆结构污染你的代码。
或者,您可以选择一些其他机制将GLFW键映射到MyKeys。如果GLFW键覆盖范围内的所有值,您可以按相同的顺序对枚举进行排序,然后从GLFW int到枚举进行偏移和类型转换。