Guardian Playtest Release

November 7, 2009 by Dave · Leave a Comment
Filed under: Game Programming, XNA 

Just uploaded the next version of Guardian for playtesting (you’ll need to be an XNA Creators Club member and signed in to follow the link successfully).  There were lots of changes this time around.  Over 250 items checked off of the todo list, many of them polish type things, but also some very major changes and additions, including these:

  • Supports multiple control configurations. The “standard” set is default and uses suggestions received from the last playtest
  • 2-4 player cooperative play
  • Comprehensive tutorial
  • Cleaned up the help “wall of text” somewhat
  • Added “demo mode” to allow watching how the game is played – this will also function as “attract mode” in a later version
  • Added 4 difficulty levels: Easy, Normal, Hard, Legendary
  • High scores for each difficulty level
  • Cooperative high scores for each difficulty level
  • Global (peer-to-peer) high scores for each difficulty level
  • The background nebula is now animated in the menus
  • Background nebula regenerated for each new wave
  • Increased sprite sizes
  • Show ammo level on selected weapon, eliminated inventory display
  • Automatically switch back to laser canon if out of ammo

I have a couple more things to finish up and then I’ll probably release another version before the 7 day playtest is up.  If that all goes well I’ll be submitting it for review in a couple of weeks!

Sprite Sheet Creator

August 25, 2009 by Dave · 1 Comment
Filed under: C#, Game Programming, Tools, XNA 

When developing the iPhone version of Guardian I manually created my sprite sheets.  I used individual sprites up until the end so everything was pretty much set in stone by the time I created the the sprite sheet.  Even then I ended up having to recreate the sprite sheet two or three times, and let me tell you, manually figuring out the texture coordinates isn’t a particularly pleasant experience. In this case I believe I made the right choice.  There were few enough sprites that I would have spent more time creating the tool than I would have saved.

The XBox version has quite a few more sprites, so I decided that spending time creating a sprite sheet tool was going to be well worth the effort.  It didn’t take too long to get it working well enough to use, and not too much longer than that to make it solid enough for distribution.

Sprite Sheet Creator

The application is released as open source under the MIT License.

Download SpriteSheetCreator.zip

Dream Build Play 2009

August 7, 2009 by Dave · Leave a Comment
Filed under: Dream Build Play, XNA 

I managed to make the deadline for entering the Dream Build Play 2009 competition.  The results are expected to be announced by the end of the month.  Based on the quality of entries this year I’m not holding out a huge amount of hope of actually winning.  Regardless, it was a great experience and I learned quite a bit in the process.

As part of the contest submission we wrote up a game description including play instructions and some comments on the technical design, as well as a video trailer.  The video is below, and the documentation I submitted follows. Many of the other entries have posted videos in the Dream Build Play 2009 YouTube group.  And you can see all of the contest entries in the Dream Build Play Gallery.

I still have a few more things to do on the game before I put it up for sale on the XBox, but I’m going to take a bit of a break before continuing on. I should have more time to update this blog as well. Thanks for reading – hope you enjoy the video.

 

 

Guardian

Game Play

The overriding premise of the game is to keep asteroids from hitting your planet, and alien ships from shooting it. Your planet will be damaged as it’s hit, and when the damage reaches the planet center the game is over.  You’re competing for high score, with the top ten high scores are tracked locally.

You command a satellite that constantly orbits the planet.  Pressing A fires your selected primary weapon from the satellite towards the red target indicator that you move with the left thumbstick to aim your shots.  You have to be careful to time your shots so the planet isn’t in between the satellite and the target.  Your main weapon is the Laser Canon and has infinite shots available.  The Plasma Canon is more powerful and the shots move faster.  The Rail Gun is an instantaneous kill, and will destroy anything in its path, including taking out a large portion of your planet if it’s in the way.  You will receive large cumulative bonuses for killing multiple enemies with a single Rail Gun shot.  Each primary weapon has a different charge rate which limits how often you can fire.  As mentioned, the Laser Canon has infinite shots, but all other weapons require ammunition.

