DCSIMG
November 2010 - Posts - Pavel's Blog
Sign in | Join | Help

Pavel's Blog

Pavel is a software guy that is interested in almost everything
software related... way too much for too little time

November 2010 - Posts

The Case of the Unexplained Sharing Violation

Published at Nov 24 2010, 04:19 PM by pavely

(pardon to Mark Russinovich for the title “The case of…”).

This seemingly innocent code caused a sharing violation error (32) after a few iterations:

   for(int i = 0; i < 10000; i++) {

      sprintf_s(text, "Text from process %d\r\n", GetCurrentProcessId());

 

      HANDLE hFile = CreateFile(_T("c:\\temp\\test.txt"), GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0);

      if(hFile == INVALID_HANDLE_VALUE) {

         DWORD err = ::GetLastError();

         printf("Error opening file %d (%d)\n", err, i);

         break;

      }

 

      SetFilePointer(hFile, GetFileSize(hFile, NULL), NULL, FILE_BEGIN);

      DWORD bytes;

      WriteFile(hFile, text, strlen(text), &bytes, NULL);

      CloseHandle(hFile);

   }

It’s a simple loop, that opens a file, sets its file pointer to the end of the file, adds a string and closes the file. After a few iterations the CreateFile call fails with GetLastError returning 32 (sharing violation). This happens on some machines but not all. Sharing violation? Who else is opening my private file? It seems that no one.

If I open Process Explorer, press Ctrl+F and type test.txt to look for any process holding a handle to that file, I get nothing. Obviously, it’s closed already – too fast to catch manually.

The solution is to use Process Monitor, another great one from SysInternals. After setting a path filter for test.txt, this is what we find when the application is executed:

 

image

SyncDemo is my executable. The culprits are clearly shown: ekrn.exe (NOD32 antivirus) and SearchProtocolHost.exe.

The solution for this code is pretty simple: as these processes open the file for reading, I just need to change the sharing settings in CreateFile:

HANDLE hFile = CreateFile(_T("c:\\temp\\test.txt"), GENERIC_WRITE,

   FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0);

Thanks goes to Alon Fliess and Dima for ideas and brainstorming.

My TechEd 2010 Session

Published at Nov 19 2010, 03:26 PM by pavely

TechEd 2010 in Eilat is approaching fast. My session is about what MEF (from .NET 4)and Unity (from the Enterprise Library, but does not depend on it) can do for you and your code. If you’re new to MEF and wonder what that is and what it can do (and you’re not on your plane back to Israel center at that time), you might want to stop by. If you’re using the dependency injection idea with Unity, I’ll show some of the things Unity can do. It’s gonna be fun, mostly demos, and hey – it’s the last session in TechEd (Tuesday, 12:30), so what have you got to lose?

For those of you following my XNA 2D game tutorial series, I’ll have to take a break for few days (sorry) to prepare for my TechEd session. Don’t worry, though, I’ll get back on that in about a week or so. I estimate another 2-3 posts in that series (then again, I estimated internally another 2-3 posts about 6 posts ago…)

Hope to see you at TechEd, regardless of my actual session!

XNA 2D Game Tutorial (Part 11)

Published at Nov 17 2010, 07:25 PM by pavely

Previous posts in this series:

In the previous part we did some collision detection between the player’s missiles and the aliens. If hit, the alien disappeared gradually (as opposed to a big explosion). Let’s add some more collision detection.

First, a small bug fix: if we keep killing aliens, eventually new one won’t be generated. The reason is the Killed event is not handled and so the number of current “live” aliens never decreases…

This is fixable by adding handling of the Killed event like so:

alien.Killed += a => {

   _currentLiveAliens--;

};

 

Currently, the player is invincible – she cannot be killed or hurt in any way. It’s time to change that. We need to check each “live” alien with the player. If there’s a hit, we’ll create an explosion.

Where should we do the collision check? As usual in these cases, we can do that from either the aliens side or the player side. Which one is “better”? In this case I’d prefer doing it from the aliens side. Why? Because we’re already iterating over the aliens – all we need is add one additional check for collision with the single player sprite. If we’d go the other way around, we’d have to create another loop for checking against all aliens – less efficient.

First, we need access to the player component from the aliens component. we’ll do that similarly to the way we exposed the aliens component – by exposing it via a readonly field:

public readonly PlayerComponent PlayerComponent;

 

and setting it in the game’s constructor while creating the component:

Components.Add(PlayerComponent = new PlayerComponent(this));

 

The next thing we need to prepare is to expose the player’s sprite for external access (currently it’s a private field):

public Sprite Player { get { return _player; } }

 

Now we can actually implement the collision check in AliensComponent.Update:

var pc = AlienRaidGame.Current.PlayerComponent;

 

foreach(var alien in _aliens)

   if(alien != null && alien.Active) {

      alien.Update(gameTime);

      if(!alien.IsDying && pc.Player.Active && alien.Collide(pc.Player)) {

         // player hit!

         alien.Hit(5);   // alien hit, too!

         pc.Player.Active = false;   // deactivate for now

      }

   }

 

If we run the game now, any alien that hits the player causes the ship to disappear, never to appear again. Only one life right now!

Let’s add some explosion sprite when the player’s ship explodes and an explosion sound, too. We’ll use the 6 frame explosion inside the file sprites.png, which is already one of our game assets.

First, we’ll add a PlayerHit method to PlayerComponent, so that the player can handle its own hit logic:

public void PlayerHit(int power = 1) {

   // player always dies

   _player.Active = false;

   // setup explosion

   _playerExplodeSound.Play();

}

 

The player is simply deactivated. I’ve also added an explosion sound (in the usual way). When an alien collides with the player, this method should be called:

if(!alien.IsDying && pc.Player.Active && alien.Collide(pc.Player)) {

   // player hit!

   alien.Hit(5);   // alien hit, too!

   pc.PlayerHit();

}

 

This shifts the responsibility of handling hitting the player to the PlayerComponent, where it’s most appropriate.

Now for the explosion: we’ll add a Sprite field to hold it, and initialize it in a deactivated state:

_playerExplosion = new Sprite(_explosionTexture, new Rectangle(0, 153, 65, 66), 6, true, 1);

_playerExplosion.Active = false;

_playerExplosion.Origin.X = _playerExplosion.FrameWidth / 2;

_playerExplosion.AnimationInterval = TimeSpan.FromMilliseconds(400);

 

_explosionTexture is Texture2D object, created in LoadContent as usual. To make the explosion visible and animating, we need to add appropriate code to the Update and Draw methods (like we do with any sprite). Now we just need to activate the explosion when the player is hit:

public void PlayerHit(int power = 1) {

   // player always dies

   _player.Active = false;

   // setup explosion

   _playerExplodeSound.Play();

   _playerExplosion.Position = _player.Position;

   _playerExplosion.Active = true;

}

 

If we run now, we find out the when the player is hit, the explosion animation plays repeatedly instead of just once. We need to add this capability to the Sprite class. Add two fields to indicate whether one shot animation is enabled:

public bool OneShotAnimation;

public bool DeactivateOnAnimationOver = true;

 

DeactivateOnAnimationOver indicates if the sprite should automatically deactivate when the animation sequence is done (true by default). We need to update the Sprite.Update method to use these new fields:

public virtual void Update(GameTime gameTime) {

   if(Active) {

      if(TotalFrames > 1 && (_animElapsed += gameTime.ElapsedGameTime) > AnimationInterval) {

         if(++_currentFrame == TotalFrames) {

            _currentFrame = 0;

            if(OneShotAnimation) {

               _currentFrame = TotalFrames - 1;

               if(DeactivateOnAnimationOver)

                  Active = false;

            }

         }

         _animElapsed -= AnimationInterval;

      }

      Position += Velocity;

   }

}

 

Now let’s initialize the explosion to use one shot animation, and voila! We have explosions. The downloadable source also includes explosion sound for the aliens (and some minor bug fixes).

Although I promised displaying stats in this part, I’ll save that for the next part.

XNA 2D Game Tutorial (Part 10)

Published at Nov 16 2010, 10:45 AM by pavely

Previous posts in this series:

In the previous part we created a bunch of alien enemies that are moving down the screen. Currently, if they hit the player’s ship – nothing happens. If the player’s missiles hit an alien – nothing happens. We need some collision detection.

Collision detection in a 2D world is usually done with a simple approximation: that all sprites are rectangular. Although it’s possible (at least in theory) to use the actual “shape” of sprites to locate overlapping areas, this is impractical – it’s computationally expensive, and the benefits are too small. Collision detection may be used hundreds times per frame, so it must be quick. We’ll compare bounding rectangles of sprites and look for an intersection. To be less sensitive to “false positives” (non collisions flagged as collisions), we can reduce the bounding rectangles by some amount (say, 10 percent). If you ever played a game where you thought you hit something but you didn’t – well, maybe you did, and it just didn’t take because of that reduction (“false negative”). or you were sure you were hit, but survived – for the very same reason. This is a well known compromise that we can live with.

We’ll start by adding a property to the Sprite class that returns the bounding rectangle of a sprite:

public Rectangle BoundingRect {

   get {

      return new Rectangle(

         (int)(Position.X - Origin.X * Scale), (int)(Position.Y - Origin.Y * Scale),

         (int)(_rects[0].Width * Scale), (int)(_rects[0].Height * Scale));

   }

}

