DCSIMG
December 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

December 2010 - Posts

XNA 2D Game Tutorial (Part 14–Last)

Published at Dec 31 2010, 06:54 PM by pavely

Previous posts in this series:

Over the past posts, we’ve created a game. A simple game, for sure, but the objective was learning XNA, not creating the greatest game ever.

Creating a game is more than just using some technology, programming language or device. The more difficult part is actually making the game fun. This is an art more than a craft, and involves game design, game play, artificial intelligence and more. This post series concentrated on the mechanics of making a game with XNA, but this is (relatively) the easy part.

We’ve covered most of the XNA ground in 2D. We are now capable of creating a complete game. All that’s left to do is start programming a unique game! This is no mean feat. It takes time, patience and creativity, as well as programming skills that hopefully were developed throughout this series.

The final game source rounds off thing started in previous parts. Player lives are tracked, boss alien appears before moving to the next level and aliens also fire missiles. Still more additions are possible, such as “power ups”, various items falling from (e.g.) dead aliens that give out various abilities and disabilities, such as: faster fire power, a shield for (say) 10 seconds, faster ship speed, slower ship speed, a bonus ship, etc. I’ll leave that as an exercise for the reader.

Writing games is one of the most challenging programming tasks as it involves so many disciplines, such as graphics, sound, animation, artificial intelligence, storytelling and more. This is one reason it’s so challenging – and fun!

The series covered 2D games only. 3D games are quite different, requiring extended skills. The skills learned in this series are not wasted in 3D. It just takes some extra ones. I will consider writing a similar series for an XNA 3D game if demand is high enough.

Until then, happy game programming (oh, and a happy new year!)

Visual Studio 2010 SP1 Beta: What’s new in MFC?

Published at Dec 25 2010, 03:23 PM by pavely

The recently released Visual Studio 2010 SP1 Beta brings many enhancements and bug fixes found since the product’s launch, most of them in the managed world. However, there are new enhancements to the good(?) old MFC, namely wrapping of some of the Direct2D interfaces.

Direct2D is a new layer in the DirectX world, sitting on top of Direct3D, providing high performance and flexible 2D graphics. It was introduced with Windows 7 and Windows 2008 R2, but it’s also possible to install it on Windows Vista. What’s wrong with Direct3D? Nothing, but doing 2D graphics is difficult using the Direct3D API alone. The old DirectDraw interfaces are good at blitting images (“sprites”) but no nothing about 2D shapes, such as ellipses, or interesting brushes, such as a linear gradient brush. This is what Direct2D is for (and image blitting as well).

MFC has been around for about 20 years and still around with us today. It’s been criticized as being bloated and poorly designed, especially in today’s standards and the existence of something like WPF hasn’t helped either. However, it’s the only real C++ UI alternative from Microsoft at the moment (although some enthusiastic people use WTL for their UI). Hopefully, Microsoft will come up with a new unmanaged library for doing UI and UX, with power and flexibility rivaling WPF, but until then, we have MFC.

The new Direct2D MFC classes integrate with the rest of the MFC framework, making it easy to integrate into existing applications.

Another new face in MFC is the wrapping the Windows Animation Manager (also introduced in Windows 7) that allows high level animations, somewhat similar to the declarative approach used in WPF and Silverlight.

It’s good to know improvements and enhancements in the Visual Studio ecosystem are present in the native programming world as well as the managed.

XNA 2D Game Tutorial (Part 13)

Published at Dec 19 2010, 06:49 PM by pavely

Previous posts in this series:

 

In a typical game, when a user double-clicks the EXE file, the game does not start right away. At the very least, an introduction screen is presented with some menu offering to start the game, maybe change some options, view high scores, etc. At the very very least, the player needs to “press any key” or something similar to get into the action.

Furthermore, when a game is over, there is typically some ending screen with the total score, perhaps some ranking system, a high score list or whatever.

To do all that, we need to manage game states. A simple game might need three states: Introduction, Playing and Game over. Managing states is not difficult with XNA when working with game components, as we have. Each game component can be “turned on” or “turned off”, so only a subset of game components are active at any one time.

