6.3 处理游戏手柄事件
wxJoystick 类让你可以在 windows 平台或者 linux 平台上使用一到两个游戏手柄.典型的使用方法是,你创建 wxJoystick 的一个实例,并且传递给它 wxJOYSTICK1 或者 wxJOYSTICK2 的参数,并且以全局指针保持这个实例.当你需要处理手柄事件的时候,使用 SetCapture 函数和一个窗口指针作为参数,来使的这个窗口收到游戏手柄事件,当你不需要使用手柄的时候,调用 ReleaseCapture 函数移出手柄事件.当然,你完全可以在应用程序初始化的时候调用 SetCapture 函数而在应用程序退出的时候调用 ReleaseCapture 函数,以便在整个应用程序生命周期内处理游戏手柄事件。
在开始描述详细的函数和事件之前,让我们先看一下 wxWidgets 的发行版中 samples/joystick 目录中的例子.在这个例子中,用户可以使用游戏手柄上的某个按钮画线,并且在按下按钮的时候播放一个声音片断。
下面大概列出了应用程序的起始代码,首先,应用程序通过创建一个临时的游戏手柄对象来检查系统是否有安装手柄,如果没有则退出应用程序.然后装载声音文件,并且获取手柄的最大活动范围以便在窗口上画画的时候实现合理的缩放使得画画的区域充满整个绘画窗口。
#include "wx/wx.h"
#include "wx/sound.h"
#include "wx/joystick.h"
bool MyApp::OnInit()
{
wxJoystick stick(wxJOYSTICK1);
if (!stick.IsOk())
{
wxMessageBox(wxT("No joystick detected!"));
return false;
}
m_fire.Create(wxT("buttonpress.wav"));
m_minX = stick.GetXMin();
m_minY = stick.GetYMin();
m_maxX = stick.GetXMax();
m_maxY = stick.GetYMax();
// Create the main frame window
...
return true;
}
MyCanvas 是那个用来接收和处理手柄事件的窗口,下面的 MyCanvas 类的实现部分:
BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
EVT_JOYSTICK_EVENTS(MyCanvas::OnJoystickEvent)
END_EVENT_TABLE()
MyCanvas::MyCanvas(wxWindow *parent, const wxPoint& pos,
const wxSize& size):
wxScrolledWindow(parent, wxID_ANY, pos, size, wxSUNKEN_BORDER)
{
m_stick = new wxJoystick(wxJOYSTICK1);
m_stick->SetCapture(this, 10);
}
MyCanvas::~MyCanvas()
{
m_stick->ReleaseCapture();
delete m_stick;
}
void MyCanvas::OnJoystickEvent(wxJoystickEvent& event)
{
static long xpos = -1;
static long ypos = -1;
wxClientDC dc(this);
wxPoint pt(event.GetPosition());
// if negative positions are possible then shift everything up
int xmin = wxGetApp().m_minX;
int xmax = wxGetApp().m_maxX;
int ymin = wxGetApp().m_minY;
int ymax = wxGetApp().m_maxY;
if (xmin < 0) {
xmax += abs(xmin);
pt.x += abs(xmin);
}
if (ymin < 0) {
ymax += abs(ymin);
pt.y += abs(ymin);
}
// Scale to canvas size
int cw, ch;
GetSize(&cw, &ch);
pt.x = (long) (((double)pt.x/(double)xmax) * cw);
pt.y = (long) (((double)pt.y/(double)ymax) * ch);
if (xpos > -1 && ypos > -1 && event.IsMove() && event.ButtonIsDown())
{
dc.SetPen(*wxBLACK_PEN);
dc.DrawLine(xpos, ypos, pt.x, pt.y);
}
xpos = pt.x;
ypos = pt.y;
wxString buf;
if (event.ButtonDown())
buf.Printf(wxT("Joystick (%d, %d) Fire!"), pt.x, pt.y);
else
buf.Printf(wxT("Joystick (%d, %d)"), pt.x, pt.y);
frame->SetStatusText(buf);
if (event.ButtonDown() && wxGetApp().m_fire.IsOk())
{
wxGetApp().m_fire.Play();
}
}
wxJoystick 的事件
wxJoystick 类产生 wxJoystickEvent 类型的事件,下表列出了所有相关的事件映射宏:
EVT_JOY_BUTTON(func) | 用来处理 wxEVT_JOY_BUTTON_DOWN 事件,手柄上的某个按钮被按下的时候产生。 |
---|---|
EVT_JOY_BUTTON(func) | 用来处理 wxEVT_JOY_BUTTON_UP 事件,某个按钮被释放的时候产生。 |
EVT_JOY_MOVE(func) | 用来处理 wxEVT_JOY_MOVE 事件,手柄在 X-Y 平面上产生移动的时候产生。 |
EVT_JOY_ZMOVE(func) | 用来处理 wxEVT_JOY_ZMOVE 事件,手柄在 Z 方向上产生移动的时候产生。 |
EVT_JOYSTICK_EVENTS(func) | 处理所有的手柄事件。 |
wxJoystickEvent 的成员函数
下面列出了所有 wxJoystickEvent 的成员函数,你可以使用它们获取关于手柄事件更详细的信息,当然,首先还是 GetEventType 函数,这个函数在你使用 EVT_JOYSTICK_EVENTS 宏的时候告诉你你正在处理哪种类型的手柄事件。
调用 ButtonDown 函数来检测是否是按钮被按下事件,你可以传递可选的 wxJOY_BUTTONn(n 代表 1,2,3 或 4) 来测试是否某个特定的按钮正被按下,或者使用 wxJOY_BUTTON_ANY 如果你不关心具体是哪个按钮被按下的话.ButtonUp 则用相似的方法来检测是按钮被释放事件.而 IsButton 则相当于调用 ButtonDown() || ButtonUp()。
要判断是否某个按钮被按下的状态而不是事件本身,你可以使用 ButtonIsDown 函数,它和 ButtonDown 的参数相似.或者你可以直接使用 GetButtonState 函数和类似的参数来返回指定按钮的按下状态的比特位。
使用 IsMove 函数来判断是否是一个 XY 平面的移动事件,使用 IsZMove 判断是否是一个 Z 平面的移动事件。
GetPosition 返回游戏手柄当前 XY 平面的座标,而 GetZPosition 返回 Z 方向的深度值(当然,如果手柄支持的话)。
最后,你可以使用 GetJoystick 来判断这个事件是哪个手柄(wxJOYSTICK1 还是 wxJOYSTICK2) 产生的。
wxJoystick 成员函数
我们没有列出游戏手柄类所有的成员函数,你可以参考 wxWidgets 的手册,不过下面是其中最有趣的几个:
正象我们在前面的例子中看到的那样,SetCapture 函数需要被调用如果你想让某个窗口处理手柄事件,而一个匹配的 ReleaseCapture 函数调用用来释放这次捕获,以便允许别的应用程序使用手柄.为避免别的程序正在使用手柄,或者手柄不能正常工作,你应该在调用 SetCapture 之前先调用 IsOK 函数来判断手柄的状态.你还可以通过这些函数来获取手柄的能力集:GetNumberButtons, GetNumberJoysticks,GetNumberAxes,HasRudder 等等。
GetPosition 函数和 GetButtonState 函数可以让你在手柄事件处理函数以外的地方获取手柄的状态。
你的应用程序还可能需要调用 GetXMin,GetXMax 等这些类似的函数来判断一个手柄支持的范围。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论