The bounding rectangle formula is a bit complex because of the possibility of a different Origin (other than 0,0) and the Scale. Hopefully, this is correct enough…

Now we’ll add a simple Collide method to the Sprite class that checks intersecting rectangles:

public virtual bool Collide(Sprite other) {

   return BoundingRect.Intersects(other.BoundingRect);

}

 

No shrinking factor is used here – I’ll leave that as an exercise for the reader. The method is marked virtual in case a derived class wants to check collisions in some other way. The XNA Rectangle type provides a simple Intersects method that we can leverage.

With this infrastructure in place, we can move on to the actual collision checking. There are several combinations we need to check: player’s missiles against aliens, aliens against player, aliens missiles (don’t exist yet) against player.

Let’s start with the player’s missiles against aliens. This allows the player to actually kill an alien. Collision detection is done in the relevant Update method. In this case we’ll check that in the PlayerComponent class where the bullets are handled. We could have reversed that, checking collisions in the alien movement loop against all player’s missiles.

To gain access to the aliens from the PlayerComponent class, we’ll have to expose the aliens collection as a property from the AliensComponent class:

internal IEnumerable<Alien> Aliens { get { return _aliens; } }

 

To gain access to the AliensComponent instance in the first place (from the PlayerComponent class, or any other component class for that matter), we’ll add a field to the game class that would be set to point to the AliensComponent:

public readonly AliensComponent AliensComponent;

 

In the constructor of the game, we’ll set the field while adding the component:

Components.Add(AliensComponent = new AliensComponent(this));

 

It’s time to do the actual checking from the PlayerComponent while moving active bullets:

foreach(var bullet in _bullets)

   if(bullet.Active) {

      bullet.Update(gameTime);

      if(bullet.Position.Y < -10) {

         // out of bounds

         bullet.Active = false;

      }

      else {

         foreach(var alien in AlienRaidGame.Current.AliensComponent.Aliens)

            if(alien != null && alien.Active && bullet.Collide(alien)) {

               // alien hit!

                bullet.Active = false;

            }

      }

   }

 

The actual collision check is in bold. In case of a collision we deactivate the bullet. The next logical step would be to make the alien explode or something. We could create an explosion sprite, but let’s do something else: we’ll make the alien disappear gradually with shades of red. But, first thing’s first: How would we know the actual alien is dead? Perhaps it’s a boss alien and is more resilient? The simplest approach would be to notify the alien itself that it has been hit and it figure out what to do with this.

Let’s add a Hit method to the Alien class, and call it in case a player missile collides with an alien:

public virtual void Hit(int power = 1) {

   if((HitPoints -= power) <= 0) {

      // alien killed, start death sequence

      _isDying = true;

      Color = new Color(255, 0, 0);

      if(Killed != null)

         Killed(this);

   }

}

 

HitPoints is a field indicating the “health” of the alien. It’s initialized to 1 for normal aliens (and to a larger value for a boss, not done yet). We can even vary the power of the player’s shot by changing the power argument. This could be (for example) as a result of some powerup (we’ll talk about those in a later post). Killed is another event an alien may fire to any interested parties:

public event Action<Alien> Killed;

 

_isDying is a boolean indicating whether the alien is in a dying process. An IsDying property exposes this publicly. The Color is changed to use the red component only. Instead of some kind of explosion, we’ll change the “redness” of the alien gradually down to black. This is all done in the modified Alien.Update method:

public override void Update(GameTime gameTime) {

   if(Active && !_isDying) {

      if(Position.X < 0 || Position.X > AlienRaidGame.Current.Window.ClientBounds.Width)

         Velocity.X = -Velocity.X;

      if(Position.Y > AlienRaidGame.Current.Window.ClientBounds.Height + 40) {

         Active = false;

         if(OutOfBounds != null)

            OutOfBounds(this);

      }

   }

   else if(_isDying) {

      if(Color.R > 4)

         Color.R -= 4;

      else {

         Active = false;

      }

      return;

   }

 

   base.Update(gameTime);

}

 

The code to test for collisions between the aliens and the player’s bullets is now modified to call Alien.Hit and to disregard dying aliens:

foreach(var alien in AlienRaidGame.Current.AliensComponent.Aliens)

   if(alien != null && alien.Active && !alien.IsDying && bullet.Collide(alien)) {

      // alien hit!

       bullet.Active = false;

       alien.Hit();

   }

 

That’s about it! Run the game and kill some aliens!

No score is incremented yet, no sound is heard when an alien explodes. Feel free to add one!

In the next part we’ll add more collision detection (so the player can be killed too) and some explosions. We’ll also add some stats, such as score and the number of lives remaining.

XNA 2D Game Tutorial (Part 9)

Published at Nov 14 2010, 10:20 PM by pavely

Previous posts in this series:

In the previous post we prepared the data for the aliens and for the game levels. In this post, we’ll put that data to action.

The first thing we’ll do is create a custom Alien class, that extends the Sprite class and adds some specific alien attributes. This will make our lives a little bit easier when we managed all those aliens. Add a new class named Alien and derive it from Sprite. We’ll need a constructor that satisfies the requirements of Sprite – we’ll get all the needed information from an AlienType:

class Alien : Sprite {

   public readonly bool IsBoss;

   public readonly AlienType Type;

 

   public Alien(AlienType type, bool isBoss)

      : base(type.Texture, type.FirstFrame, type.Frames, type.IsHorizontal, type.Space) {

      IsBoss = isBoss;

      Type = type;

      Origin.X = type.FirstFrame.Value.Width / 2;

      AnimationInterval = type.AnimationRate;

 

   }

}

 

The IsBoss field indicates whether this alien is, in fact, a boss alien. A more “object oriented” approach would be to create an AlienBoss class, derive it from Alien, thus customizing its behavior. I’ll leave that as an exercise for the reader. I’ll take the (somewhat) simpler approach here, but if I had wanted to make the  boss behave very differently from that of a regular alien, I would have done that with the derived class approach.

Now we’ll create an array of Alien references in the AlienComponent class (created in the previous part), somewhat similar to the missiles array we created for the player. In this case, however, as every alien may look different, we may have to create aliens dynamically as needed. Another possible approach would be to allow the Texture of a sprite to be changed after the sprite has been initialized. Currently, the Texture of a sprite is passed via the constructor, and is read only since.

In the Update method, we’ll update all existing aliens (for animation and movement purposes), and in the Draw method we’ll draw them. Nothing has been created at this time:

public override void Update(GameTime gameTime) {

   foreach(var alien in _aliens)

      if(alien != null && alien.Active)

         alien.Update(gameTime);

 

   base.Update(gameTime);

}

 

public override void Draw(GameTime gameTime) {

   _batch.Begin();

   foreach(var alien in _aliens)

      if(alien != null && alien.Active)

         alien.Draw(gameTime, _batch);

   _batch.End();

   base.Draw(gameTime);

}

 

_aliens is the array declared in the AliensComponent class. Next, we’ll add the component to the game’s Components collection in the game’s constructor (as usual for game components):

Components.Add(new AliensComponent(this));

 

Running the game at this time has no special effect. Our next task would be to actually create an alien (based on some random factor and the game level). The Update method is the proper place for this:

// get current level data

LevelData data = AlienRaidGame.Current.GetCurrentLevelData();

 

if((_elapsedTime += gameTime.ElapsedGameTime) > data.AlienGenerationTime) {

   _elapsedTime = TimeSpan.Zero;

   if(CreateAlien() != null)

      _currentLiveAliens++;

}

 

We first get the current level data by calling the game’s GetCurrentLevelData method we developed in the previous part. Note that to get to the game object itself I’ve added a static property called Current that is set in the game’s constructor. The alternative is to cast the Game property back to the actual AlienRaidGame type, which I find annoying (and like all casts – is applied at runtime, which is slower).

_elapsedTime is incremented by the elapsed time since the last frame and compared to the alien generation time obtained from the level data. This indicates when it’s time to attempt creation of a new alien. CreateAlien is a helper method that does the actual creation and setting up of the alien:

private Alien CreateAlien() {

   var data = AlienRaidGame.Current.GetCurrentLevelData();

   if(_currentLiveAliens > data.MaxActiveAliens) return null;

 

   int chance = 0;

   int value = _rnd.Next(100);

   foreach(var sd in data.SelectionData) {

      if(value < sd.Chance + chance) {

         // selected

         while(_aliens[_currentAlienIndex] != null && _aliens[_currentAlienIndex].Active)

            _currentAlienIndex = (_currentAlienIndex + 1) % _aliens.Length;

         Alien alien = new Alien(sd.Alien, false);

         alien.Position = new Vector2((float)(_rnd.NextDouble() * Game.Window.ClientBounds.Width), -50);

         alien.Velocity = new Vector2((float)(_rnd.NextDouble() * alien.Type.MaxXSpeed * 2 - alien.Type.MaxXSpeed),

            (float)(_rnd.NextDouble() * alien.Type.MaxYSpeed + 2));

         alien.Scale = 2;

         _aliens[_currentAlienIndex] = alien;

         return alien;

      }

      chance += sd.Chance;

   }

   return null;

}

 

_currentLiveAliens counts the total aliens currently active and compared to the data from the current level prevents too many aliens to be present at any one time. Then the SelectionData collection is used to select an alien type at random, based on probabilities in the current SelectionData. If selected, a free index is located and a new alien instance is placed there. The alien’s position is set randomly in the X direction and at Y=-50 (just above the visible screen, so it can make an entrance). Speed is set based on maxima read from the alien type. The alien is now active!

