You can download the soure code and images here:
Button Tutorial
In this tutorial I will show you how to create a GUI button control using XNA. I've
tried to make the control extendable so it can be added to the project later. The
control works pretty good but it is not quite perfect. I included changing the color
of the button by hovering over it and how to check to see if it has been clicked.
Later I will change the control to be a game component.
To get started you need to create an XNA Windows game project. Once the project
has been created you will have to add a class to the project, call it Button. You
will have to add three using statements to the class because it will use parts of
the XNA Framework. You need one for the Framework, one for Graphcs and one for Input.
These are the using statements:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
I've added several fields to the class. One for the texture for the button, the
font the button will use, The location of the button on the screen, the text to
be displayed on the button, the location of the text in the button, a SpriteBatch,
a variable to hold the current state of the mouse and the last state of the mouse.
I also added a field to say the button was clicked and one for text that will be
displayed when the button is clicked. These last two will not appear in the final
version.
Here are all the fields for the button:
Texture2D image;
SpriteFont font;
Rectangle location;
string text;
Vector2 textLocation;
SpriteBatch spriteBatch;
MouseState mouse;
MouseState oldMouse;
bool clicked = false;
string clickText = "Button was Clicked!";
The field that might require explanation is the location field. I used a Rectangle
instead of a Vector2. I did this because I wanted to use the first overload of the
Draw method and I wanted to be able to scale the control later.
With that done, I will give the rest of the code for the Button class and then go
over the highlight. You will see that I made the fields private and only exposed
a few of them These are the fields:
public Button(Texture2D texture, SpriteFont font, SpriteBatch sBatch)
{
image = texture;
this.font = font;
location = new Rectangle(0, 0, image.Width, image.Height);
spriteBatch = sBatch;
}
public string Text
{
get { return text; }
set
{
text = value;
Vector2 size = font.MeasureString(text);
textLocation = new Vector2();
textLocation.Y = location.Y + ((image.Height / 2) -
(size.Y / 2));
textLocation.X = location.X + ((image.Width / 2) - (size.X
/ 2)); }
}
public void Location(int x, int y)
{
location.X = x;
location.Y = y;
}
public void Update()
{
mouse = Mouse.GetState();
if (mouse.LeftButton == ButtonState.Released && oldMouse.LeftButton
== ButtonState.Pressed)
{
if (location.Contains(new Point(mouse.X, mouse.Y)))
{
clicked = true;
}
}
Text = "Click Me";
oldMouse = mouse;
}
public void Draw()
{
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
if (location.Contains(new Point(mouse.X, mouse.Y)))
{
spriteBatch.Draw(image,
location,
Color.Silver);
}
else
{
spriteBatch.Draw(image,
location,
Color.White);
}
spriteBatch.DrawString(font,
text,
textLocation,
Color.Black);
if (clicked)
{
Vector2 position = new Vector2(10, 75);
spriteBatch.DrawString(font,
clickText,
position,
Color.White);
}
spriteBatch.End();
}
The constructor of the Button class takes three parameters: the image for the button,
the font for the button and a SpriteBatch object. I don't think I did anything in
the constructor that needs explanation.
The Text property may require a little explanation. The get is simple, it just returns
the text. It is the set that is interesting. In the set the text field to the value
passed. Then I get the size of the text to be written in the button. After that
I create a vector to hold where the text will be drawn. Then I did a little magic.
I take the size of the button, divide that by 2, find the size of the text and divide
that by 2. Subtract that from the height or width of the button and add it to the
X and Y coordinates of the button to center the text in the button.
I used a method to set the location of the button on the screen.
In the Update method I get the state of the mouse. I check to see if the left button
has been pressed and released. If the location of where the mouse has been clicked
is inside the control, I set clicked to true. You will see that I keep setting the
text of the button using the Text property. I found that if I didn't do this it
would not draw properly in the control.
Finally there is the Draw method. I probably could have made a field for the
hover event but I just checked if the mouse was inside the button in the Draw method.
The Draw method is like the Draw method in the Game class. It makes a call to Begin
of the SpriteBatch setting it to AlphaBlend because I made the corners a little
rounded. If the mouse is inside the button it draws the button, tinting the button
silver, otherwise it draws the button with no tint. Then it draws the text inside
the button. Finally, if the button has been clicked it draws a message on the screen.
That is all for the Button class. It is time to turn your attention to the Game1.cs
file. I've added the code and the image I used for the button. You will have to
download this to get the image for the button. Once you unzipped the file you will
need to add the image to the Content folder. You will also need to add a SpriteFont
to the Conent folder. You do this by right clicking the Conent folder and adding
a new item. Click SpriteFont and call it myFont.
Go ahead and add these two variables to your program:
Button button;
SpriteFont myFont;
Before you can use the mouse, you have to make it visible. You do that by setting
the IsMouseVisible property to true. I did it in the Initialize method. Here's the
code:
protected override void Initialize()
{
IsMouseVisible = true;
base.Initialize();
}
Now it is time to turn your attention to the LoadContent method. In the LoadConent
method you will load in the texture for the button and the SpriteFont, then create
the button. I don't think that there is anything that you are not familiar with
so I'm just going to give you the code.
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
Texture2D texture;
texture = Content.Load("button");
myFont = Content.Load("myFont");
button = new Button(texture, myFont, spriteBatch);
}
Now it is time for the Update method. All the Update method does is set the location
of the button and call the button's Update method. Here's the code:
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
button.Location(10, 10);
button.Update();
base.Update(gameTime);
}
That just leaves the Draw method. All the Draw method does is call the button's
Draw method.
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
button.Draw();
base.Draw(gameTime);
}
Well, that is all you need to do to create a simple button.
Thanks again for reading this.