Here is my Mouse2D DrawableGameComponent. I started out just wanting to be able to put a custom Mouse pointer/cursor on the screen instead of the windows mouse. From there the code just seemed to keep evolving more and more. After I got my custom pointer on the screen, I wanted to then place a Texture2D where it clicked (this was mostly for debugging etc, but I think turned out to be useful for other things). I could see this feature being used in map editors maybe, or something where you want to give the user the ability to design what they see on the screen.
Well, from there I just kept adding more and more to the code. Instead of just placing a Texture2D where a click occurred, I wanted to create an event system for the clicks. So, I started adding this in. Then, instead of just tracking clicks, I decided to track when the button is released as well. I also added events for the Mouse scroll wheel as well. Then I created events for when the Mouse was moved. After all that I decided that I should pass back some useful information from the events. So, when the MouseMoved event is fired, we pass back MouseMovedEventArgs which contains the Movement property which is a Vector2 that represents how much the Mouse has moved in the X and Y direction since the last update.
As well as adding some useful information into the events for Mouse movement, I also wanted to add some information on the Mouse button clicks and releases. So the ClickEventArgs class was then created. This contains the Click and PreviousClick properties. By using these, you can figure out how a click occured, and how much the user moved the Mouse before they release the button. This could be useful for drag and drop type of actions (maybe for selecting units in an rts style game) etc. It can also be used to find out how much time in between the click and the release of the button. There are event handlers for each Mouse button and it's state, and for the scroll wheel changes and for the mouses movement.
I called this DrawableGameComponent Mouse2D because it was developed with 2D games in mind (since I have zero 3D game developing skills). I'm not familiar with 3D enough yet to know if this class would need to be changed in order to be affective for 3D game projects. Well, I think that gives enough of an introduction to this. Now I'll post some code. Since the code for Mouse2D is a bit long, especially with the xml comments etc), I won't be putting code from it in this blog post. You will have to download the code in order to view it. Instead, I'm going to post some sample code of how you might use it in a game.
Ok, now on to the code. (code license)
Ok, to start, you would just create a new Widows Game using XNA GSE. You should now have a project with a Game1.cs file in it. This is the base for starting your XNA game. You should end up with something like the below for the first few lines of your new Game1.cs file:
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
#endregion
namespace WindowsGame1
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
ContentManager content;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
content = new ContentManager(Services);
}
Ok, so, we'll change the above to this:
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using TehOne.Xna.GameComponents;
#endregion
namespace WindowsGame1
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
ContentManager content;
MousePointer2D mousePointer;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
content = new ContentManager(Services);
mousePointer = new MousePointer2D(this);
this.Components.Add(mousePointer);
}
Basically, what we did was, we added a field to the class to hold our Mouse2D object. Then, in the constructor, we instantiated the Mouse2D object and stored it in our newly created field. Then, we add the object to the Game.Components collection. If you were to build the game now, you should see a mouse cursor/pointer on the screen. The Texture2D being used for the Mouse is an embedded resource in the TehOne.Xna.GameComponents dll. If you want to use your own Texture2D, then you would set the PointerAssetName in the constructor, like below:
public Game1()
{
graphics = new GraphicsDeviceManager(this);
content = new ContentManager(Services);
mousePointer = new MousePointer2D(this);
this.Components.Add(mousePointer);
mousePointer.PointerAssetName = @"Content\Sprites\YourMouseAsset";
}
As long as the PointerAssetName that you set exists, then you will now see your custom pointer on the screen if you rebuild the project. If the PointerAssetName that you set doesn't exist, the Mouse2D will still use it's internal Texture2D for the mouse. That is unless you set CanUseInteralAssets property to false. If you did set that to false, and your PointerAssetName you set doesn't exist, then you will get an exception thrown.
Now, to show how to hook into the events. This is a very simple example (to keep this post shorter). A more complete example is included in the code download. This shows you how to move a sprite when the mouse moves. I currently only having it moving from left to right for the sake of example (boundry detection is not being done either). What we are doing is adding a method to be fired when the mouse moves. Then we wire this event into the MouseMoved event of the Mouse2D object.
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
ContentManager content;
MousePointer2D mousePointer;
private SpriteBatch _spriteBatch;
private Texture2D _sprite;
private Vector2 _spritePosition = new Vector2(0, 0);
public Game1()
{
graphics = new GraphicsDeviceManager(this);
content = new ContentManager(Services);
mousePointer = new MousePointer2D(this);
this.Components.Add(mousePointer);
mousePointer.PointerAssetName = @"Content\Sprites\YourMouseAsset";
mousePointer.MouseMoved += new MousePointer2D.MouseMovedHandler(mousePointer_MouseMoved);
}
void mousePointer_MouseMoved(object sender, MousePointer2D.MouseMovedEventArgs e)
{
_spritePosition.X = mousePointer.Position.X;
}
protected override void LoadGraphicsContent(bool loadAllContent)
{
if(loadAllContent)
{
_spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
_sprite = content.Load<Texture2D>(@"Content\Sprites\YourSpriteName");
}
}
protected override void Draw(GameTime gameTime)
{
device.Clear(Color.CornflowerBlue);
_spriteBatch.Begin();
_spriteBatch.Draw(_sprite, _spritePosition, Color.White);
_spriteBatch.End();
base.Draw(gameTime);
}
For the last example, I'll wire up some events for the scroll wheel and a left click. First we need to create our methods for each, and then wire them up to the proper events. For the ScrollChanged event, we create a mousePointer_ScrollChanged method and when it is fired, we check to see which way the scroll wheel was moved (up or down). And then we set our sprites Y position based on it. For the LeftButtonPressed event, we create the mousePointer_LeftButtonClicked method and when it is fired we move the our sprites postion to the postion where the click occured.
public Game1()
{
graphics = new GraphicsDeviceManager(this);
content = new ContentManager(Services);
mousePointer = new MousePointer2D(this);
this.Components.Add(mousePointer);
mousePointer.PointerAssetName = @"Content\Sprites\YourMouseAsset";
mousePointer.MouseMoved += new MousePointer2D.MouseMovedHandler(mousePointer_MouseMoved);
mousePointer.ScrollChanged +=new MousePointer2D.ScrollChangedHandler(mousePointer_ScrollChanged);
mousePointer.LeftButtonPressed += new MousePointer2D.ClickHandler(mousePointer_LeftButtonClicked);
}
void mousePointer_MouseMoved(object sender, MousePointer2D.MouseMovedEventArgs e)
{
_spritePosition.X = mousePointer.Position.X;
}
void mousePointer_ScrollChanged(object sender, MousePointer2D.ScrollChangedEventArgs e)
{
if (e.Direction == MousePointer2D.ScrollChangedEventArgs.ScrollDirection.Up)
_spritePosition.Y -= _sprite.Height;
if (e.Direction == MousePointer2D.ScrollChangedEventArgs.ScrollDirection.Down)
_spritePosition.Y += _sprite.Height;
}
void mousePointer_LeftButtonClicked(object sender, MousePointer2D.ClickEventArgs e)
{
_spritePosition = e.Click.Position;
}
As always, I would really appreciate some feeback on this. I'm sure people can make use of this code (especially beginers). And I'm even more sure that it can be improved with input from others (especially those with more experience then me).
Read more!