MonoGame Tutorial: Building a 2D Game Using C#

Part 7 – Getting Keyboard and Mouse Inputs

In Part 6 we added the game border, completing the playing field. In this part, we’ll start getting user input and applying it to the game.

The main game element that a user interacts with is the paddle. So, let’s look at how we get inputs from the user and translate that into action in our game.

In our “Game1.cs” file, in the constructor, add the following two lines (we’ll go over this new code in a bit):
[code language=”csharp” highlight=”13,14″]
public class Game1 : Game
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
GameContent gameContent;

private Paddle paddle;
private Wall wall;
private GameBorder gameBorder;

private int screenWidth = 0;
private int screenHeight = 0;
private MouseState oldMouseState;
private KeyboardState oldKeyboardState;
//rest of file not shown to conserve space
Also in “Game1.cs”, add the indicated lines below to the Update method:
[code language=”csharp” highlight=”3,4,5,6,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35″]
protected override void Update(GameTime gameTime)
if (IsActive==false)
return; //our window is not active don’t update

if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))

// TODO: Add your update logic here
KeyboardState newKeyboardState = Keyboard.GetState();
MouseState newMouseState = Mouse.GetState();

//process mouse move
if (oldMouseState.X != newMouseState.X)
if (newMouseState.X >= 0 || newMouseState.X < screenWidth)

//process keyboard events
if (newKeyboardState.IsKeyDown(Keys.Left))
if (newKeyboardState.IsKeyDown(Keys.Right))

oldMouseState = newMouseState; // this saves the old state
oldKeyboardState = newKeyboardState;

Okay, let’s take a look at what we added. We added a test for IsActive. This tells us if our game is the active window. We don’t want to process events if we aren’t the active window, so if we aren’t active, we exit the update method.

We added two private variables called oldMouseState and oldKeyboardState. Why do we need those? This is one area where MonoGame programming is very different from what you are probably used to. In “normal” Windows programming, you get high-level events from the mouse like “Click”. Those high-level events aren’t available in MonoGame.

Instead, we have to compose them ourselves from the raw data that MonoGame provides to us. Basically, for the mouse, that is the current X and Y coordinate on the screen, button state (pressed or released), and thumb-wheel movement. We can’t determine a “Click” directly from this data. Instead, we need to have at least two data points from MonoGame, before we can detect a click event. Because of that, every time we get an Update event from MonoGame, we will need to save the previous Mouse and Keyboard state.

That’s what oldMouseState and oldKeyboardState are for. At the end of each Update method call, we save the mouse and keyboard state, so that when the next Update event occurs, we can compare the new readings with the old ones. With that background, how do we create a mouse click event?

Well, for a mouse click to have occurred, the user must press and release a mouse button without moving the mouse. So the logic to detect a left mouse click is:
[code language=”csharp” simple=”true”]
if (newMouseState.LeftButton == ButtonState.Released && oldMouseState.LeftButton == ButtonState.Pressed && oldMouseState.X == newMouseState.X && oldMouseState.Y == newMouseState.Y)
We’ll add that later to start the game and serve a ball.

For now, we will need to determine if the mouse has moved left or right. To do that, we just have to see if the X coordinate has changed between the old and new readings. That’s what this code does:
[code language=”csharp”]
if (oldMouseState.X != newMouseState.X)
if (newMouseState.X >= 0 && newMouseState.X < screenWidth && newMouseState.Y >=0 && newMouseState.Y < screenHeight)
If the mouse X coordinate has changed, we’ll just change the paddle position to the new coordinate, by calling the paddle.MoveTo method. We’ll only do this, if the mouse is within the boundary of our game field.

For the keyboard, we’ll just move the paddle a fixed amount to the left or right when the user presses the left or right arrow, by calling the paddle.MoveLeft and paddle.MoveRight methods, respectively.

Go ahead and press F5 to run the game now. When you move the mouse left or right you should see the paddle on the screen move left and right. Also, when you press the left or right keyboard arrow, you should see the paddle move left and right, as well.

Now our paddle can move, but it can’t fulfill its life mission yet, since there is nothing to hit! So, it’s time to add a ball to our game. We’ll do that in Part 8.

13 thoughts on “MonoGame Tutorial: Building a 2D Game Using C#”

  1. I was looking for a quick tutorial to dive into MonoGame. Thank you! This one is perfect! It’s very easy to understand basic concepts of game making.

  2. Excellent tutorial . Although XNA is no longer supported by MicroSoft, it’s a good framework for 2D game development.

  3. Exactly what I was looking for! I heard that Axiom Verge was built with Monogame and instantly wanted to figure out what I could do with it as well. Thanks for setting me on the right track with this quick tutorial 🙂

  4. What a great tutorial! Very too the point with great code examples! Thoughts on doing another one on another game type?

  5. Great tutorial! This really helped me understand the basics of XNA/MonoGame; which in turn will help me get past a hurdle with something else I was attempting.

    Also, being the audio nerd that I am I couldn’t help but play around with the panning option. Using what I had already learned in the tutorial, is was simple enough to make the brick breaking sound pan more left or right as you get farther from the center. Fun stuff!

  6. The best XNA/MonoGame tutorial so far!!
    I`m so hyped about the game, that I would love to see how to make more levels with more difficulties.

    Great Job!

Leave a Reply

Your email address will not be published. Required fields are marked *