Running the code as is causes various aliens to move in a certain direction and disappear. After a while, aliens stop appearing. This is because we increment the current live aliens but never decrement it. There is no checking for going off the screen. Let’s take care of that.

First, if an alien moves off the screen in the X axis, I want it to simply change direction (bounce back). This we can do in the Alien.Update override (of the same Sprite method):

public override void Update(GameTime gameTime) {

   if(Active) {

      if(Position.X < 0 || Position.X > AlienRaidGame.Current.Window.ClientBounds.Width)

         Velocity.X = -Velocity.X;

   }

 

   base.Update(gameTime);

}

 

Although the bounds checks are not exact, they are good enough. The aliens now bounces off the right and left edges of the game screen.

Now for the Y position: if it’s beyond the screen, then mark the alien as inactive and decrement the active alien count. It’s a bit problematic to do that in the same Update method, as we don’t have access to the parent AliensComponent, and we wouldn’t want a direct access anyway. One option is to check all that in the AliensComponent.Update method. This is somewhat awkward, but possible. Another alternative is to use an event. The alien can fire an event when it’s Y position is out of bounds. Any interested party (the AliensCompoenent object) can handle that event appropriately. For the sake of versatility, let’s use an event. First, let’s declare it in the Alien class:

public event Action<Alien> OutOfBounds;

 

In “classic” .NET an event delegate should be of type EventHandler or EventHandler<T> (that accept an object and a T that must derive from EventArgs). Here we’re cutting another corner, as we prefer type safety and fewer arguments.

Raising (or firing the event) should be done during Update:

if(Position.Y > AlienRaidGame.Current.Window.ClientBounds.Height + 40) {

   Active = false;

   if(OutOfBounds != null)

      OutOfBounds(this);

}

 

Subscribing to the event is conveniently done in the CreateAlien helper. A simple lambda expression (or anonymous delegate if you prefer, or a regular method) can be used:

alien.OutOfBounds += a => {

   _currentLiveAliens--;

};

 

If that’s a bit scary, we can write it like this instead:

alien.OutOfBounds += delegate {

   _currentLiveAliens--;

};

 

If that’s still scary, then we could write that as a separate method and do the _currentLiveAliens—in there.

If the anonymous delegate or lambda expression is unfamiliar, or you chose to stay from those “complications”, I strongly suggest you read about those and get comfortable with that. They’re not going away any time soon.

Running the game now shows a bunch of aliens that keep flying, changing direction at the seams, while the player moves her ship and fires at the aliens. Didn’t hit them, did you? The upside is the aliens couldn’t hit you, either.

Why? There is no collision detection or handling of such collisions. That’s the topic of the next part.

XNA 2D Game Tutorial (Part 8)

Published at Nov 13 2010, 02:46 PM by pavely

Previous posts in this series:

 

What do we have so far? A player controlling a ship capable of firing missiles (with sound), flying through space with a backdrop of passing stars. Clearly, no real challenge for the player yet. It’s time to add some enemies to challenge the player. In this part, we’ll handle setting up the data, and in the next part we’ll implement the actual enemies.

Creating enemy sprites and managing them is no different in principal than dealing with the player and her missiles. It’s just a matter of creating and initializing sprites, managing their movements (if any) and drawing them. The real challenge is designing the enemies for versatility, challenge, balance and re-playability. For this demo game, I’d like to have levels the player goes through. In each level, she must destroy a certain number of enemies. Before moving to the next level, I’d like to have a “boss” alien – this is classic (although somewhat a cliché). Difficulty will increase in each level simply by force of numbers: more enemies, more frequent firing, faster speeds, etc. This is not an “intelligent” way to go, but it’s simple; and we’re taking the simple approach in this tutorial.

The concept of “intelligence” is a complex one, and we’ll not deal with “Artificial Intelligence” techniques in this tutorial. We’ll focus on XNA stuff and simply use randomness and shear numbers to give the player a sense of some kind of intelligent behavior from the enemy aliens.

The first order of business is to define various alien enemy types with properties, such as their texture, animation parameters, maximum speed, score if hit, etc. This allows us to select aliens to be used in each level, gradually using “stronger” aliens. Let’s define a simple alien type class that holds all that info:

class AlienType {

   public TimeSpan AnimationRate = TimeSpan.FromMilliseconds(500);

   public string Name;

   public int Score;

   public int Space;

   public float MaxXSpeed;

   public float MaxYSpeed;

   public Texture2D Texture;

   public int Frames = 1;

   public bool IsHorizontal = true;

   public Rectangle? FirstFrame;

}

 

This simple class uses fields only for performance reasons discussed a previous post. Some fields are technical (Texture, Space, Frames, etc.) and some functional (MaxXSpeed, MaxYSpeed). The Name field will be used as a key to access a particular alien as we’ll see shortly.

How do we get data into a collection of AlienType objects? One simple way is to create a collection and populate it in code. This works, but not the best approach. one of the important issues on creating a game is the question of balance. It’s fairly difficult to get a game to be “quite right” in terms of difficulty. You want it to be difficult, but not too difficult. if it’s easy, the player is bored. If it’s too difficult, the player might give up. And yes, it’s very tricky, as players themselves are different. And no, your perception is not sufficient, as you may not be a typical player.

What this all means, is that various game parameters will have to be tweaked quite a bit. If this is all in code, every tweak requires a recompilation, meaning time consumption, and more importantly – a developer must be at the seat. Why should this be? A game designer (in a simple case, a friend) may want to balance the game by tweaking parameters, but she may not have a Visual Studio or something. That’s why it’s better to put all possible parameters outside the code, in some data files (e.g. XML). This is the approach we’ll take.

Add a new folder to the project named Data. Right-click the new folder and select Add –> New Item. Navigate to the Visual C#->Data node and select “XML file”. Type AlienTypes in the Name box and click “Add”.

image

Right click the resulting file and select properties. Change the “Build action” to “None” and the “Copy to output directory” to “Copy if newer”. This will ensure the file is located with the project output and is always up to date.

Now let’s fill some alien types within the newly created XML file:

<AlienTypes>

  <AlienType Name="alien1" Score="10" MaxXSpeed="3" MaxYSpeed="2"

             Texture="Images/sprites" Frames="2" Space="1"

             FirstFrame="104,84,16,13" AnimationRate="500" />

  <AlienType Name="alien2" Score="15" MaxXSpeed="4" MaxYSpeed="3"

             Texture="Images/sprites" Frames="2" Space="0"

             FirstFrame="36,82,16,15" AnimationRate="400" />

  <AlienType Name="alien3" Score="20" MaxXSpeed="5" MaxYSpeed="4"

             Texture="Images/sprites" Frames="2" Space="0"

             FirstFrame="2,81,16,15" AnimationRate="400" />

  <AlienType Name="alien4" Score="25" MaxXSpeed="5" MaxYSpeed="5"

             Texture="Images/sprites" Frames="2" Space="1"

             FirstFrame="36,123,16,14" AnimationRate="400" />

  <AlienType Name="alien5" Score="30" MaxXSpeed="4" MaxYSpeed="6"

             Texture="Images/sprites" Frames="2" Space="0"

             FirstFrame="37,143,13,9" AnimationRate="300" />

 

  <AlienType Name="boss1" Score="500" MaxXSpeed="5" MaxYSpeed="0"

             Texture="Images/sprites" Frames="2" FirstFrame="186,85,54,36" AnimationRate="1000" />

  <AlienType Name="boss2" Score="800" MaxXSpeed="6" MaxYSpeed="0"

             Texture="Images/sprites" Frames="2" FirstFrame="2,1,63,38" AnimationRate="900" />

  <AlienType Name="boss3" Score="1000" MaxXSpeed="7" MaxYSpeed="0"

             Texture="Images/sprites" Frames="2" FirstFrame="133,0,66,40" AnimationRate="800" />

  <AlienType Name="boss4" Score="1500" MaxXSpeed="8" MaxYSpeed="0"

             Texture="Images/sprites" Frames="2" FirstFrame="138,43,52,36" AnimationRate="600" />

</AlienTypes>

The “Images/sprites” asset name is a new image file that holds all the alien images (and some other things like explosion images we’ll use later).

To read all this data, we’ll create a Dictionary in the game class and read the data in the Initialize method. We’ll expose the Dictionary as property for any interested party. The reading of data is done using LINQ to XML. If you’re not familiar with LINQ in general, or LINQ to XML, you should head out to the web and study it. It’s one of those things that once you really understand – you’ll use it time and time again and never go back. If you’re feeling unsure, you can read the data using the old XML API (in System.XML – XmlDocument, XmlElement, XmlAttribute, etc. This API is way too verbose for my taste Smile):

protected override void Initialize() {

   base.Initialize();

 

   _alienTypes = (from at in XElement.Load("data/alientypes.xml").Descendants("AlienType")

                  select new AlienType {

                     Name = (string)at.Attribute("Name"),

                     Score = (int)at.Attribute("Score"),

                     MaxXSpeed = (float)at.Attribute("MaxXSpeed"),

                     MaxYSpeed = (float)at.Attribute("MaxYSpeed"),

                     Texture = Content.Load<Texture2D>((string)at.Attribute("Texture")),

                     FirstFrame = ParseRectangle((string)at.Attribute("FirstFrame")),

                     Space = (int)at.Attribute("Space"),

                     Frames = (int)at.Attribute("Frames"),

                     AnimationRate = TimeSpan.FromMilliseconds((int)at.Attribute("AnimationRate"))

                  }).ToDictionary(t => t.Name);

}

 

