Thursday, 23 December 2010

Tutorial 11 : Creating the GUI (Part 2)

In this tutorial we will be adding a generic button class to our project, and then we will be using this class to add buttons to our toolbar. We will keep this button class a general as possible so it can be re-used throughout the project.

The first thing we are going to do is add a new class in the GUI folder called “Button.cs” and make it inherit the Sprite class. Before we add anything to this class though, we are going to create a new enum just above it :

/// <summary>/// Describes the state of the button./// </summary>publicenum ButtonStatus{ Normal, MouseOver, Pressed,}

This constructor takes in three different textures, each one controls the appearance of the different button states. We also initialize the bounds rectangle to fit around the button based on the buttons position and the sizes of the texture.

Next we are going to add in a method to update the state of the button :

And that’s the button class finished for now, we will come back to it later to add in events.

Before we add a button to our toolbar we will need to add some new images to our project. Download the images I uploaded at the start of the tutorial and then add them into a new folder called GUI in the Content Project. I know these aren't the greatest images in the world but they’re the best my art skills can create!

Now we are ready to add a button to our toolbar, go back to “Game1.cs” and add a field for a button :

Button arrowButton;

Next we need to load in our button textures and pass them to our button, add the following to LoadContent :

We first check if the event is null, or in other words if anything attached itself to the event, and, if it has, we fire the event.

And that’s our button class finished for good! All that we have left to do is to attach our button to a method that when called, will allow the player to create a new arrow tower.

To do this we need to go back to “Game1.cs” and find where we initialized the button in the LoadContent method. Just under that we will hook up our event to a new method :

arrowButton.Clicked += new EventHandler(arrowButton_Clicked);

Now we need to add a new method called arrowButton_Clicked that will be called by the event :

privatevoid arrowButton_Clicked(object sender, EventArgs e)

{ player.NewTowerType = "Arrow Tower";}

When this method is called it tells the Player class that the player wants to build a new Arrow Tower, the only problem with this code is, the Player class doesn’t have a property called NewTowerType, let’s go to “Player.cs” now and add one :

// The type of tower to add.privatestring newTowerType;

publicstring NewTowerType{ set { newTowerType = value; }}

Now that we know what tower we want to build, we need a way to act on this information and create a new tower for the player, lets add a new method to handle this :

// Only add the tower if there is a space and if the player can afford it.if (IsCellClear() == true && towerToAdd.Cost <= money) { towers.Add(towerToAdd); money -= towerToAdd.Cost;

// Reset the newTowerType field. newTowerType = string.Empty; }}

What this method does is it checks what type of tower the player wants, and initializes one based on that information. It then checks if there is a space for that tower and also if the player can afford it, and if they can, we add the new tower to the game, charge the player for it, and reset the newTowerType field.

All that’s left to now is to go to the Update method and find the code that used to create tower’s for the player :

We’re finished! Hit the F5 key and try clicking on a clear space, you should find that no tower is created, however if you click the tower button first and then click a space you should find that a new tower is created and you should also see that the player’s money goes down.

Note : As I see it, there is only one more tutorial left in this series which will contain a small bug fix and a small addition to the GUI. However if you have any suggestions for any more tutorials in the series feel free to tell me then and I will see what I can do.

13 comments:

Hi, thanks for this excellent explanation. I was wondering if it maybe wouldn't be easier to make it so the button remains in the "pressed" state after clicking, then looping through all buttons to see which one is pressed and adding a tower of the appropriate type, before setting the button back to "normal". What do you reckon the drawbacks would be ?

That sounds like a perfectly good idea, how I would do this is add an event to the player class that fires when the player creates a new tower. It would probably need to be a custom event so you could pass the tower type to subscribing events.

Then in Game1 you would subscribe to the event and when the event is fired use the tower type that was passed to the event to update the button state.

Ooohh! And why is the enum of the different button states outside the class? Never seen that before.

And also, is it possible to make the method arrowButton_Clicked in another class then Game1.cs? I could make the player class public or make it in the method itself public and put it inside the player class? I probably should know this but my brain starting to overload trying to understand how everything works together :D.

If you are unsure or it isn't clear which code goes where, feel free to leave a comment and I will try to alter the article to make it more clear :).

As for the player fields, if you look back to Tutorial 6, the first two lines of code assign these values.

Putting the enum outside of the class is just personal preference. It is just a habit that I have gotten into so feel free to change it so it works better for you; everything should still work fine!

And finally, the arrowButton_Clicked can be put into any class as long as Game1.cs can still access it! For example, if you wanted to have that method in the player class, you would move the method to Player.cs and make it public. Then in Game1.cs in the LoadContent method simply change this :

Hey, I like your tuts very much! I am trying to convert this game for WP7, so that you can play it on touchscreen.My question is, do I have any advantage from handling the buttons inside the toolbar class?Means you add a list of buttons inside toolbar and construct them on toolbars constructor. Also updating and drawing would be inside the toolbar class.

I think it would make the code a lot cleaner especially if you are adding new buttons to it. I would add a method like AddButton() to the toolbar class as well to make it easy to add buttons. When a new button is added you could just set it's position to be the position of the last button in the list + the width of the last button + some offset!