Cursor manipulation

This recipe incorporates the basic principles of mouse cursor manipulation such as showing and hiding the mouse cursor.

Be aware that libSDL offers fairly limited support for mouse cursor images. These are constrained by using 2 bits for each pixel on an image (1 bit for data and 1 bit for mask) and by image width, which must be a multiple of 8 bits.

There's a much better way to display a mouse cursor. You can use mouse movement events to get the current mouse cursor position and draw an image on the resulting position. This gives you much more flexibility because you can use the cursor image with more than 1 bit for pixels, set up mouse movement smoothing, acceleration, and so on.

This recipe will show you how to implement a custom mouse cursor. This might be especially useful in a case where you need to emphasize an item location under the cursor.

Getting ready

LibSDL provides its own cursor drawing routine, which is turned on by default. If you want to use your own cursor image, you need to turn the default cursor off first.

This recipe will need you to include the GL module, which contains the most important OpenGL functions. This module is defined by the gl namespace.

This recipe assumes that you didn't change viewing frustum scaling. This means that screen coordinates use a range (-1,1) in each direction and the point at (0,0) position is the center of the screen. It's also assumed that you have enabled GL_TEXTURE_2D texturing target. The cursor texture should be bound to the current texturing target:

gl.Enable(GL_TEXTURE_2D)
gl.BindTexture(GL_TEXTURE_2D, cursor_texture_identifier)

How to do it…

First, you need to turn off the default cursor with the SDL.SDL_ShowCursor function:

SDL.SDL_ShowCursor(0)

Alternatively, you can turn the default cursor on with the following code:

SDL.SDL_ShowCursor(1)

Now, you need to get a source of the mouse cursor position. It's preferred to use events for obtaining the mouse cursor position, but you can also use an SDL.SDL_GetMouseState function as follows; it returns the state of mouse buttons and a cursor position:

local buttons, x, y = SDL.SDL_GetMouseState()

This position is relative to the position of the application window and you can safely use it to position the surface on the screen.

Now, you can draw the cursor image on the screen with each screen update. Let's assume that window_width contains the width of the current application's window and window_height contains the height of the window. The Mouse variable is a Lua table with both mouse cursor coordinates x and y. The mouse cursor size is defined by two variables, c_w and c_h.

Be aware that OpenGL uses a different Cartesian coordinate system by default than you are used to. The following figure shows how the coordinates are oriented:

How to do it…

All the coordinates are limited to the range (-1,1), where 0 corresponds to the center. That's why you'll need to divide all the input coordinates with window width and height respectively.

First, you need to define the cursor picture size:

local c_width, c_height = 32/window_width, 32/window_height

Next, you'll need to transform mouse cursor coordinates into a range of (-1, 1) in both directions:

local x = (mouse.x/window_width)*2-1
local y = -((mouse.y/window_height)*2-1)-c_height

Notice, that the y coordinate is multiplied by -1. That's because (-1,-1) in OpenGL corresponds to the lower-left corner of the window.

Now, you can draw a simple textured rectangle on the screen with OpenGL functions as follows:

gl.Begin(gl_enum.GL_QUADS)
  gl.Color4f(1,1,1,1)
  gl.TexCoord2f(0, 0)
  gl.Vertex2f(x, y)
  gl.TexCoord2f(1, 0)
  gl.Vertex2f(x+c_width, y)
  gl.TexCoord2f(1, 1)
  gl.Vertex2f(x+c_width, y+c_height)
  gl.TexCoord2f(0, 1)
  gl.Vertex2f(x, y+c_height)
gl.End()

How it works…

Are you still able to detect the mouse movement and position even if you hide the mouse cursor. The burden of cursor rendering becomes your responsibility.

Cursor rendering should be processed on every time frame so that the user can attain the best interactivity with your application. Cursor is usually drawn as the closest polygon to the viewer along with GUI elements. However, you're not limited to this traditional cursor rendering. For example, you can make the cursor polygon a part of your game. This means you can apply physics, collisions, feedback, and so on.

See also

  • The Loading images with SDL_image recipe
  • The Creating textures recipe
..................Content has been hidden....................

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