The ToDictionary extension method turns the created list into a dictionary, keyed by the name of the AlienType. The resulting data is exposed as a simple method from the game class:

internal AlienType GetAlienType(string name) {

   return _alienTypes[name];

}

 

The next step is to create some data that represents what’s going on in each game level. We’ll add another XML file called Levels.Xml to the Data folder. Let’s create some levels:

<Levels>

  <Level Number="1" MaxActiveAliens="7" TotalAliensToFinish="15" Boss="boss1"

         AlienGenerationTime="800" ChangeDirChance="2" FireChance="2" MaxAlienBullets="5">

    <AlienTypes>

      <AlienType Name="alien1" Chance="25" />

      <AlienType Name="alien2" Chance="20" />

      <AlienType Name="alien3" Chance="20" />

      <AlienType Name="alien4" Chance="5" />

    </AlienTypes>

  </Level>

  <Level Number="2" MaxActiveAliens="10" TotalAliensToFinish="25" Boss="boss2"

         AlienGenerationTime="600" ChangeDirChance="2" FireChance="3" MaxAlienBullets="7">

    <AlienTypes>

      <AlienType Name="alien1" Chance="20" />

      <AlienType Name="alien2" Chance="20" />

      <AlienType Name="alien3" Chance="20" />

      <AlienType Name="alien4" Chance="15" />

      <AlienType Name="alien5" Chance="10" />

    </AlienTypes>

  </Level>

</Levels>

These are just 2 levels, but we can add as many as we want. The downloadable source has 4 levels defined.

A level has some attributes, such as the maximum number of active aliens, the number of aliens needed to advanced to the next level, the name of the boss alien, etc. The most interesting part is the AlienTypes element that lists the chance of each alien type to be generated during game play.

Similarly to the AlienType class, we’ll create some data structures that can hold the information for a particular level:

class AlienSelectionData {

   public AlienType Alien;

   public int Chance;

}

 

class LevelData {

   public int Number;

   public TimeSpan AlienGenerationTime;

   public int MaxActiveAliens;

   public int TotalAliensToFinish;

   public AlienType Boss;

   public List<AlienSelectionData> SelectionData;

   public int ChangeDirChance;

   public int FireChance;

   public int MaxAlienBullets;

}

 

Although we can read all levels data in one swoop – this is unnecessary. We just need to read a single level, corresponding to the current level.

First we’ll add a Level field to the game and create a helper method named InitLevel that reads the current level data – in preparation for a new level. That data is exposed through a method, similarly to what we did with alien types:

private void InitLevel(int levelNum) {

   Level = levelNum;

   _levelData = (from level in XElement.Load("Data/Levels.xml").Descendants("Level")

                 where (int)level.Attribute("Number") == levelNum

                 select new LevelData {

                    Number = levelNum,

                    ChangeDirChance = (int)level.Attribute("ChangeDirChance"),

                    MaxActiveAliens = (int)level.Attribute("MaxActiveAliens"),

                    TotalAliensToFinish = (int)level.Attribute("TotalAliensToFinish"),

                    Boss = _alienTypes[(string)level.Attribute("Boss")],

                    FireChance = (int)level.Attribute("FireChance"),

                    MaxAlienBullets = (int)level.Attribute("MaxAlienBullets"),

                    AlienGenerationTime = TimeSpan.FromMilliseconds((int)level.Attribute("AlienGenerationTime")),

                    SelectionData = (from sel in level.Descendants("AlienType")

                                     select new AlienSelectionData {

                                        Chance = (int)sel.Attribute("Chance"),

                                        Alien = _alienTypes[(string)sel.Attribute("Name")]

                                     }).ToList()

                 }).SingleOrDefault();

   Debug.Assert(_levelData != null);

}

 

internal LevelData GetCurrentLevelData() {

   return _levelData;

}

 

The technique used here is the same used for the alien types data. It’s a bit more complex, as we need to read a collection within the level data, indicating the chance a certain alien type should be created.

The InitLevel method should be called when the game starts, and when advancing to a new level. We’ll add a call in the AlienRaidGame.Initialize method, setting the level to 1:

InitLevel(1);

 

Now that we have all the right data set up, when can move on to actually creating and managing the aliens. We’ll do that in a separate component, for the same reasons we created separate components for the stars and the player. Add a new DrawableGameComponent named AliensComponent by right-clicking the project, selecting Add->New Item, navigating to XNA/Game Component, setting the name to AliensComponent and clicking Add. Then change the base class from GameComponent to DrawableGameComponent.

In the next part, we’ll fill the newly created component with some live aliens!

XNA 2D Game Tutorial (Part 7)

Published at Nov 11 2010, 10:25 AM by pavely

Previous posts in this series:

The game as it is now is not yet challenging – there are no enemies to threaten the player – she simply flies through space, shooting at nothing. We’ll deal with some enemies in the next part, but first let’s consider sound.

Sound is a critical part of any game. Just for kicks, play your favorite action game with the volume off – you’ll get bored or irritated pretty quickly. Sound is not just for fun, though; sometimes it’s a critical ingredient, indicating to the player that something important has happened without the player needing to focus in any particular point on the screen.

So how do we play sound effects or music in XNA? There are basically two ways: the first is to use XACT (Microsoft Cross Platform Audio Creation Tool), which allows great control over the sounds you want to play. The second route is to use a (pretty) simple API provided originally for the Zune (which does not support XACT), but can be used with any XNA supported device. We’ll take the second approach in this tutorial.

The first order of business is to add audio assets to the content project, much the same way we added images. XNA supports playing WAV files (and some other less frequently used formats) as a sound effect. It also supports playing MP3 files (more suitable for background music).

Add a folder named “Audio” to the content project (sibling of “Images”). Right click the new folder and select Add –> Existing Item and navigate to a WAV file. For our purposes, we’ll add a WAV file that would be the sound when the player fires one of its missiles/bullets.

Next, we need to load that sound into a SoundEffect object, very similar to other assets using the ContentManager.Load<> generic method (in the LoadContent method of the PlayerComponent class for our purposes):

_bulletSound = Game.Content.Load<SoundEffect>("Audio/bullet");

 

Where _bulletSound is a field of type SoundEffect.

The SoundEffect type has a Play method, and it’s tempting to simply use it to play the sound. However, that’s not recommended. The reason is that a call to Play is a kind of “singleton”; that is, a single sound instance can be played at one time. So, if the player fires two bullets in close succession (and the sound effect is not too short), a second Play would not create a separate, independent sound. The proper way to do this is use the SoundEffect.CreateInstance method that returns a SoundEffectInstance object, representing an independent sound instance.

Each SoundEffectInstance can be separately played and configured (e.g. different volume).

The easiest way to handle the sound effect for the player’s bullets (although a bit wasteful) is to create a same length array of SoundEffectInstance references, initialize them using SoundEffect.CreateInstance and playing when appropriate (e.g. in the CreateBullet helper method).

_bulletSoundInstance[i] = _bulletSound.CreateInstance();

_bulletSoundInstance[i].Volume = .7f;

 

This initializes the sound effect instances inside the loop that creates the bullet sprites. To play, we’ll call SoundEffectInstance.Play in CreateBullet after the new bullet has been setup properly:

_bulletSoundInstance[_lastBulletIndex].Play();

 

That’s about it! We have sound!

XNA 2D Game Tutorial (Part 6)

Published at Nov 09 2010, 01:20 PM by pavely

Previous parts in this series:

In the previous part, we added animation capabilities to a general Sprite class. Our next step is to add firing capabilities to the player.

The first thing we’ll do is move the player logic to its own component. This would make it flexible (allowing us to disable it in a title screen, for example) and easier to maintain.

Add a new Game Component named PlayerComponent using the Add –> New Item context menu (as we did with the starfield component). Change the base class to DrawableGameComponent, as the player clearly has something to draw.

Let’s move the keyboard input handling and all other player related logic to the new game component’s Update method and the player drawing code to the Draw method of the component. This requires moving the player’s Sprite object to the component as well:

public class PlayerComponent : DrawableGameComponent {

   Texture2D _playerShip;

   Sprite _player;

   SpriteBatch _batch;

 

   public PlayerComponent(Game game)

      : base(game) {

   }

 

   public override void Initialize() {

      base.Initialize();

 

      _player = new Sprite(_playerShip, new Rectangle(0, 0, 15, 20), 2);

      _player.Position = new Vector2(400, 530);

      _player.AnimationInterval = TimeSpan.FromMilliseconds(500);

      _player.Scale = 2;

   }

 

   protected override void LoadContent() {

      base.LoadContent();

 

      _playerShip = Game.Content.Load<Texture2D>("Images/ship");

 

      _batch = new SpriteBatch(Game.GraphicsDevice);

   }

 