Let’s add an introduction component. Add a new GameComponent by selecting Add New Item from the project right click menu. Name it IntroComponent. As usual, change the base class from GameComponent to DrawableGameComponent, as we need to draw some introduction stuff.

Let’s add to that class a SpriteBatch, and two fonts, one big and one small (we’ll use the Stats font we added in a previous post for the small version). We’ll load the fonts as usual, and create the SpriteBatch as usual as well. Here’s the Draw method we create:

public override void Draw(GameTime gameTime) {

   _batch.Begin();

   _batch.DrawString(_font, "ALIEN RAID", new Vector2(150, 120), Color.Yellow);

   _batch.DrawString(_smallFont, "Press ENTER to play", new Vector2(280, 250), Color.Cyan);

   _batch.End();

 

   base.Draw(gameTime);

}

 

Next, we’ll add a readonly field to the game class (as we did with other components) and add the component to the Components collection in the constructor:

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

 

Running the game now has a strange effect: the title is displayed but the game is playing…

What we want is to disable and hide the IntroComponent while the game is actually playing.

First, let’s define some game states. Add the following code before the declaration of the AlienRaidGame class:

public enum GameState {

   Intro, InPlay, GameOver

}

 

We have the three basic states: introduction, playing and game over. To switch between states, we’ll add a property indicating the current state and create a helper method in the game class that switches on or off the appropriate components:

public GameState State { get; private set; }

 

public void GotoState(GameState state) {

   switch(state) {

      case GameState.Intro:

         IntroComponent.Enabled = IntroComponent.Visible = true;

         AliensComponent.Enabled = AliensComponent.Visible = false;

         PlayerComponent.Enabled = PlayerComponent.Visible = false;

         GameOverComponent.Enabled = GameOverComponent.Visible = false;

         break;

 

      case GameState.InPlay:

         IntroComponent.Enabled = IntroComponent.Visible = false;

         AliensComponent.Enabled = AliensComponent.Visible = true;

         PlayerComponent.Enabled = PlayerComponent.Visible = true;

         GameOverComponent.Enabled = GameOverComponent.Visible = false;

         break;

 

      case GameState.GameOver:

         IntroComponent.Enabled = IntroComponent.Visible = false;

         AliensComponent.Enabled = AliensComponent.Visible = false;

         PlayerComponent.Enabled = PlayerComponent.Visible = false;

         GameOverComponent.Enabled = GameOverComponent.Visible = true;

         break;

   }

   State = state;

}

 

Pretty straightforward. The more compute-science inclined might say that we need to build a full fledged state machine with states and transitions and …

Forget it. It’s not worth the trouble, and a simple switch will do even if we need a few more states along the way.

The Enabled property of a GameComponent specifies whether Update should be called. The Visible property specifies whether DrawableGameComponent.Draw should be called. Usually, both will be set to the same value. Note that the starfield component is always visible and enabled (which is the default). I decided I want to see the starfield even in the introduction screen.
Now that we have this in place, we can start with the “Intro” state by calling GotoState in the game’s constructor:

GotoState(GameState.Intro);

 

Running the game now makes the intro visible (along with the starfield) but the game does not go any further. We need to make good on our promise and play the game when ENTER is pressed.

For this we’ll modify IntroComponent.Update to check for the appropriate key and transition to the new state when needed:

public override void Update(GameTime gameTime) {

   var ks = Keyboard.GetState();

   if(_previousKS.IsKeyDown(Keys.Enter) && ks.IsKeyUp(Keys.Enter))

      AlienRaidGame.Current.GotoState(GameState.InPlay);

   _previousKS = ks;

 

   base.Update(gameTime);

}

 

The _previousKS is a KeyboardState field that keeps track of the previous state. This helps to wait when the ENTER key is released after being pressed. Then we transition to the InPlay state.

Similarly, we can add a GameOverComponent and switch to that state when the player is killed (when Lives reach zero). From there, we can override Update again, and wait for some key and return to the Intro state or even straight to the InPlay state. The attached code has the GameOver state implemented (the player has currently one “life”).

