• File → New Project

    Adding Sound Effects (TriangleShooter)


    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.

    SoundEffect Variables
    1. SoundEffect fire;
    2. SoundEffect enemyHit;

    Loading the content is straightforward and similar to the previous loading of content we’ve done.

    1. fire = Content.Load<SoundEffect>("UI_Misc17");
    2. enemyHit = Content.Load<SoundEffect>("UI_Misc13");

    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.

    Code Snippet
    1. if (new Rectangle((int)enemy.Position.X - enemy.Avatar.Width / 2, (int)enemy.Position.Y - enemy.Avatar.Height / 2, enemy.Avatar.Width, enemy.Avatar.Height).Contains((int)b.Position.X, (int)b.Position.Y))
    2. {
    3.     bullets.Remove(b);
    4.     enemies.Remove(enemy);
    5.     enemyHit.Play();
    6.     score++;
    7.     if (score > highScore)
    8.     {
    9.         highScore = score;
    10.     }
    11.     break;
    12. }

    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.

    Shooting with a sound effect
    1. if (timeToShoot <= TimeSpan.Zero)
    2. {
    3.     timeToShoot = new TimeSpan(0, 0, 0, 0, ShootDelay);
    4.     bullets.Add(new Bullet() { Avatar = txBullet, Position = new Vector2(player.Position.X + player.Avatar.Width * (float)Math.Cos(player.Rotation), player.Position.Y + player.Avatar.Height * (float)Math.Sin(player.Rotation)), Rotation = player.Rotation, Speed = 15f });
    5.     fire.Play(.5f, 0f, 0f);
    6. }

    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.

    Download the latest version of the source code.

  • File → New Project

    Using the Accelerometer (TriangleShooter)


    This week, we’ll be using the accelerometer to move the player around. For those of you without a device, this one is going to be a bit tricky, as the emulator has no support for the accelerometer at this time. To do this, we’ll put in a check to see whether we are running on a device or an emulator, and use the accelerometer if it’s the device, and multi-touch if it’s the emulator. To begin, grab the latest version of the code from the SkyDrive share.

    In order to use the accelerometer, we’ll need to add an assembly reference to Microsoft.Devices.Sensors, and to test if the game is running on the emulator or a device, we add a reference to Microsoft.Phone. To add the reference, right-click on the references folder in the TriangleShooter project, choose Add Reference, and choose the two references from the list. Additionally, the following Using statement will need to be added for easy access to the Accelerometer:

    Assembly for Accelerometer
    1. using Microsoft.Devices.Sensors;

    We’ll create a variable for the Acceleromter called accelerometer:

    Accelerometer Variable
    1. Accelerometer accelerometer;

    We’ll check to see if we are running on the device, and if so, initialize the variable, set up a method that will handle the accelerometer, and start the monitoring.

    Initializing the Accelerometer
    1. if (Microsoft.Devices.Environment.DeviceType == Microsoft.Devices.DeviceType.Device)
    2. {
    3.     accelerometer = new Accelerometer();
    4.     accelerometer.ReadingChanged += new EventHandler<AccelerometerReadingEventArgs>(accelerometer_ReadingChanged);
    5.     try
    6.     {
    7.         accelerometer.Start();
    8.     }
    9.     catch (AccelerometerFailedException)
    10.     {
    11.     }
    12. }

    The method monitoring the reading changed event will update the position and rotation similar to the method we used around multi-touch.

    Accelerometer ReadingChanged
    1. void accelerometer_ReadingChanged(object sender, AccelerometerReadingEventArgs e)
    2. {
    3.     if (!isPlayerDead && player != null)
    4.     {
    5.         Vector2 direction = new Vector2(Math.Max(-.5f, Math.Min(.5f, (float)-e.Y)), Math.Max(-.5f, Math.Min(.5f, (float)-e.X)));
    7.         player.Rotation = (float)(Math.Atan2(direction.Y, direction.X));
    9.         player.Position += direction * player.Speed;
    11.         player.Position = new Vector2(Math.Min(Math.Max(player.Position.X, 0), 800), Math.Min(Math.Max(player.Position.Y, 0), 480));
    12.     }
    13. }

    If you make only these changes, the accelerometer will work, but the player won’t move around, because we never actually set the player speed. We can update the player initialization to the following to make that happen.

    Player Initialization
    1. player = new Player() { Avatar = txPlayer, Position = new Vector2(100f, 240f), Rotation = 0f, Speed = 15f };

    Finally, we’ll update the UpdatePlayer method to check if the game is running on the emulator, and use the multi-touch if it is.

    1. private void UpdatePlayer()
    2. {
    3.     if (Microsoft.Devices.Environment.DeviceType == Microsoft.Devices.DeviceType.Emulator)
    4.     {
    5.         foreach (TouchLocation tl in TouchPanel.GetState())
    6.         {
    7.             if (tl.State == TouchLocationState.Pressed)
    8.             {
    9.                 if (movementId == 0)
    10.                 {
    11.                     movementId = tl.Id;
    12.                 }
    13.             }
    15.             if (tl.Id == movementId)
    16.             {
    17.                 Vector2 direction = tl.Position - player.Position;
    19.                 if (direction.LengthSquared() > 100)
    20.                 {
    21.                     direction.Normalize();
    23.                     player.Rotation = (float)(Math.Atan2(direction.Y, direction.X));
    25.                     player.Position += direction * 10;
    26.                 }
    27.             }
    29.             if (tl.State == TouchLocationState.Released)
    30.             {
    31.                 if (tl.Id == movementId)
    32.                 {
    33.                     movementId = 0;
    34.                 }
    35.             }
    36.         }
    37.     }
    38. }

    Now we run with multi-touch on the emulator, and the accelerometer on the device.

    At this point, we’re pretty complete as far as the game goes. There are a few things we can do to clean up the code, and to improve the gameplay, and I will post updates as I continue with the project, but next week, we’ll be introducing a new project, so stay tuned.

    Download the latest version of the source code.

  • File → New Project

    Back from the Phone Camps!


    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

    watch it here

    Part 4: Windows Phone 7.5 Fast Application Switching, Tombstoning and Multitasking

    watch it here (Me!)

    Part 5: Live Tiles and Push Notifications

    watch it here

    Part 6: Building Games for Windows Phone 7.5

    watch it here (Me!)

    Part 7: Monetizing a Windows Phone 7.5 Application

    watch it here


    Hi Everybody

    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, 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.

  • File → New Project

    Adding Shooting (TriangleShooter)


    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:

    1. using Microsoft.Xna.Framework;
    2. using Microsoft.Xna.Framework.Graphics;
    4. namespace TriangleShooter
    5. {
    6.     class Bullet
    7.     {
    8.         public Texture2D Avatar { get; set; }
    9.         public Vector2 Position { get; set; }
    10.         public float Rotation { get; set; }
    11.         public float Speed { get; set; }
    12.     }
    13. }

    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.

    Variables for Bullets
    1. const int ShootDelay = 250;
    2. TimeSpan timeToShoot;
    4. List<Bullet> bullets;
    5. Texture2D txBullet;

    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.

    1. bullets = new List<Bullet>();
    3. timeToShoot = new TimeSpan(0, 0, 0, 0, ShootDelay);

    And add some code into the LoadContent method to load in the texture.

    1. txBullet = Content.Load<Texture2D>("Bullet");

    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.

    1. timeToShoot -= gameTime.ElapsedGameTime;
    3. if (timeToShoot <= TimeSpan.Zero)
    4. {
    5.     timeToShoot = new TimeSpan(0, 0, 0, 0, ShootDelay);
    6.     bullets.Add(new Bullet() { Avatar = txBullet, Position = new Vector2(player.Position.X + player.Avatar.Width * (float)Math.Cos(player.Rotation), player.Position.Y + player.Avatar.Height * (float)Math.Sin(player.Rotation)), Rotation = player.Rotation, Speed = 15f });
    8. }
    10. foreach (Bullet b in bullets.ToList())
    11. {
    12.     b.Position = new Vector2(b.Position.X + b.Speed * (float)Math.Cos(b.Rotation), b.Position.Y + b.Speed * (float)Math.Sin(b.Rotation));
    14.     if (!graphics.GraphicsDevice.Viewport.Bounds.Contains(new Point((int)b.Position.X, (int)b.Position.Y)))
    15.     {
    16.         bullets.Remove(b);
    17.     }
    18.     else
    19.     {
    20.         foreach (Enemy enemy in enemies.ToList())
    21.         {
    22.             if (new Rectangle((int)enemy.Position.X - enemy.Avatar.Width / 2, (int)enemy.Position.Y - enemy.Avatar.Height / 2, enemy.Avatar.Width, enemy.Avatar.Height).Contains((int)b.Position.X, (int)b.Position.Y))
    23.             {
    24.      ��          bullets.Remove(b);
    25.                 enemies.Remove(enemy);
    26.                 break;
    27.             }
    28.         }
    29.     }
    30. }

    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.

    1. foreach (Bullet b in bullets)
    2. {
    3.     spriteBatch.Draw(b.Avatar, b.Position, null, Color.White, b.Rotation, new Vector2(b.Avatar.Width / 2, b.Avatar.Height / 2), 1f, SpriteEffects.None, 0f);
    4. }

    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.

    Download the latest version of the source code.

  • File → New Project

    Adding Multiple Enemies with AI (TriangleShooter)


    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.

    Rotating the Enemy
    1. enemy.Rotation += ((float)Math.PI / 30f) % ((float)Math.PI * 2);

    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.

    Drawing the Rotated Enemy
    1. spriteBatch.Draw(enemy.Avatar, enemy.Position, null, Color.White, enemy.Rotation, new Vector2(enemy.Avatar.Width, enemy.Avatar.Height) / 2, 1f, SpriteEffects.None, 0f);

    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.

    Follow AI
    1. Vector2 enemyDirection = player.Position - enemy.Position;
    3. if (enemyDirection.LengthSquared() > enemy.Speed * enemy.Speed)
    4. {
    5.     enemyDirection.Normalize();
    7.     enemy.Position += enemyDirection * enemy.Speed;
    8. }

    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.

    Creating an Enemy
    1. enemy = new Enemy();
    2. enemy.Avatar = txEnemy6;
    3. enemy.Position = new Vector2(600f, 200f);
    4. enemy.Rotation = 0f;

    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:

    Using Object Initialization
    1. enemy = new Enemy() { Avatar = txEnemy6, Position = new Vector2(600f, 200f), Rotation = 0f, Speed =  3f};

    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

    Single Enemy
    1. Enemy enemy;

    with a List of Enemy

    List of Enemy
    1. List<Enemy> enemies;

    and initialize it in the Initialize method.

    Initializing enemies
    1. enemies = new List<Enemy>();

    in the LoadContent method, replace the line

    enemy initialization
    1. enemy = new Enemy() { Avatar = txEnemy6, Position = new Vector2(600f, 200f), Rotation = 0f, Speed = 3f };

    with the following few lines. This will create three separate enemies, each with a different speed.

    Adding enemies
    1. enemies.Add(new Enemy() { Avatar = txEnemy6, Position = new Vector2(600f, 200f), Rotation = 0f, Speed = 3f });
    2. enemies.Add(new Enemy() { Avatar = txEnemy6, Position = new Vector2(600f, 300f), Rotation = 0f, Speed = 3.5f });
    3. enemies.Add(new Enemy() { Avatar = txEnemy6, Position = new Vector2(600f, 400f), Rotation = 0f, Speed = 4f });

    the Update method needs to add a foreach loop around the area we’re using enemy. It will look like this

    Updating each Enemy
    1. foreach (Enemy enemy in enemies)
    2. {
    3.     enemy.Rotation += ((float)Math.PI / 30f) % ((float)Math.PI * 2);
    5.     Vector2 enemyDirection = player.Position - enemy.Position;
    7.     if (enemyDirection.LengthSquared() > enemy.Speed * enemy.Speed)
    8.     {
    9.         enemyDirection.Normalize();
    11.         enemy.Position += enemyDirection * enemy.Speed;
    12.     }
    14.     if (new Rectangle((int)enemy.Position.X, (int)enemy.Position.Y, txEnemy6.Width, txEnemy6.Height).Contains((int)player.Position.X, (int)player.Position.Y))
    15.     {
    16.         triangleColor = Color.Red;
    17.     }
    18. }

    and a foreach around the enemy in Draw

    Drawing each Enemy
    1. foreach (Enemy enemy in enemies)
    2. {
    3.     spriteBatch.Draw(enemy.Avatar, enemy.Position, null, Color.White, enemy.Rotation, new Vector2(enemy.Avatar.Width, enemy.Avatar.Height) / 2, 1f, SpriteEffects.None, 0f);
    4. }

    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.

    Download the latest version of the source code.

Page 5 of 8 (37 items) «34567»