   public override void Update(GameTime gameTime) {

      var ks = Keyboard.GetState();

      if(ks.IsKeyDown(Keys.Right))

         _player.Position.X += 5;

      else if(ks.IsKeyDown(Keys.Left))

         _player.Position.X -= 5;

 

      if(_player.Position.X < 0) _player.Position.X = 0;

      else if(_player.Position.X > Game.Window.ClientBounds.Width - _player.FrameWidth * _player.Scale)

         _player.Position.X = Game.Window.ClientBounds.Width - _player.FrameWidth * _player.Scale;

 

      _player.Update(gameTime);

 

      base.Update(gameTime);

   }

 

   public override void Draw(GameTime gameTime) {

      _batch.Begin();

      _player.Draw(gameTime, _batch);

      _batch.End();

      base.Draw(gameTime);

   }

}

 

All that’s left to do for this to work as before is add the new component to the game (in the game constructor):

Components.Add(new PlayerComponent(this));

 

This leaves us with the same functionality, but the player handling logic and drawing is separated into its own component class.

The next feature I want to add is to allow the player to shoot some kind of projectiles or bullets. This will all be handled in the PlayerComponent class, as it’s the one responsible for all player capabilities, including firing bullets. I want to allow several bullets to travel at the same time across the screen. In very old games only one bullet could be on the screen at any one time, so the player had to wait (in case of a bullet miss) for the bullet to disappear from the screen before he could fire again. This was usually done because of performance reasons (keeping track and drawing many bullets is hard), but on today’s hardware that’s not an issue. So, for a fun game, we’ll allow more than one bullet at a time, perhaps limiting firepower to some maximum rate. This rate can later be modified because of power ups, for example. But we’ll get to that later.

Handling Projectiles

Projectiles, such as various bullets, cannon balls, lasers, etc. are handled much the same way as any sprite. The difference is of control. These entities are started at a specific time (e.g. when pressing a certain key), but have “a life of their own”. For the player’s projectiles we’ll create an array of sprites – preparing them up-front (so as to minimize the chance of garbage collection during the actual game action), and selecting the first “available” bullet when the space bar is pressed. Let’s begin with adding some fields:

Texture2D _bulletTexture;

Sprite[] _bullets = new Sprite[16];   // assume no more than 16 active bullets

TimeSpan _minForBullet = TimeSpan.FromMilliseconds(400);

TimeSpan _totalForBulletElapsed;

int _lastBulletIndex;

 

_bulletTexture is the image for the bullet (added to the Images folder of the content project as usual). _bullets is the array of sprites (to be initialized later) for a maximum of 16 concurrent bullets. Of course, we can change that number if the need arises. _minForBullet is the minimum time between starting a new bullet. That is, this limits the firing rate. _totalForBulletElapsed accumulates passing game time and when it’s larger than _minForBullet (and the player presses space), will initiate a new bullet. _lastBulletIndex will help in finding the next (inactive) available bullet sprite to use.

In the Initialize method, we’ll set up the bullets:

for(int i = 0; i < _bullets.Length; i++) {

   Sprite bullet = new Sprite(_bulletTexture);

   bullet.Active = false;

   bullet.Scale = 2;

   bullet.ZLayer = .7f;

   bullet.Origin = new Vector2(bullet.FrameWidth / 2, 0);

   _bullets[i] = bullet;

}

 

Most of the code should be familiar. We’re creating all bullets up-front (to minimize creation during play, thus reducing garbage collection chance) in an inactive state. When the player presses space and enough time has passed since initiating the last shot, we’ll start a bullet (all in the Update) method:

if((_totalForBulletElapsed += gameTime.ElapsedGameTime) > _minForBullet && ks.IsKeyDown(Keys.Space)) {

   _totalForBulletElapsed = TimeSpan.Zero;

   CreateBullet();

}

 

foreach(var bullet in _bullets)

   if(bullet.Active) {

      bullet.Update(gameTime);

      if(bullet.Position.Y < -10) {

         // out of bounds

         bullet.Active = false;

      }

   }

 

Regardless, we must update the position of all active bullets. If a bullet moves beyond the screen bounds, we de-activate it.

The CreateBullet is a small helper that actually activates the bullet, placing it in the right location and giving it proper velocity:

private void CreateBullet() {

   while(_bullets[_lastBulletIndex].Active)

      _lastBulletIndex = (_lastBulletIndex + 1) % _bullets.Length;

   Sprite bullet = _bullets[_lastBulletIndex];

   bullet.Position = _player.Position;

   bullet.Active = true;

   bullet.Velocity.Y = -6;

}

 

The first thing it does is find an inactive bullet that we can re-activate. Then it places it, gives it speed and activates it.

All that’s left is to draw the active bullets (in the Draw method):

foreach(var bullet in _bullets)

   if(bullet.Active)

      bullet.Draw(gameTime, _batch);

 

That’s basically it. The only missing code is the loading of the bullet texture, done in LoadContent:

_bulletTexture = Game.Content.Load<Texture2D>("Images/bullet");

 

In the next part, we’ll play some sound effects, so the game feels more alive.

XNA 2D Game Tutorial (Part 5)

Published at Nov 07 2010, 10:17 PM by pavely

Previous parts in this series: Part 1 (Getting Started), Part 2 (Showing Something), Part 3 (Input Handling), Part 4 (Game Components).

What do we have at the moment? A ship we can control with keyboard and stars flying by, implemented as a DrawableGameComponent for flexibility and modularity. Although the ship seems to move, it’s still too static. Its engines are not changing. What we want is some animation. Perhaps toggling between two images such that the engine would seem to fluctuate?

Animation (in the 2D world, at least) means changing the shape of a sprite with respect to time or some other factor. In this case, we’ll have two shapes for the ship that we would want to swap every so and so milliseconds. Here’s the new player’s ship image (enlarged):

image

Changing the ship.png in the project to the above image and running produces something like this:

image

Not exactly what we were hoping for…

We want to show one image at a time. This requires some code modifications when drawing the player’s ship.

Currently, our drawing code for the ship looks like this:

spriteBatch.Draw(_playerShip, _pos, null, Color.White, 0, Vector2.Zero, 2, SpriteEffects.None, 0);

 

The null third parameter is the key to animation. The null means “use the entire image” – that’s where the “double ship” effect comes from. if we change this to a Rectangle object that only uses the left half of the image, we’ll see a normal image again:

spriteBatch.Draw(_playerShip, _pos, new Rectangle(0, 0, 15, 20), Color.White, 0, Vector2.Zero, 2, SpriteEffects.None, 0);

 

The 15 is half the width, as is evident when opening the file in some image editor. The 20 is the height of the image. All we have to do now is keep track of the current frame (0 or 1) and change the rectangle accordingly. Let’s add a simple integer to the game class that would indicate the current frame:

int _currentFrame;

 

Now we can use the current frame to modify the displayed rectangle:

spriteBatch.Draw(_playerShip, _pos, new Rectangle(_currentFrame * 15, 0, 15, 20), Color.White, 0, Vector2.Zero, 2, SpriteEffects.None, 0);

 

Changing _currentFrame from 0 to 1 switches the active image. How do we make that switch? We need to toggle _currentFrame from 0 to 1 and back after some period (say 0.5 seconds). To do that we’ll use a TimeSpan object that will accumulate the elapsed time. If 0.5 second pass by, we'll make the switch. All this happens in the Update method:

if((_shipAnimElapsed += gameTime.ElapsedGameTime) > TimeSpan.FromMilliseconds(500)) {

   _currentFrame = 1 - _currentFrame;

   _shipAnimElapsed -= TimeSpan.FromMilliseconds(500);

}

 

We use the GameTime.ElapsedGameTime property that indicates the elapsed time since the last call to Update (should be a constant 16.666667 msec by default, but can vary because of slowdown or changes in the frame rate). when half a second passes, we switch the current frame and subtract 0.5 seconds from our elapsed time counter. Now we have proper animation!

Some Refactoring

This capability – animation – is probably useful for many sprites. It seems appropriate to factor all this out to a separate Sprite class, that can animate along several frames, and can provide other services, such as drawing, position updating, collision detection and more.

Let’s create a new Sprite class. Right-click the project, and select Add –> Class. Name it Sprite:

image

Click Add.

We want our Sprite class to encapsulate as much common functionality as we can, so we can leverage it for the alien enemies, the various projectiles, etc. Here are some basic attributes the Sprite class should hold:

public class Sprite {

   public Texture2D Texture { get; private set; }

   public Vector2 Position;

   public Vector2 Velocity;

   public Vector2 Origin;

   public bool Active = true;

   public float Scale = 1;

   public float Rotation;

   public float ZLayer;

 

   public int TotalFrames { get; private set; }

