Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Invasion - C# Style

0.00/5 (No votes)
28 Jan 2003 4  
This "Space Invaders" - like game was ported to C# using the new DirectX9 to demonstrate the ease of managed DirectX.

Title Screen Middle of the game

Introduction

DirectX has changed quite a bit over the years and the new DirectX 9 offers some new things that previous versions never did.  DX9 provides new functionalities for enhanced 3D manipulations.  But one big change is the addition of a managed DirectX so that you can create applications using a .Net language and still tie into DirectX.  This is without having to work around a COM Interoperability issue.  DirectX9 directly supports managed code and makes life for the DirectX/C# developer much simpler in the long run.  The Managed DirectX classes include a DirectDraw set of classes to use for 2D manipulation.  This 2D interface is not a new version of DirectDraw - it is a wrapper to get to the DirectDraw7 interface.  This is good for a lot of developers that still want to do 2D games and also want to use a .NET language.

The DirectX SDK can be obtained from Microsoft at http://msdn.microsoft.com/directx/

Ok, enough of an introduction, let's get to the code...

The Graphics

One of the first things that I did was to convert the BMP files into PNG.  I did this for a couple of reasons.  The first is that PNG files are smaller, so that having them embedded into the executable directly will not increase the file size as much as bitmaps would.  The second reason is to demonstrate that other file formats can be used to create surfaces from.  This is not directly in DX9, but there are C# classes to read the data in correctly.  I had converted to JPG at first, but the quality setting was too low and the images did not look as good. 

Handling error codes from the calls to methods like Draw are different from DX8 too.  There is not a returned error code, just a try/catch to get the errors.

try
{
    back.Draw(new Rectangle(150, 275+(40 * iOption),32,20), 
              Selected, rcRect, DrawFlags.DoNotWait | DrawFlags.KeySource);
}
catch(SurfaceLostException)
{
    RestoreSurfaces();
}

The Sounds

Sounds ended up being a very simple thing overall, but I did have a few problems with it.  At first, the samples for using DirectSound seemed simple enough until you notice that the Device class that DirectSound uses is the same class name that DirectDraw uses.  This meant that I had to fully qualify the class names when I created those variables.

Microsoft.DirectX.DirectDraw.Device displayDevice;
Microsoft.DirectX.DirectSound.Device soundDevice;

To create the SecondaryBuffer objects to play the sounds, I decided to use a stream from the executable to get WAV files into the buffers.  To do this a GetManifestResourceStream was used.  The problems that I had here were that the resource had to be fully qualified with the assembly name too.

try
{
    SkidBuffer = new SecondaryBuffer(
              loadedAssembly.GetManifestResourceStream("Invasion.skid.wav"), 
                                     soundDevice);
}
catch(SoundException)
{
    Console.WriteLine("load sounds error 1");
}

Rest of the Conversion

Overall, the remaining parts that needed to be converted went smoothly.  I removed the linked lists in favor of the ArrayList class.  This really cleaned up the code when it came time to add/remove UFOs, bullets, and extras.  You could argue that using a vector from STL would clean up the handling of the linked list too or the use of some other type of container class.  I agree that is the reason for the conversion.

One of the tricky parts of converting an application from C++ to C# is remembering all of the little differences between the languages.  For example, in C++ you can use rand() to generate a random number.  For C#, random numbers are generated with an instance of the Random class.  This works just great, except for one thing.  I originally setup each UFO with its own random variable.  This worked just fine until I realized that each UFO was getting the same random numbers.  This is because the instance of Random, seeds the variable with the current time.  This meant that the separate UFO variables would get a random number generator all seeded with the same time.  Each of the random generators created the exact same numbers.  Once I moved the random number generator to the Invasion class, then each UFO had its own values and things worked as expected. 

Debugging

Debugging a fullscreen DirectX application is always a tricky thing to do.  For this conversion, Console.Writeline was used to print out data to the debug window. Unhandled exceptions were the root of most of the crashes that were experienced; this includes InvalidRectangleException as the biggest problem.  This seems very important with Managed DirectX to handle all exceptions with a try/catch.  A second display could have been used to make things simpler, but having the output in the debug window after the crash was good enough to fix the issues. 

History

The original code for this game came from Invasion - A computer game using DirectDraw by Mauricio Ritter.  It is a great little game that had all of the right graphics and unlimited game play.  Mauricio did a great job, so I made sure to leave his name in the credits.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here