Chapter 6 – Mouse Input in SDL

I intended to teach this before the graphics chapter but I figured it would be difficult to understand the sample program which will be written in this one without having some knowledge of how graphics work in SDL. Okay, then. Let’s get on with it. Mouse input is used in a lot of games ranging from those waste-of-time point & click flash games that I hate so much (but sometimes play when I’m bored), to main-stream First-Person Shooters, such as Counter-Strike.

In SDL, receiving and handling mouse input is pretty similar to receiving keyboard input. However unlike the keyboard, There are two events for the mouse. The SDL_MouseMotionEvent and the SDL_MouseButtonEvent. This is because the mouse sends to kinds of messages. Firstly, when you drag the mouse (or touch-pad, whatever you use), it sends a mouse motion message along with it’s position. Secondly, when you press a button on the mouse, it send a mouse button message.

First, let’s discuss SDL_MouseButtonEvent. The SDL_MouseButtonEvent has two event types, SDL_MOUSEBUTTONDOWN and SDL_MOUSEBUTTONUP, which are sent on a mouse-button press and mouse-button release respectively.

Here’s a sample program that exits when the left mouse-button is pressed.


#include <SDL/SDL.h>

int main(int argc, char* argv[])
{
    ...

    /* An SDL_Event struct */
    SDL_Event event;

    /* A bool to check if the program has exited */
    int quit = 0;

    /* While the program is running */
    while (!quit)
    {
        /* Check for new events */
        while(SDL_PollEvent(&event))
        {
            /* If a quit event has been sent */
            if (event.type == SDL_QUIT)
            {
                /* Quit the application */
                quit = 1;
            }
            
            /* If a button on the mouse is pressed. */
            if (event.type == SDL_MOUSEBUTTONDOWN)
            {
                /* If the left button was pressed. */
                if (event.button.button == SDL_BUTTON_LEFT)
                    /* Quit the application */
                    quit = 1;
            }
        }
    }
    ...
}

Now, to explain the code:

            /* If a button on the mouse is pressed. */
            if (event.type == SDL_MOUSEBUTTONDOWN)

As I explained earlier, the event type SDL_MOUSEBUTTONDOWN is sent when a mouse button is pressed.

                /* If the left button was pressed. */
                if (event.button.button == SDL_BUTTON_LEFT)

event.button is an SDL_MouseButtonEvent. To understand this, we need to take a closer look at the SDL_MouseButtonEvent structure.

typedef struct{
  Uint8 type;
  Uint8 button;
  Uint8 state;
  Uint16 x, y;
} SDL_MouseButtonEvent;

The type member is the event type, which is either an SDL_MOUSEBUTTONUP, or an SDL_MOUSEBUTTONDOWN. The button member is the mouse button which was pressed (SDL_BUTTON_LEFT, SDL_BUTTON_MIDDLE or SDL_BUTTON_RIGHT). The state is either SDL_PRESSED, on a button-press, or SDL_RELEASED, on a button-release. The x and y members are the x and y co-ordinates of the mouse cursor on the screen.

Now, in the code, we checked whether button equalled SDL_BUTTON_LEFT, i.e whether the left mouse button was pressed.

                    /* Quit the application */
                    quit = 1;

If the left mouse button is pressed, quit the program.

Now, let’s look at SDL_MouseMotionEvent. It has one event type, SDL_MOUSEMOTION. It is sent when the mouse is moved. To explain it better, here’s a sample program. However the program has a lot of bright flashing colours. I’ve heard these things are dangerous for photo-sensitive people . I sure hope this doesn’t cause someone an epileptic seizure or something. I should better write some kind of license above the source code that tells people to use it “at their own risk”, before someone sues me or something.

/**
Warning: Program not suitable for photo-sensitive people (or people with epilepsy).

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY  WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

In simple language, if this program harms you in any way whatsoever, it's not my fault!
**/

#include <SDL/SDL.h>