   public TimeSpan AnimationInterval;

 

The Texture property is the image from which the sprite is drawn. Position and Velocity are self evident – Velocity will be added to Position on each update. Velocity can be zero if so desired.

Origin, Scale, Rotation and ZLayer, mimic the parameters to SpriteBatch.Draw that will be used in the Draw call. Active is a simple boolean flag indicating whether the sprite is “alive”. This will help us a little later. TotalFrames indicates the number of animation frames and AnimationInterval controls the animation speed.

Now for the constructor:

public Sprite(Texture2D texture, Rectangle? firstRect = null, int frames = 1, bool horizontal = true, int space = 0) {

   Texture = texture;

   TotalFrames = frames;

   if(firstRect != null) {

      _rects = new Rectangle[frames];

      Rectangle first = (Rectangle)firstRect;

      for(int i = 0; i < frames; i++)

         _rects[i] = new Rectangle(first.Left + (horizontal ? (first.Width + space) * i : 0),

            first.Top + (horizontal ? 0 : (first.Height + space) * i), first.Width, first.Height);

   }

}

 

The only required parameter is the texture – without it there is nothing to draw. Note that there is no error handling at this time – it’s left as an exercise for the reader – I want to concentrate on the practical XNA stuff, not the things that are always relevant.

The firstRect argument indicates the coordinates and sizes of the first frame within the image texture. If it’s null, that means the entire texture is the single frame. If not, we need to calculate the rectangles of the other frames. I wanted to support frames laid out horizontally as well as vertically – that’s the horizontal argument. The space argument indicates whether there is some space between frames in the texture. The rectangles are calculated accordingly, in preparation for drawing.

Next up are the Update and Draw methods. Update should take care of the animation (if any) and move the sprite if Velocity is non-zero:

public virtual void Update(GameTime gameTime) {

   if(Active) {

      if(TotalFrames > 1 && (_animElapsed += gameTime.ElapsedGameTime) > AnimationInterval) {

         if(++_currentFrame == TotalFrames)

            _currentFrame = 0;

         _animElapsed -= AnimationInterval;

      }

      Position += Velocity;

   }

}

 

_animElapsed is of type TimeSpan and serves a similar purpose to the _shipAnimElapsed variable from the previous code. Note that nothing happens if the sprite is not active.

The final piece of the puzzle (at this time) is the Draw method:

public virtual void Draw(GameTime gameTime, SpriteBatch batch) {

   if(Active) {

      batch.Draw(Texture, Position, _rects == null ? null : (Rectangle?)_rects[_currentFrame],

         Color, Rotation, Origin, Scale, SpriteEffects.None, ZLayer);

   }

}

 

It uses the various fields declared previously and a Color field (initialized to Color.White) – changing this could be beneficial for the starfield, for example. Notice the selection of the current rectangle frame based on the _currentFrame field.

All that’s left to do right now is modify the game to use the new Sprite class instead of the manual drawing and animating done previously:

Add a Sprite field called _player to the game class. Remove the animation and frame related fields. In the Initialize method, create the sprite:

protected override void Initialize() {

   base.Initialize();

 

   _player = new Sprite(_playerShip, new Rectangle(0, 0, 15, 20), 2);

   _player.Position = new Vector2(400, 530);

   _player.AnimationInterval = TimeSpan.FromMilliseconds(500);

   _player.Scale = 2;

}

 

Modify the Update method to use the new sprite:

if(ks.IsKeyDown(Keys.Right))

   _player.Position.X += 5;

else if(ks.IsKeyDown(Keys.Left))

   _player.Position.X -= 5;

 

if(_player.Position.X < 0) _player.Position.X = 0;

else if(_player.Position.X > Window.ClientBounds.Width - _player.FrameWidth * _player.Scale)

   _player.Position.X = Window.ClientBounds.Width - _player.FrameWidth * _player.Scale;

 

_player.Update(gameTime);

 

FrameWidth is a helper properties that return the width of each frame:

public int FrameWidth { get { return _rects == null ? Texture.Width : _rects[0].Width; } }

 

There is room for some optimization here. Multiplying by the scale is not fun. We’ll improve that later.

Now we need to change the Draw method to use our new sprite:

protected override void Draw(GameTime gameTime) {

   GraphicsDevice.Clear(Color.Black);

 

   spriteBatch.Begin();

   _player.Draw(gameTime, spriteBatch);

   spriteBatch.End();

 

   base.Draw(gameTime);

}

 

And that’s about it! We have a decent Sprite class and we’ve converted the player’s ship to use it. We can do a similar thing to the Star class, which is now obsolete. We can directly use the new Sprite class instead. I’ll leave that as an exercise for the reader. The attached ZIP replaces the Star with a Sprite.

XNA 2D Game Tutorial (Part 4)

Published at Nov 06 2010, 12:06 AM by pavely

Previous posts in this series: Part 1, Part 2, Part 3.

Our sprite ship is moving with the help of the arrow keys. But it doesn’t seem to be travelling through space. Perhaps we should add some starts going by, as the ship travels forward at incredible speeds…

We could continue with the same basic idea we use with the player’s ship: Add appropriate variables, update stars position in the Update method and draw them all in the Draw method. This will cause some bloating of Update and Draw, not to mention the alien enemies we’ll add later, the bullets the player and the aliens fire, etc.

There must be a better way to segregate the different parts of the game, adding some control along the way. For example, in the title screen that every game should have, you don’t expect the enemy aliens swooping in, shooting the player. In fact, the player ship should not be visible or controllable at that point. How can we achieve all that order and control? Enter game components.

In XNA parlance, a game component is an object, whose class derives from GameComponent or DrawableGameComponent. These components can be added or removed at will by using the Game.Components property. Furthermore, each game component can be enabled or disabled (Enabled property). This is very handy, as various game states require different participating components.

A GameComponent represents an entity with no drawable parts, and contains an Update method (very similar to the Game.Update method, and in fact called by that base implementation). A DrawableGameComponent adds a Draw method that is called by the Game.Draw base implementation. Also added is a Visible property, which allows control of whether that DrawableGameComponent’s Draw method should actually be called.

With these ideas in mind, let’s add a starfield to the game as a component. This allows separating the main game class from other game entities and allows further control of specific components.

To add a GameComponent quickly, right click the project and select Add –> New Item…. In the “Add New Item” dialog box, navigate to “Visual C#” –> “XNA Game Studio 4.0”. Select Game Component and in the Name textbox, type StarfieldComponent:

image

Click Add.

The created StarfieldComponent class derives from GameComponent. As the starfield clearly has to draw the stars, we’ll change the base class to DrawableGameComponent. The class looks like this (all XML comments removed):

public class StarfieldComponent : DrawableGameComponent {

   public StarfieldComponent(Game game)

      : base(game) {

      // TODO: Construct any child components here

   }

 

   public override void Initialize() {

      // TODO: Add your initialization code here

 

      base.Initialize();

   }

 

   public override void Update(GameTime gameTime) {

      // TODO: Add your update code here

 

      base.Update(gameTime);

   }

}

 

To actually draw something, we’ll have to manage a bunch of stars, keeping track of their position. Also, we’d want a different color for each star (perhaps selected randomly). Let’s create a simple Star class that will hold all that info:

class Star {

   public Vector2 Position;

   public float Speed;

   public Color Color;

}

 

Note that I use public fields rather than properties. This may be a bit disturbing, as we’re used to have properties (even if they are auto-implemented) as an abstraction level that allows (perhaps later) adding validation rules, etc. But when writing games, “cutting corners” is kind of allowed. Accessing a field will always be at least as fast as accessing a property (depending on optimizations and other factors), and we want to get as much speed as we can. This may not be too important for most 2D games (unless they have some complex AI logic or something), but still, it’s good to keep this in mind. We want performance. Little things can matter a lot.

Should the Star class be a value type (struct)? In this case, maybe it can. We’re going to create those stars upfront anyway, so as to minimize the chance of garbage collection along the way. This is another very important point: XNA is running on the .NET platform. This means, there is a garbage collector, and we don’t to wake it up. One way to minimize GC is to create everything we can upfront, so that during normal game play the GC would not have the need to wake up. There is no sure way to avoid GC. There is XNA behind the scenes after all, and we are unaware of all that it’s doing. But we can at least play our part. Sometimes it’s feasible to call GC.Collect explicitly where it may not be problematic, such as when moving to the next game level.

Let’s get back to the starfield. The StarfieldComponent should hold a collection or an array of Star objects and configure them accordingly:

Star[] _stars = new Star[128];

Random _rnd = new Random();

public override void Initialize() {

   for(int i = 0; i < _stars.Length; i++) {

      Star star = new Star();

      star.Color = new Color(_rnd.Next(256), _rnd.Next(256), _rnd.Next(256), 128);

      star.Position = new Vector2(_rnd.Next(Game.Window.ClientBounds.Width), _rnd.Next(Game.Window.ClientBounds.Height));

      star.Speed = (float)_rnd.NextDouble() * 5 + 2;

      _stars[i] = star;

   }

 

   base.Initialize();

}

 

The Initialize method is called automatically by the game object for all “registered” components. How do you add a component to the game? User the Components property’s Add method inside the game constructor:

Components.Add(new StarfieldComponent(this));

 

A GameComponent can always access the game object itself through the inherited Game property (you may need to cast it to the actual game class).

Note that the star’s color contains an alpha (transparency) component with the value 128 (half transparent). This will help make the stars less pronounced, so they don’t distract too much from the main entities (such as the player’s ship and the aliens). The star’s position and speed is selected at random, although a more “intelligent” choices could have been made, this will suffice for now.

How do we move the stars? As anything that is not a direct drawing operation, this is done in the GameComponent’s overridden Update method:

public override void Update(GameTime gameTime) {

   int height = Game.Window.ClientBounds.Height;

 

   for(int i = 0; i < _stars.Length; i++) {

      var star = _stars[i];

      if((star.Position.Y += star.Speed) > height) {

         // "generate" a new star

         star.Position = new Vector2(_rnd.Next(Game.Window.ClientBounds.Width), -_rnd.Next(20));

         star.Speed = (float)_rnd.NextDouble() * 5 + 2;

         star.Color = new Color(_rnd.Next(256), _rnd.Next(256), _rnd.Next(256), 128);

      }

   }

 

   base.Update(gameTime);

}

 

Each star is “moved” by its current speed in the Y direction (down the screen). if it’s out of bounds, a “new” star is generated by placing it in a random X position and somewhere above the visible area of the screen, selecting  a new random color and a new random speed.

Next up is drawing the stars. This must be done in the Draw override of the DrawableGameComponent. This method needs to be added manually, as the wizard created a GameComponent-derived class that has no Draw method. First, we need a star image, which I created by firing up Paint and drawing a 2 by 2 white square, saving it, and adding it to the Images folder of the content project (just the way we did with the ship image).

Now we need to load it as a Texture2D object, prepare a SpriteBatch for drawing and then do the actual drawing. We’ll start by overriding another method named LoadContent, very similar in concept to the same method in the game class:

protected override void LoadContent() {

   _starTexture = Game.Content.Load<Texture2D>("Images/star");

   _batch = new SpriteBatch(Game.GraphicsDevice);

 

   base.LoadContent();

}

 

We load the texture and create a SpriteBatch for later use. We could theoretically use the SpriteBatch created by the game class, but this gives us more freedom to initialize the SpriteBatch differently and independently (more on that in a moment). The Draw method looks like this:

public override void Draw(GameTime gameTime) {

   _batch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);