Pressing Y fires your selected secondary weapon.  These weapons fire from the surface of the planet.  Missiles will automatically target the asteroid or enemy ship closest to the red target – it takes a second or two for the missile to lock on.  Nuclear Missiles will target the actual red target location, so you can fire them at a point in space and use the large blast radius to take out multiple targets.  The BG4143 will destroy everything on the screen by sending out a shockwave with an ever increasing radius.

Alien ships will drop a powerup after destruction.  You grab the powerup by moving the target close by and using X to activate the planetary tractor beam.  The beam will slowly pull the powerup to the planet, after which it will be used or automatically added to your inventory.  Powerups can add energy to your shields or primary weapon, add maximum shield/weapon energy, and increase shield/weapon charge rate. Powerups will also make ammunition available for the various secondary weapons.

You cycle your primary weapon by pressing the Right trigger, and cycle the secondary weapon using the Left trigger.  The right shoulder button will generate a new background at any time, and the left shoulder button displays your current weapon inventory during game play.

Shields work on their own with no intervention.  They will protect your planet for awhile but have a slow charge rate which can be increased by powerups.  Once the shield power is used up asteroids or enemy fire will damage your planet.  However the shield will continue to recharge as long as nothing is hitting it.

There are 32 asteroids in each wave, and 0 to 3 enemy ships.  There are also bonus asteroids and comets that will move by your planet quickly.  These can be difficult to hit, but you’ll receive a bonus score for destroying them.  They will never hit your planet, but they do come in close enough to hit the satellite and destroy it.  The asteroids and ships start out fairly slowly, but they speed up over time until they’re moving quite rapidly.

Development and Design

A limited version of Guardian was originally created for the iPhone, but I wasn’t happy developing on that platform so I made the decision to port it to XNA and XBox and add much of the functionality I had originally planned for the iPhone.

Most of the game uses basic 2D technology: Sprite sheets, particle systems, state machines, and the like.  Collision detection is mostly accomplished through point-in-circle tests.  However the planetary collision detection uses pixel tests since the planet is eaten away throughout the game.

Some of the more interesting technicalities are described in the following sections.

Background Nebula

The background nebulae are generated using a pixel shader which uses fractal brownian motion and other procedural techniques to build a random cloud and star texture.  Each time you see a new background it was generated in real time.  The backgrounds can actually be animated at 60fps to get some very nice moving nebula effects, but combining it with the rest of the game dropped me down to 30fps.  At some point I plan to optimize it some more.

It is also interesting to note that the backgrounds are generated entirely on the GPU and exist entirely in video memory.

Planet Generation

The planets are also procedurally generated, and are actually 3D.  The basic spherical structure is a cube, and a mapping function is used to move each vertex out to the sphere’s radius, and then the noise functions are used to add the height value.  A second sphere is used for the ocean areas.  Each time the game is started you get a new planet.  In future versions I plan to allow regenerating the planet, as well as having different texture sets to allow for non-Earth type planets.

Generating the planet in 3D allowed me to show the planet rotating in the menu areas, with a seamless transition to the game play area by simply moving the camera out to the proper location using the SmoothStep function.  The planet displayed during game play is still 3D, and can actually be rotated, but it looks kind of strange since the craters don’t move with it.

Planet Craters

The craters are created by drawing one of several random crater sprites into a mask texture each time damage is done to the planet.  The mask texture holds the cumulative result of each crater application.  Before drawing the planet the mask is used to set the stencil buffer, then the planet is drawn with the craters masked out.

Yet Another Guardian Progress Video

July 19, 2009 by Dave · Leave a Comment
Filed under: Game Programming, XNA 

Things are coming along nicely with Guardian. The Dream Build Play entry deadline is fast approaching, but I think I’m in pretty good shape to get my entry completed. The video shows most of the functionality. Pretty much all that’s left now is fleshing out some of the graphics, and adding a few more weapons. Then I can start getting some sleep.

