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:

  1. 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.
  2. Store the current mouse position into temporary variables, currentX and currentY.
  3. Reset the mouse position to the center of the screen or application window.
  4. Compute the relative mouse cursor position as the difference between its current position and the screen center position:
    relativeX = currentX - centerX
    relativeY = currentY - centerY
  5. 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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.247.11