   foreach(var star in _stars)

      _batch.Draw(_starTexture, star.Position, null, star.Color, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 1.0f);

   _batch.End();

   base.Draw(gameTime);

}

 

A few things to note here. A more complex SpriteBatch.Begin method overload is called. This allows selecting how sprites are sorted (the Deferred value is actually the default), this is not that important at the moment. The second value (of type BlendState) is more significant. The default value (in an empty Begin call is BlendState.AlphaBlend) means that sprites are drawn considering their transparent areas (e.g. with PNG images or the areas colored with RGB=(255,0,255)). In our case, no transparency is relevant for the stars, as they are opaque squares. However, remember we set an alpha value of 128 to the color itself. We would like the stars to be semi-transparent as a whole. With AlphaBlend.NonPremultiplied we can achieve that (try removing it and see what happens – the stars are much more pronounced, a bit distracting).

Generally speaking, we can assemble other BlendState objects, but there are some predefined static fields in the BlendState class that seldom require us to do so. This is also why we need a different SpriteBatch than the one used in the game class for the player’s ship. And in any case, it’s easier to just create a separate SpriteBatch in each drawable component.

Run the game and watch the stars blaze through the empty space! We have stars! Cool.

In the next part, we’ll talk about animation and do some basic refactoring.

XNA 2D Game Tutorial (Part 3)

Published at Nov 04 2010, 08:59 AM by pavely

In part 2 we finally saw something other than a black window. Our ship sprite is just standing there: pretty boring. We want to move it a bit – perhaps using the arrow keys, so that the player has some control over her ship.

XNA supports several input devices: the keyboard, the mouse and the game pad (usually with the XBOX). Accessing all those devices is pretty straightforward and surprisingly similar. We’ll use the keyboard in our game.

To access the keyboard, we call the Keyboard.GetState static method, getting back a KeyboardState structure. This structure holds some simple methods, IsKeyDown and IsKeyUp that we can leverage.

let’s set up for moving the player’s ship right and left. First, we’ll replace the hard-coded ship position with a variable of type Vector2. We’ll manipulate that variable when the right or left keys are pressed. Querying the keyboard state and manipulating the position is done inside the Update method (remember, anything that is not a drawing operation belongs in Update). Here’s the updated Update method:

protected override void Update(GameTime gameTime) {

   // Allows the game to exit

   if(GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)

      this.Exit();

 

   KeyboardState ks = Keyboard.GetState();

   if(ks.IsKeyDown(Keys.Escape))

      Exit();

   if(ks.IsKeyDown(Keys.Right))

      _pos.X += 5;

   else if(ks.IsKeyDown(Keys.Left))

      _pos.X -= 5;

 

   base.Update(gameTime);

}

 

Let’s update the Draw method to use the new Vector2 object named _pos:

protected override void Draw(GameTime gameTime) {

   GraphicsDevice.Clear(Color.Black);

 

   spriteBatch.Begin();

   spriteBatch.Draw(_playerShip, _pos, Color.White);

   spriteBatch.End();

 

   base.Draw(gameTime);

}

 

Every press of the right or left key moves the ship 5 pixels. Moving far to the right or to the left makes the ship disappear. No bounds checking is performed by XNA – it’s up to you to check and act appropriately if needed. Here’s some code that bounds the ship to the right and left edges of the window:

if(_pos.X < 0) _pos.X = 0;

else if(_pos.X > Window.ClientBounds.Width - _playerShip.Width)

   _pos.X = Window.ClientBounds.Width - _playerShip.Width;

 

This code is a bit awkward to write. Saving the width of the window in a field would be better (and faster, too, as we’re accessing two properties to get to the Width; very expensive in game terms). Note that the code assumes the position is of the top-left corner of the sprite. We’ll see how we can change that in a moment.

More on SpriteBatch.Draw

As we saw in part 2, there are several overloads to SpriteBatch.Draw. Up until now, we used the simplest – just specify the texture, position and the “color”.

A more interesting overload allows scaling the sprite, rotating the sprite and setting a different origin (as opposed to 0,0 – the top-left corner).

Let’s first make the sprite bigger – it seems too small for our selected resolution of 800x600. We’ll change the Draw call to the following:

spriteBatch.Draw(_playerShip, _pos, null, Color.White, 0, Vector2.Zero, 2, SpriteEffects.None, 0);

 

The null parameter indicates a Rectangle (Nullable<Rectangle> or Rectangle? to be precise) that we can use as a source inside the texture. This means we can have a large image and only extract a part of it. In this example, the entire image is the ship, so null indicates the entire image texture. The zero after the color indicates the rotation angle (in radians). Here we specify no rotation. This is quite handy, and can save us the trouble of pre-rotating an image to various angles – we can simply specify the angle and be done with it. Note that the rotation point is the next parameter indicating where any positioning or rotation originates. in this example, its Vector2.Zero or simply X and Y of zero (this is the default). if we specify something like new Vector2(_playerShip.Width / 2, _playerShip.Height / 2), that would make the center point of the ship as the (0,0). This affects the position setting and the rotation point.

The next argument is the scaling factor – here I specify 2. This means the sprite will be drawn at twice its width and height. Note that this disrupts our bound checking code and we need to change that:

if(_pos.X < 0) _pos.X = 0;

else if(_pos.X > Window.ClientBounds.Width - _playerShip.Width * 2)

   _pos.X = Window.ClientBounds.Width - _playerShip.Width * 2;

 

Note the multiplication by 2 factor. This is becoming really awkward – and begs some refactoring – perhaps some Sprite class that would take care of all those little details? We’ll add something like this in a later part. For now, just be aware of the nuances.

The next argument is a SpriteEffects. None does nothing (dah), but you can flip horizontally (FlipHorizontally) or vertically (FlipVertically).

The last argument is a Z layer index. That means, sprites may be drawn in any order and their actual Z order will be based on that parameter. The accepted range is 0.0 to 1.0, where 0.0 is in front and 1.0 is way back. The default is 0.0. We’ll see some usage of that in a later part.

Where are we?

We have a player-controlled sprite, with bounds checking. What’s next? Perhaps some stars passing by, so we may feel like we’re actually moving. That’s in the next part.

XNA 2D Game Tutorial (Part 2)

Published at Nov 02 2010, 12:18 PM by pavely

In the first part we just created a black window. It’s time to see something more interesting.

The first thing we’ll do is change the window size. The window size is important for practical purposes – all our sprites (soon to be drawn) need to be with a good relative size, the space for movement must be sufficient, etc. The other thing is full screen mode. In a typical game, immersion is the keyword. To immerse the player inside the game, she should not see the taskbar, messenger popping up, etc. The game needs to run full screen. For debugging and development purposes, however, we’ll run the game windowed.

So, how do we set the window size, and whether we want a full screen game? Simple, set some properties in the game constructor:

graphics.PreferredBackBufferHeight = 600;

graphics.PreferredBackBufferWidth = 800;

graphics.IsFullScreen = false;

Window.Title = "Alien Raid Demo Game";

 

This should suffice. The game will run at a resolution of 800x600, windowed (for now). I also set the Window title to something more appropriate.

Drawing Sprites

The term “sprite” is pretty old, dating back to the golden era of personal computers during the 80s. As I mentioned in the first part, the Commodore 64 had 8 hardware sprites. What this meant was, that I could set their shape (which need not be rectangular and could have transparent areas), set their position and not worry that a sprite will disturb the text, graphics or other sprites while moving. There was no need to “delete” it from its previous location when moving. All this was incredibly useful back in those days.

There are no sprites today in the way it was back then. But we don’t actually need that same support. CPUs and GPUs are so powerful, that the typical game redraws its graphics from an empty window each and every frame. So, no need to worry about “deleting” old images. Transparency support is also inherent and does not require anything special, except preparing the images with transparent regions (we’ll see how to do that in a moment).

The Player’s Space Ship

Our game hero controls a spaceship that will battle the evil aliens. To draw the ship, we first need to add it as an asset, or content, to the game. Then, we’ll load it in code and draw it.

The player’s ship will have (for now) a single image. You can download it here.