That the idea of states and state management. It’s pretty convenient given the Components model.

In the next (and final) part I’ll talk about some more features we can add, and discuss some philosophical issues related to game development and XNA.

XNA 2D Game Tutorial (Part 12)

Published at Dec 05 2010, 03:55 PM by pavely

Previous posts in this series:

Teched is over. Time to get back to XNA…

In our current project, we have a simple game in which the player can shoot aliens. They keep coming, and once the player is killed – the game is technically over, although the alien enemies keep on coming. What’s left? The aliens may fire perhaps, the player needs more than one “life”, we should display some score, we need to end a level sometime… etc.

It seems there’s a lot to do, and there is. A game is a complex piece of software. In this part, we’ll take a look a displaying some statistics, as we have not yet tackled text displays.

Displaying Text

To display some text, we’re going to need a font. Unlike “regular” frameworks (e.g. WinForms, WPF), there is no direct Font class, as XNA is adept at “blitting” sprites (in the 2D world) and nothing else. What we need is a sprite based font, which is another content type we can use.

Right click the content project and select “Add New Folder…”. Name it Fonts. Right click the newly created folder and select “Add New Item…”. Select the Sprite Font item, give it a name, such as Stats.SpriteFont and click “Add”:

image

The result is an XML file, describing a font, such as the font name, its size, spacing and more. This is your chance to customize the resulting font. For example, let’s change the font name to Arial:

<FontName>Arial</FontName>

 

Feel free to change other properties of the font.

To use the newly created sprite font we need to load the content in the usual way, and then use SpriteBatch.DrawString to display a string with our font in a suitable position.

To make this more concrete, we’ll display a score for the player. To do that, we’ll add a Score field to the PlayerComponent class, and update that when an alien is killed:

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

   // alien hit!

   bullet.Active = false;

   alien.Hit();

   Score += alien.Type.Score * AlienRaidGame.Current.Level;

   _explodeSoundInstance[i].Play();

   break;

}

 

This is part of the PlayerComponent.Update method. First, we’ll load the font in PlayerComponent.LoadContent:

_statsFont = Game.Content.Load<SpriteFont>("Fonts/stats");

 

_statsFont is a private field in that class. To display the score, we’ll add an appropriate call in PlayerComponent.Draw:

_batch.DrawString(_statsFont, string.Format("Score: {0,5}", Score), new Vector2(30, 30), Color.Yellow);

 

That’s about it. We have text!

As another statistical item, let’s add more “lives” for the player and display them as images of the space ship to indicate the actual lives remaining. First, we’ll create a field called Lives to serve as our life counter. Then we’ll display that with “regular” calls to SpriteBatch.Draw:

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

   _batch.Draw(_playerShip, new Vector2(i * 30 + 30, 60), new Rectangle(0, 0, _playerShip.Width / 2, _playerShip.Height), Color.White);

 

This gives the following display:

image

The only remaining thing is to actually update Lives when appropriate. I’ll leave that as an exercise for the reader (for now).

In the next part we’ll take a look at game states and how to manage them.

My TechEd Session: MEF & Unity

Published at Dec 02 2010, 08:52 PM by pavely

My session was scheduled for the last time slot of the conference. I was really glad to see so many of you there, especially considering that many people were on their flights back home and there was Alex’s XNA session right next door. Thank you all for coming! I talked about the idea of Inversion of Control (IoC) and one way of achieving that, through Dependency Injection (DI). The slides can be downloaded from here, and the demos from here.

In the old COM days, the legendary Don Box (now at Microsoft, one of the architects of WCF) said “COM is Love” (and he had demonstrated that in a number of ways, such as “COM” written on his underwear – yes, he did actually show that during a session, and his car license plate was “IUnknown”). I say, “MEF is Happiness”. I hope you’d agree. What about Unity? Unity is happiness in its own way, and its injection capability is interesting, with no MEF equivalent. By the way, that injection can be used without Unity being used as an IoC container, by using the Interception class.

Until next TechEd!