SDL中的陷阱鼠标


12

如何将用户的鼠标捕获到我的游戏中?这不是一个全屏游戏,但我想要它,以便用户不能将鼠标拖到屏幕外。

我是否需要检查鼠标和SDL_WarpCursor的坐标以使其在窗口内显示(手动),还是有自动方法?

谢谢。


您是否考虑过隐藏光标并将其变形回中心?然后,只需将十字准线绘制在屏幕中央即可代替OS光标。
沃恩·希茨

Answers:


24

尽管您可以使用SDL_WarpCursor()实现此功能,但在某些平台上,该方法却遇到了问题。我遇到了某些平台无法可靠执行WarpCursor()动作的实际问题,尤其是当我在每一帧都调用它时。

另外,请记住,在许多平台上,处理光标的频率高于您的应用程序。如果您以低于60fps的速度运行,则尤其如此!因此,即使平台成功在游戏的每个帧上变形了鼠标,但如果光标正在渲染帧之间接收更新,则光标仍可能离开窗口。

在SDL下诱捕鼠标的正确方法是:

SDL_WM_GrabInput( SDL_GRAB_ON );

这告诉SDL您的意图是实际上要完全控制鼠标+键盘(请参阅文档),因此无论如何都将鼠标保持在窗口内。从那时起,无论帧速率如何,鼠标都不会移出窗口,并且您不应调用SDL_WarpCursor,除非您确实确实打算将光标传送到某个地方,而不是连续地向其发送垃圾邮件。

在这种“抓取”模式下,您将继续接收鼠标运动事件,就好像鼠标没有被约束在窗口内一样。(因此,如果光标位于屏幕的右边缘,并且用户将鼠标向右移动,您将收到一个鼠标移动事件,该事件向右显示运动,尽管光标位置不会改变)。这对于(例如)转动FPS游戏的控件非常有用,在该控件中,您仅关心光标的相对运动,而不关心光标的绝对位置。

SDL2的更新-2013年12月9日

SDL2的此接口已更改。如果您使用的是SDL1.2,则上面的答案仍然正确。但是,在SDL2下,该SDL_WM_GrabInput(SDL_GrabMode)功能不再可用。SDL2捕获鼠标的新方法是:

SDL_SetRelativeMouseMode(SDL_TRUE);

否则,这与以前的功能相同-在此模式下,您将继续接收SDL_MOUSEMOTION事件,就好像鼠标没有被约束在窗口内一样。


1
警告:我注意到在某些平台上,在打开鼠标捕捉后,我立即收到一个虚假的MouseMotion事件,动作非常大。为了解决这个问题,我让我的代码忽略了打开此模式后收到的第一个鼠标移动事件。
特雷弗·鲍威尔

效果很好,并且比手动方式容易得多。谢谢!
大卫·戈麦斯

3

尽管Trevor更新后的答案确实反映了SDL2的当前状态,但是您也可以通过SDL_Window使用该SDL_WINDOW_INPUT_GRABBED集合创建鼠标来捕获鼠标。请注意,我在Linux上遇到了一些奇怪的问题(可能是由于某些X窗口怪癖),除非调用SDL_QUIT(即使另一个OS事件夺走了焦点),否则您将永远无法退出该窗口。


谢谢您,SDL_WINDOW_INPUT_GRABBED可以在我的SDL2代码上完美地工作。
Adrian Maire


2

您可以使用SDL Motion事件来检测鼠标何时移动。然后,即使在触发事件以传递relX和relY值之后,也可以在其中调用WarpCursor。您也可以隐藏OS光标并在屏幕中央绘制十字准线或类似图形。这样可以确保鼠标似乎始终位于用户的中间位置,并且您仍然可以接收运动值等。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.