The AlienRaidContent project will hold all our game assets (images, audio files, fonts, etc.). First, right click the project and select Add –> New Folder. Name it Images. Then right click the newly created folder and select Add –> Existing item. Navigate to the location where you saved the ship.png file and select it.

Images in XNA are represented by the Texture2D class. We’ll need to load the image into a Texture2D object and then we can move on to drawing.

Add a private field to the game class named _playerShip of type Texture2D. Loading content is done in the LoadContent method of the game class. Currently it has code that creates a SpriteBatch, which we’ll need soon enough for drawing. Add the following code to LoadContent:

_playerShip = Content.Load<Texture2D>("Images/ship");

 

Note that when building the project, the ship.png file turns into a ship.xnb file. XNB is XNA’s internal format for game assets (all assets turn into XNBs). Note also that you don’t specify the extension of the asset name (in this example, just “ship”).

The ContentManager.Load<> generic method just used can be (and will be) used for other assets as well.

Now that we have an image, we can draw it. Drawing images (effectively sprites) is done inside the game’s Draw method using a SpriteBatch. A SpriteBatch is a kind of manager for drawing a series of sprites. It can set some default behaviors for all drawing operations within it. Add the following code to the Draw method, after the call to Clear:

spriteBatch.Begin();

spriteBatch.Draw(_playerShip, new Vector2(400, 500), Color.White);

spriteBatch.End();

 

The spriteBatch instance was created in the LoadContent method by the VS 2010 wizard.

Running the game produces this output (clipped):

image

A call must be made to Begin, followed by calls to Draw (as many as needed) and finally a call to End sends drawing instructions to the graphic card (not exactly, but conceptually true).

The SpriteBatch.Draw has 7 overloads. In the previous snippet, I’ve used the simplest possible overload, supplying the texture to draw, the position to draw at (by default, the position of the upper-left corner of the texture) and something curious of type Color.

Color is the type that represents a color, with Red/Green/Blue components (RGB) and an Alpha component (transparency, more on that in a later part). So, what does a Color parameter has to do in here? I mean, the image has its colors, why should we supply any color at all? And why did I supply a White color (where R=G=B=255, the maximum)?

The color parameter is a kind of filter. For example, if I change the color to Color.Red (meaning R=255,G=0,B=0), this what we get:

image

That means the red component went through, while green and blue where filtered out. Let’s try Color.Green:

image

This time the green component is the sole survivor. Let’s try something like new Color(128, 255, 92):

image

We get a mixture: red component passes through with about half power (128/255), green is fully existing, and blue passes with 96/255 power.

Overall, this parameter allows us to customize each and every drawing for some special effect. We’ll use that in later parts. For now, reverting to Color.White preserves the original image.

What about transparency? The ship is clearly non-rectangular, but the ship image is. How can we specify transparent areas? There are two ways. The first is to use an image format that is capable of carrying transparency information, e.g. PNG. Our ship is indeed a PNG file, but the PNG file was drawn in a way that paints the relevant pictures with transparent pixels. This can be done with appropriate software, for example the free Paint.NET. Note that MS paint cannot handle transparency, so saving a PNG through paint will always be opaque.

The other way to make transparent pixels is to paint them with the “special” color whose R=255,G=0,B=255 (a kind of appalling pink). This color was selected because it’s highly unlikely you’d want it in a normal image… so any supported format (BMP, JPG, etc.) that uses this color will be considered transparent for transparency purposes.

We’ll talk about the other variations of SpriteBatch.Draw in later parts.

This wraps up the second part. Enjoy your sprites!

XNA 2D Game Tutorial (Part 1)

Published at Nov 01 2010, 10:30 AM by pavely

I like creating games. In fact, that’s what drew me into the computer world back in 1983. It’s amazingly satisfying seeing one of your creations looking like it’s alive, making decisions and reacting to the player’s actions. Back then I used to create games for the legendary Commodore 64, with it’s 64KB of RAM (of which about 39K was free for the programmer), 1MHz 6510 CPU (yes, 1 mega-hertz!), its video chip (VIC) that supported 8 hardware sprites (more on that in a bit) and its sound chip (SID) that supported 3 independent voices including white noise. It was a mean gaming machine for its time, leaving computers such as Apple II and ZX Spectrum eating dust.

Days and years went by… the PC took over all other machines, mainly because of its open architecture. Now fast forward to 2010. We have monstrous CPUs and GPUs, the latter capable of handling many graphic tasks that used to be handled by CPUs alone.

There are many libraries and frameworks for writing games these days. Most of them are capable graphic engines, written in C++ for C++ consumption. There are others, however. One of them is the Microsoft XNA framework, born a few years back and now in it’s 4th major version. This framework allows programming games in .NET, targeting the PC, XBox 360, Zune (up until version 3.1) and now the Windows Phone 7, all with high source code compatibility.
Although Windows Phone 7 is the big hype at the moment, I want to present a tutorial that uses the plain old PC as the gaming platform. Changing it to WP7 or XBOX is not too difficult and maybe I’ll tackle that in the last part of this series. Note that there are plenty of tutorials out there… but this is mine.

Getting started

To get started, you’ll need Visual Studio 2010 (any edition, including Express), XNA Game Studio 4, and (if you want to develop for Windows Phone 7) the tools for Windows Phone 7. All these are free downloads (VS 2010 express version only), so go ahead and download and install the bits.

Open VS 2010 and select File->New Project. In the new project dialog box, navigate to Visual C#. You should see a sub-node named XNA Game Studio 4.0. Select the Windows Game (4.0) option in the right side and enter a name for the project. We’ll call it AlienRaid and it will be a pretty classic shooter, that will allow me to show XNA stuff, while walking in familiar territory. This will be a 2D game (I may tackle 3D in a later time) – don’t underestimate 2D – we can create fun games with whatever technology or game type!

The complete game will look something like this:

SNAGHTML38952709

The dialog box should look something like this:

image

Click OK.

You’ll see 2 projects created, named “AlienRaid” and “AlienRaidContent”. We’ll get to the reason for the two projects later. The main project hosts the Game1.cs file. For now, just press F5 or Ctrl+F5 to run the game. If everything is setup ok you should see something like this:

image

Not an amazing game yet, but it’s a start!

Notice that the mouse cursor disappears when hovering over the window. Close the window using the X button or press Alt+F4.

Let’s explore some of the code generated by the wizard. The Game1.cs class hosts a Game1 class inheriting from the XNA Game class. This is the main class of any XNA game. A single instance of it is created in the Main method (look at program.cs):

static void Main(string[] args) {

   using(Game1 game = new Game1()) {

      game.Run();

   }

}

The Run method only returns when the game exits.

First, we’ll do some simple refactoring and change the name of the game class to something more appropriate. In the Solution Explorer, rename Game1.cs to AlienRaidGame.cs. This will also change the class name from Game1 to AlienRaidGame.

Every game must have a game loop. A game loop is some code that’s run over and over again, each and every frame at some frame rate. XNA uses 60 frames per second (FPS) by default. That means the game loop runs every 16.66667 milliseconds. Where is the game loop located? That’s the two methods named Update and Draw of the game class.

First, let’s look at Draw:

protected override void Draw(GameTime gameTime) {

   GraphicsDevice.Clear(Color.CornflowerBlue);

 

   // TODO: Add your drawing code here

 

   base.Draw(gameTime);

}

 

Right now, it doesn’t do very much. The first instruction simply clears the drawing buffer to some color (that’s the color in the previous snapshot). If we are to create a space shooter, we probably want a black background, so let’s change the color to black:

GraphicsDevice.Clear(Color.Black);

 

Run the game and note the black background.

Generally, the Draw method is the placing all drawing code that’s needed to render the scene. This means the player’s ship, the alien enemies, the score, the various projectiles – everything must be drawn somewhere within this method. And it’s all drawn 60 times a second! This is how a game works. A game is never idle. It’s always doing something.

We still haven’t drawn anything... we’ll do that in part 2.

Let’s examine the Update method:

protected override void Update(GameTime gameTime) {

   // Allows the game to exit

   if(GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)

      this.Exit();

 

   // TODO: Add your update logic here

 

   base.Update(gameTime);

}

 

The first thing happening is the checking of the XBOX game pad for a Back button press, and if pressed, the game exist by calling the Game.Exit method. Since we’re using the PC, we may not have a game pad available, let’s add code that exits the game when the ESC key is pressed. We can replace the existing code or simply add to it, so that both options are available.

To accomplish this, we’ll use the Keyboard.GetState static method, that will allow us to examine the state of any key we desire:

if(Keyboard.GetState().IsKeyDown(Keys.Escape))

   Exit();

 

The code tests to see if ESC is pressed and if so, calls the Exit method. Nothing to it!

What is that GameTime object we’re getting in Update and Draw? This object has two uses: the first, it indicates how much time has passed since the last call (to Update or Draw) in the ElapsedGameTime property (of type TimeSpan). These allows for timing thing more accurately, regardless of the actual frame rate. We’ll see examples of this in a later part. The second use is the IsRunningSlowly property. If true, it indicates XNA can’t keep up with the desired frame rate, so it may call Update more times (and not call Draw) to compensate. This is an advanced property and we won’t deal with it now. In a typical 2D game, it should be rare to get to a slowly running game, and even if we do get there, it’s usually very temporary.

In the next part we’ll start drawing something. Until then, the resulting project is attached.