XNA Game Project

June 24, 2009 by Dave · Leave a Comment
Filed under: Game Programming, XNA 

Here’s a video of the XNA game I’ve been working on. It’s a port of the iPhone version with some additional functionality planned.

Simplified XNA Message Boxes

June 11, 2009 by Dave · Leave a Comment
Filed under: C#, Game Programming, XNA 

Shawn Hargreaves brings up the subject of how annoying async coding can be.  Calling a “begin” method, dealing with the completion callback function, handling the results – it’s all very ugly to keep track of, and often leads to very ugly code.

He wants to be able to write code like this (and so do I)…

 

 int? button = Guide.ShowMessageBox("Save Game",
                                       "Do you want to save your progress?",
                                       new string[] { "OK", "Cancel" },
                                       0, MessageBoxIcon.None);

    if (button == 0)
    {
        StorageDevice storageDevice = Guide.ShowStorageDeviceSelector();

        if (storageDevice != null)
        {
            using (StorageContainer storageContainer = storageDevice.OpenContainer("foo"))
            {
                ...
            }
        }
    }

 

 

It turns out that making async code work almost like this isn’t too bad to do. It basically involves creating a static class to encapsulate all of the various things you need to keep track of. Here is the fairly well commented code for the static class.

class SimpleMessageBox
  {
    private static int? dialogResult = null;
    public static bool Showing { get; set; }

    public static int? ShowMessageBox(string title, string text, IEnumerable  buttons, int focusButton, MessageBoxIcon icon)
    {
      // don't do anything if the guide is visible - one issue this handles is showing dialogs in quick
      // succession, we have to wait for the guide to go away before the next dialog can display
      if (Guide.IsVisible) return null;

      // if we have a result then we're all done and we want to return it
      if (dialogResult != null)
      {
        // preserve the result
        int? saveResult = dialogResult;

        // reset everything for the next message box
        dialogResult = null;
        Showing = false;

        // return the result
        return saveResult;
      }

      // return nothing if the message box is still being displayed
      if (Showing) return null;

      // otherwise show it
      Showing = true;
      Guide.BeginShowMessageBox(title, text, buttons, focusButton, icon, MessageBoxEnd, null);
      return null;
    }

    private static void MessageBoxEnd(IAsyncResult result)
    {
      dialogResult = Guide.EndShowMessageBox(result);

      // if no button was pressed then we want the result to be -1
      if (dialogResult == null)
        dialogResult = -1;
    }

 

Using the class involves calling SimpleMessageBox.ShowMessage(…) in your Update() method. You continue to call it each frame until it returns a result. This does require some game state information (i.e. your game state is SaveGameState or something similar) so it takes a little extra work, but you have to keep track of those sorts of states anyway.

Here’s a sample of the usage:

protected override void Update(GameTime gameTime)
    {
      base.Update(gameTime);

      if (saveGame)
      {
        // show the message box - we end up calling this each frame as long as we're in the saveGame state - it will
        // return null until the user presses a button or closes the guide - it returns -1 if the guide
        // is closed, otherwise it returns the button number
        int? button = SimpleMessageBox.ShowMessageBox("Save Game", "Do you want to save your progress?",
                                                      new string[] { "OK", "Cancel", "Repeat" }, 0, MessageBoxIcon.None);

        switch (button)
        {
          case -1:
            message = "No Button";
            saveGame = false;
            break;

          case 0:
            message = "Saved";
            saveGame = false;
            break;

          case 1:
            message = "Cancelled";
            saveGame = false;
            break;

          case 2:
            message = "Repeat";
            break;
        }
      }
    }

 

I haven’t use this code in a real project yet (just the sample), but it seems like it would work in quite a few situations. It’s a bit different than doing a message box in Windows since you have to realize you’re calling the ShowMessageBox method each frame. That aside, you can almost imagine that you’re using a blocking message box function.

Download Sample Project

« Previous PageNext Page »