Windows Phone Resources
This week, I’m going to go over how to break out Player and Enemy into classes, which will make it easier to handle multiple enemies, collision, AI, that sort of thing. We’ll be starting things off with the project from last week, so you can go grab that now.
If you take a look at how we’ve been doing things, you’ll notice that I have been using only the file game1.cs, which was automatically generated for me. When I added an enemy, in order to track its position, I created a variable called enemyPosition, because I was already using position for my player. If I wanted to add another enemy, I would have to do something like enemyTwoPosition or enemy2Position, and the next enemy after that would have to be enemy3Position, and it would just be a pain to have to keep track of all of those and copy all of the attributes for each new instance. It would also be a pain to have to check every instance for their collision, and to have to draw each one. If I changed something in one, I’d have to change it in all of them, and missing one of them could result in a bug that might not be noticed right away, when it would be easiest to fix. That’s why I’m going to break out the player and enemy into their own classes. I’m not going to go into subclassing, although there are a good number of shared attributes that would make it make sense to do so.
Let’s take a look at what we have, first.
We only have a texture and a position for the enemy, because it was static in the last article. It would make sense to add rotation to it, as well as a speed variable that will allow us to have different classes of enemies with different speeds. To begin, we’ll need to create a new class. Right click on the TriangleShooter project in the Solution Explorer, and choose Add –> Class. When it asks for a filename, type in Player.cs. Add another class, and name this one Enemy.cs. The contents of the two files is below:
Essentially, they are the same thing. That’s why I said that you could do well with subclassing, but we’ll keep it like this. I also added Speed onto Player, which will be useful a bit later in the series when I get into fine-tuning your game to make it more fun to play. To take advantage of the new classes, we’ll make a few changes to the game1.cs file. Namely, we’ll modify the variable declaration, the Initalize method, LoadContent, Update, and Draw. We’re just refactoring here. No changes to how the game plays are made in this modification.
We move most of the initialization until after LoadContent, since we need to load the textures.
Here is where we set up the Player and Enemy instances.
In the Update method, we switch everything over to use the classes.
And the same with Draw
This sets us up perfectly to begin adding additional enemies into the game. Next week, I’ll go ahead and do that, and add some basic AI to the enemies.
Download the latest version of the source code.
This week, we’re going to liven the game up a bit by adding sound effects. While I am pretty amazing at drawing triangles and other figures that you can create without any artistic skills, I have even less skills making sounds. Luckily, there are some places we can get some free sounds to use in our game. We’ll be using a collection of sounds from the AppHub’s SoundLab project, so you can grab that, and pick up the source code from last week from the SkyDrive share.
This one is going to actually be pretty easy. To start with, we’ll grab the sounds from the SoundLab project, and pick a couple that we think might work for the game. You could go with some gun sounds if you are feeling in a more aggressive mood, but I feel that some of the sounds in the UI folder actually work better for the feel of the game. I picked UI_Misc13.wav for the sound of a bullet hitting an enemy, and UI_Misc17.wav for the shooting sound. So the first thing we need to do is grab the files we picked, and drop them into the TriangleShooterContent project. Once they are added in, we can set up a variable for them, load them from the content project, and then play them.
The variables are of type SoundEffect, so we’ll set one up for firing, and the other for when the enemy gets hit.
Loading the content is straightforward and similar to the previous loading of content we’ve done.
And playing them is a simple matter as well. The collision sound is good how it is, so we don’t need to tweak it at all. We can just use the default method signature with no arguments.
The firing sound effect is a bit loud for how often it happens, so we use the overload that allows you to define the volume, pitch modification, and panning. about 50% volume seems good.
And really, that’s it. Well that was easy. Next week, we’ll refactor the code to make it easier to read and make some tweaks to the gameplay.
Let’s make TriangleShooter a better game. This time around, we’ll be putting the shooter in TriangleShooter, by adding in the ability for the player to shoot. We’ll be starting with last week’s code, so you can go over and grab that from my SkyDrive share.
I tried a few different ways of making the player shoot in my development of the game, and the best one I have found so far is to have you always laying out a steady stream of shots. Towards the end of the series, I’ll be doing some play mechanics tweaking, and we can investigate some of the other ways, but that’s how I’m going to do things in this article.
If you’re going to shoot, you need a bullet. You can get my highly stylized, square bullet from the SkyDrive share. To begin with, download that, then add it into the TriangleShooterContent project by dragging it and dropping it in there. We’ll also need a class to handle the bullet, which is going to look familiar. Create a new class in the TriangleShooter project named Bullet.cs, and set the content to the following:
We’ll set up the variables at the top of the game class to hold the texture, the list of Bullets, and to monitor the passing time to shoot, along with a constant to tweak the timer a bit.
In the Initialize method, we set up the list for the bullets, and set the time to shoot from the constant value we set up.
And add some code into the LoadContent method to load in the texture.
And now we’ve got everything we need. We only have the Update and Draw to go. The Update is more interesting, so let’s start there.
The first part of the code is similar to what we do to spawn enemies. We subtract the elapsed time from the remaining time, and if the time is less than zero, we spawn a new bullet, setting it’s position to the front of the player and the rotation to the players rotation. We then update all existing bullets. Because we may need to remove them from the master list, we make a copy in the foreach by using the .ToList() function. We move them in the direction based on their rotation, and see if they have left the bounds of the screen. If they have, we remove them from the update list. To optimize things here, we should do something like create a list of decommissioned bullets, and reuse them rather than creating new ones each time, but we won’t do that this time around. If they are within the bounds of the screen, we check collision with each of the enemies, again using the .ToList() function because we might need to remove items. If they collide, we remove both the bullet, and the enemy that collided with it.
This is all we need to do, but we do need to draw the bullets. Luckily, this is a simple process, just add a few lines into Draw.
And now we have shooting!
Next week, we’ll do some refactoring to make the code easier to work with, and see if we can add in some death behavior.
Over the last couple months, I’ve been spending a lot of my time on the road presenting at at least a Phone Camp a week. We did nine cities in the West Region, and of those, I presented at seven. I also made it to a couple of Code Camps, and helped out at some of our other major events like the HTML 5 Web Camp. If you didn’t get a chance to attend one of the camps, and want to see me in action, I was recorded at the Sunnyvale Phone Camp hosted at Nokia, and the recordings are available through the links below.
Part 1: Windows Phone 7.5 Overview for Developers
watch it here
Part 2: Building Windows Phone 7.5 Applications with Visual Studio 2010
watch it here (Me!)
Part 3: Building Windows Phone 7.5 Apps with Silverlight
Part 4: Windows Phone 7.5 Fast Application Switching, Tombstoning and Multitasking
Part 5: Live Tiles and Push Notifications
Part 6: Building Games for Windows Phone 7.5
Part 7: Monetizing a Windows Phone 7.5 Application
watch it here
Being at all those camps was incredibly fun, but of course it meant that I was pretty busy. In the little free time that I had, I tried to keep up with the emails I had coming in, but I could only get so far each time before I had to rush off to the next event. Over the next few days I hope to get through the remainder of what I have sitting in my inbox, but if you haven’t heard back from me I recommend you send me a ping with the original email to bump yourself to the top of my inbox, since my process is to go from the newest emails back.
I also got a chance to meet some really cool people on the road, and hope to do some more events in some locations I hadn’t gotten much of a chance to visit like Portland. We’re working on the next series of events, including a few full day Game Development Camps where we’ll be going through how to get your game up and running using XNA, combining Silverlight and XNA, and going multi-platform. We’re still looking at whether we can get enough people in some of the cities, so if you want us to come to you, let me know.
The other thing I’m working on right now is getting my projects that I’ve been showing at all the camps to a point where they are ready to go online. Similar to the TriangleShooter series I posted starting about a year ago, I have a few other projects I will be chunking out into consumable slices. Of course, I still have the Language Learning Game, but I also have the first seven steps of an Augmented Reality sample in Silverlight, am working on the open source Geo Augmented Reality Toolkit over at http://gart.codeplex.com, a couple projects around the .NET Micro Framework using Netduino and Gadgeteer, and have four more projects that I will be putting into the marketplace and sharing code for. I’ll post updates here on my blog, and am working on recording video walkthroughs to be able to demonstrate everything more easily than screenshots, which is pretty important for samples like the Augmented Reality bit. I’m expecting to post at twice a week, with one of those posts being a continuation of whatever developer series I’m working towards.
If you are local to the Silicon Valley, tonight I’ll be at the Hacker Dojo for the final night of our “30 to Launch” event. I’ll be bringing some books to give away to the first people who ask me for them. I’ll also be at the Windows Phone Night Out on Wednesday in San Francisco. I won’t be able to bring books there, but I can see if I can bring something smaller with me to give out.
Another week, another article bringing us one step further in the creation of TriangleShooter. Last week, we did a bit of refactoring and broke Player and Enemy out into classes. At the time, this didn’t change anything in how the application worked, but this week, we’ll take advantage of it by adding in some basic AI, and then showing how easily you can scale out to more enemies. We’re going to be starting with the project we created worked on last week, so you can grab that from the SkyDrive Share.
The first thing we can do is make the enemy seem a bit more impressive. He was just sitting out there while we flew all around him just making fun of his inability to move. Well, let’s change that. We’ll begin by some basic animation. We’re not going into sprite frames or anything like that, a rotation should do. In the update method, we’ll add a line to update the enemy’s rotation. Let’s drop it in right before the collision detection. Rotation is handled as a float, in radians. That means that when the rotation is equal to 2*pi, it will be a single rotation. Since rotation is cyclical, and bounded between 0 and 2*pi, we can make use of the modulus operator to make sure that it doesn’t eventually exceed the boundary of what a float can handle.
We’ll need to update the Draw function as well, to make use of the newly updated rotation. We’ll use the same format as we did for the player. The main difference will be that the origin of rotation for the enemy will be the center.
If you run the application now, it works much like it did at the end of the last article, but now the enemy rotates. That simple change makes the visuals of the game quite a bit more interesting. It also gives us a great view into how easy it is going to be to add in some additional AI.
Let’s jump right into that. We’ve already seen how easy it is to make the player move towards a touch point. Let’s do the same thing with the enemy, and set the destination to the player. That’s the basis for follow AI. Add the following lines to the Update method right after the line that updates the rotation.
That’s it. We run the application, and now the enemy follows you around the screen. Programming is really easy, when you think about it.
The next step is to add more enemies. This is actually a lot easier than you might think. First, let’s look at how we are currently creating instances of the Enemy class.
As you can see, it takes four lines of code, and we aren’t even setting speed at this point. There are a couple of ways to condense this down, including creating a constructor, and using Object Initialization. In this case, let’s go ahead and use Object Initialization, which means that we will use the default constructor, then assign the values directly after in braces. I prefer this method in this case because when I read through the code, it is more explicit. You may prefer to use a constructor, which works just fine by me. Using Object Initialization, the previous code changes to the following:
You’ll notice that I added Speed in there while I was at it.
With this setup, it’s much easier to instantiate a full new Enemy with just a single line of code.
We had been using a variable called enemy defined throughout the class. To allow for more enemies, we’ll make use of a generic collection called List. Replace the line towards the top of game1 defining enemy
with a List of Enemy
and initialize it in the Initialize method.
in the LoadContent method, replace the line
with the following few lines. This will create three separate enemies, each with a different speed.
the Update method needs to add a foreach loop around the area we’re using enemy. It will look like this
and a foreach around the enemy in Draw
And again, that’s all. A couple more simple changes, and we’ve added support for as many enemies as we want.
Next week, we’ll add in some spawning code, and add in the rest of the enemy graphics to add in some variety.