int main(int argc, char* argv[])
{
    ...

    /* An SDL_Event struct */
    SDL_Event event;

    /* A bool to check if the program has exited */
    int quit = 0;

    /* While the program is running */
    while (!quit)
    {
        /* Check for new events */
        while(SDL_PollEvent(&event))
        {
            /* If a quit event has been sent */
            if (event.type == SDL_QUIT)
            {
                /* Quit the application */
                quit = 1;
            }

            /* If the mouse is moving */
            if (event.type == SDL_MOUSEMOTION)
            {
                SDL_PixelFormat* fmt = screen->format;
                /* If the mouse is moving to the left */
                if (event.motion.xrel < 0)
                    SDL_FillRect(screen, NULL, SDL_MapRGB(fmt, 255, 0, 0));
                /* If the mouse is moving to the right */
                else if (event.motion.xrel > 0)
                    SDL_FillRect(screen, NULL, SDL_MapRGB(fmt, 0, 255, 0));
                /* If the mouse is moving up */
                else if (event.motion.yrel < 0)
                    SDL_FillRect(screen, NULL, SDL_MapRGB(fmt, 0, 0, 255));
                /* If the mouse is moving down */
                else if (event.motion.yrel > 0)
                    SDL_FillRect(screen, NULL, SDL_MapRGB(fmt, 0, 255, 255));
            }
        }

        SDL_Flip(screen);
    }
    ...
}

The explanations…

            /* If the mouse is moving */
            if (event.type == SDL_MOUSEMOTION)

This is the event type of SDL_MouseMotionEvent and is sent when the mouse moves. Let’s take a closer look at the SDL_MouseMotionEvent:

typedef struct{
  Uint8 type;
  Uint8 state;
  Uint16 x, y;
  Sint16 xrel, yrel;
} SOL;

Let’s get through this quickly. First is the type member, which (you guessed it!) is the event type, in this case SDL_MOUSEMOTION. The second member, state is the mouse-button state (more on that later). The x and y members signify the position of the mouse cursor on the screen. The xrel and yrel members represent the relative motion of the mouse. xrel is a positive number if the mouse is moving towards the right and negative if it is moving towards the left. Similarly, yrel is a positive number if the mouse is moving down and a negative number if it is moving up.

                SDL_PixelFormat* fmt = screen->format;
                /* If the mouse is moving to the left */
                if (event.motion.xrel < 0)
                    SDL_FillRect(screen, NULL, SDL_MapRGB(fmt, 255, 0, 0));
                /* If the mouse is moving to the right */
                else if (event.motion.xrel > 0)
                    SDL_FillRect(screen, NULL, SDL_MapRGB(fmt, 0, 255, 0));
                /* If the mouse is moving up */
                else if (event.motion.yrel < 0)
                    SDL_FillRect(screen, NULL, SDL_MapRGB(fmt, 0, 0, 255));
                /* If the mouse is moving down */
                else if (event.motion.yrel > 0)
                    SDL_FillRect(screen, NULL, SDL_MapRGB(fmt, 0, 255, 255));

Not much to understand here. As I explained earlier, xrel and yrel can be used to find out the direction of the mouse motion. I fill the screen with a different colour for every direction the mouse moves. If you move the mouse up, the screen will become red. If you move it down, it will become green. If you move it left, it will become blue. And if you move it down it will become a greenish-blue colour, the name of which I do not know.

Another long chapter. I wonder why my posts seem to be getting longer and longer. Perhaps it’s because I’m writing in more detail, discussing more stuff, or just yapping more than usual.

Advertisements

4 comments

  1. Thank you very much, dude, this is gold!!! I have my doubts about moving a rectangule with the mouse, it was so easy…but I didnt get, thanks pal

    excellent tutorial, this is awesome

  2. Hi thank you for your detailed explanation! This tutorial of yours is wonderful!
    Nevertheless I have a problem maybe you can help me with?! I am making a menu and the buttons shall play their animation when the mouse is on a specific location and stops the animation immediately when the location is left (sorry for my bad English.It is not my native language).Can I send you my Testcode per email, so you can see what I tried ?

  3. hey, i’m looking for an option to combine mouse motion with mouse button up, can you help me with that maybe? the problem is whenever there’s a mousemotion event detected, it’s ignoring the mouse button up event… i’d love to get some help! thanks!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s