7 min read

Mouse Input

Introduction

In a previous tutorial, we looked at how to do keyboard input. Now we will look at mouse input. Remember that the Xbox 360 doesn’t have mice, so what we learn in this tutorial won’t work on the Xbox.

Showing the Mouse

The mouse location and button clicks are kept up to date in your XNA game. However, by default, the mouse is not displayed. One solution to this is to just draw an image at the location of the mouse. But perhaps an easier way is to just tell your game to render the mouse, instead of hiding it. This can be done with one simple line in your main game class. You can put the following line in just about any method of your main game class and it will work (constructor, Initialize, LoadContent, Update, or Draw, though Update and Draw means it will get called every frame when it only needs to happen once) but I’ve put mine in the constructor, and I think that’s the best place for it logically.

this.IsMouseVisible = true;

Doing Mouse Input

Getting input from the mouse is quite easy. And if you have already looked at doing input for the keyboard or Xbox controller, it won’t be much of a surprise. The first thing we are going to do is to get the current state of the mouse. The natural place to put our code is in the Update() method, so go there now. Add the following lines of code to get the current mouse state:

MouseState mouseState = Mouse.GetState();

The MouseState class contains all of the information that we could possibly want to know about the current state of the mouse.

Next, let’s try doing something when the mouse is clicked. To do this, we just add the following code:

if(mouseState.LeftButton == ButtonState.Pressed)
{
    // Do whatever you want here
}

Now, after trying this, you may see that the stuff inside of the if-statement will get executed whenever the mouse is pressed. We usually want to know when the mouse is first pressed, rather than whether it is down or not. To do this, we have to add a little bit more to our program.

The basic idea is that we need to store the previous mouse state, and then when it is time to update, we can check to make sure that the button was released before, and pressed now. That would constitute a mouse click.

So let’s start by adding the following line as an instance variable to our class:

private MouseState oldState;

Then in the Update() method, change what we had before to:

MouseState newState = Mouse.GetState();

if(newState.LeftButton == ButtonState.Pressed && oldState.LeftButton == ButtonState.Released)
{
    // do something here
}

oldState = newState; // this reassigns the old state so that it is ready for next time

This code first gets the current mouse state and then checks to see if in the current state, the button was pressed and if it was released in the old state (from the last update). This is equivalent to a button press since it was up before and down now. If it was pressed, then do whatever you want it to do, and then finally, set the old mouse state to be this current state. By the time the next update comes around, this will be the old mouse state.

Also, while we are at it, let’s see how to get the mouse position. This is also quite easy. The MouseState class has properties that are defined for the mouse position. So we need to do something like the following:

int x = mouseState.X;
int y = mouseState.Y;

That’s the basics of mouse input!

Changing the Mouse Location

Occasionally, you may want to set the mouse location in your game. I’d recommend not doing this very often, as it can be kind of frustrating to the user to have the mouse randomly change locations, but there are a few good times to do it. Just use it sparingly.

To set the mouse location, you use the Mouse class, which has a static method for setting the mouse location.

Mouse.SetPosition(x, y);

More About the MouseState class

You now know the basics of using the mouse as input. Below is a discussion of the components of the MouseState class, just for your information. Note that if a mouse doesn’t have a given button, then it always returns ButtonState.Released.

LeftMouseButton

The state of the left mouse button. This is the primary mouse button, and it should be used for the most common actions.

MiddleMouseButton

The state of the middle mouse button. Not all mice have a middle mouse button, but most do. Often, this is accomplished by pressing (not rotating) the mouse wheel, which counts as the middle mouse button.

RightMouseButton

The state of the right mouse button. This should be used for secondary actions. It is normally easier for a player to hit the left mouse button, so the most common actions should use that. But for other actions, the right mouse button is a good one to use.

XButton1 and XButton2

Some fancy mice have these extra buttons. They are often used for forward and backward in web browsers but assuming you have a mouse that has this button, you can use it in your game for anything you want. Just be warned that many mice do not have this button.

X

This stores an integer which contains the x-coordinate of the mouse in window coordinates. That is, this value is the number of pixels over from the left edge of the game window that the mouse is currently located at.

Y

This stores an integer which contains the y-coordinate of the mouse in window coordinates. This means it is the number of pixels that the mouse is down from the top of the game window.

ScrollWheelValue

This stores an integer value that contains the cumulative mouse wheel scroll value since the game was started. As you rotate the mouse wheel up, this number increases, and as you rotate it down, the number decreases. This value does not contain the total number of times that the mouse wheel was “clicked,” however. It contains the number of “detents” that the mouse wheel has moved. My mouse, for example, changes by 120 detents every time I move the mouse wheel. I’m sure it isn’t always the same for every mouse or every computer–it is probably user configurable to allow for more or less sensitive mice.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace MouseInput
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        private MouseState oldState;


        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            this.IsMouseVisible = true;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {

            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            //------------------------------------------------------------------------------------------

            MouseState mouseState = Mouse.GetState();

            //------------------------------------------------------------------------------------------

            if (mouseState.LeftButton == ButtonState.Pressed)
            {
                // Do whatever you want here
            }

            //------------------------------------------------------------------------------------------

            MouseState newState = Mouse.GetState();

            if (newState.LeftButton == ButtonState.Pressed && oldState.LeftButton == ButtonState.Released)
            {
                // do something here
            }

            oldState = newState; // this reassigns the old state so that it is ready for next time

            //------------------------------------------------------------------------------------------

            int x = mouseState.X;
            int y = mouseState.Y;

            //------------------------------------------------------------------------------------------

            Mouse.SetPosition(50, 100);

            //------------------------------------------------------------------------------------------

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}