- Lua Game Development Cookbook
- Mário Ka?uba
- 724字
- 2021-07-16 13:23:09
Using the relative mouse position
The relative mouse position is often used when you need unconstrained mouse movement. A typical example of such a use is a first person shooter game in a 3D environment. The relative mouse position represents how much the mouse pointer position changed in comparison with the previous state in all the axes.
Getting ready
The biggest problem with the relative mouse position is that the mouse pointer is constrained to the application window or the screen. You can solve this by centering the mouse cursor in the center of the application window after computing the relative cursor position or by using direct values from the mouse driver.
The relative mouse position has the big advantage of versatility because you can apply the mouse cursor speed modifier simply by multiplying the relative mouse position with a number. If that number is greater than 1, the mouse cursor will move faster. Multiplying by a number lesser than 1, will slow down the mouse cursor.
How to do it…
The first solution is the most viable in this situation as you don't have to depend on platform-specific features.
The whole solution relies on the following steps:
- Reset the mouse position to the center of the screen or application window on startup—this is to prevent sudden mouse cursor jumps on startup.
- Store the current mouse position into temporary variables,
currentX
andcurrentY
. - Reset the mouse position to the center of the screen or application window.
- Compute the relative mouse cursor position as the difference between its current position and the screen center position:
relativeX = currentX - centerX relativeY = currentY - centerY
- Repeat from step 2.
Mouse cursor centering can be achieved with the SDL.SDL_WarpMouse
function, where the parameters are the cursor positions in the x and y axes. In this case, you can't rely on the xrel
and yrel
event attributes because you center the mouse cursor position on every mouse move. As a consequence of this, the xrel
and yrel
values will be eliminated with the -xrel
and -yrel
values respectively in the next event iteration.
The mouse motion event handler will look like the following code:
[SDL.SDL_MOUSEMOTION] = function(_event) local event = _event.motion
The centerX
and centerY
values correspond to the screen center position and will change only on window resize event or on screen resolution change:
SDL.SDL_WarpMouse(centerX, centerY) relativeX, relativeY = event.x - centerX, event.y - center
The totalX
and totalY
variables will contain unconstrained mouse cursor coordinates:
totalX, totalY = totalX + diffX, totalY + diffY end
By putting the SDL.SDL_WarpMouse
function inside the mouse movement event handler, you can save some time. There's no need to reset the mouse cursor position at every event loop iteration.
There's more…
You might have noticed that this application doesn't let you move the cursor outside the application. For example, you need to switch to another application, but your mouse cursor is stuck in the middle of the application window. This issue can be solved by handling SDL_ACTIVEEVENT
. If your application loses focus, it will stop trying to set the mouse cursor position in the middle of the window. After it gains a window focus, it will reset the mouse position and restore the former mouse event handler.
It's a good idea to move the mouse movement event handler into a separate function. Let's assume that this function is called mouseMotionHandler
.
This first thing you must do is to do forward declaration of the events
table.
local events events = {...}
This gives you a way to modify the events
table inside the SDL_ACTIVEEVENT
event handler that is defined in this table.
The updated SDL_ACTIVEEVENT
handler can look like the following code:
[SDL.SDL_ACTIVEEVENT] = function(raw_event) local event = raw_event.active
First, you need to check whether your application gained or lost focus completely using the following code:
if SDL.And(event.state, SDL.SDL_APPINPUTFOCUS) > 0 then if event.gain == 1 then
The application gained complete focus and can restore the old mouse motion event handler. Don't forget to put the mouse cursor in the middle of the screen:
SDL.SDL_WarpMouse(centerX, centerY) events[SDL.SDL_MOUSEMOTION] = mouseMotionHandler else
The application lost complete focus; therefore, it can disable the mouse motion handler:
events[SDL.SDL_MOUSEMOTION] = false end end end
This way your application behaves in a more suitable manner and allows users to use other applications at the same time.
- Getting Started with ResearchKit
- 深入淺出Java虛擬機:JVM原理與實戰
- Learning C++ Functional Programming
- Java 9 Programming Blueprints
- NativeScript for Angular Mobile Development
- 零基礎學MQL:基于EA的自動化交易編程
- 軟件架構:Python語言實現
- BIM概論及Revit精講
- 從Java到Web程序設計教程
- 一本書講透Java線程:原理與實踐
- Java程序員面試筆試寶典(第2版)
- Mudbox 2013 Cookbook
- 快樂編程:青少年思維訓練
- Instant GLEW
- Visual C#(學習筆記)