- 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.
- Web應用系統開發實踐(C#)
- 程序員面試筆試寶典(第3版)
- Learning Cython Programming
- Visual Basic程序開發(學習筆記)
- Leap Motion Development Essentials
- PostgreSQL Replication(Second Edition)
- Visual Basic程序設計實踐教程
- BeagleBone Black Cookbook
- Test-Driven Development with Django
- Android傳感器開發與智能設備案例實戰
- Citrix XenServer企業運維實戰
- Oracle數據庫編程經典300例
- 精通Spring:Java Web開發與Spring Boot高級功能
- Java并發實現原理:JDK源碼剖析
- SAP Web Dynpro for ABAP開發技術詳解:基礎應用