BreakOut 3D

For educational purpose only.

OK, I m sorry for not having the imagination to come up with something on my own but I really love those classic games. I really miss those days when everything was simple and in two directions. But now its different, people today must have everything in 3d. So here it is, my version of breakout.

The game resolution is 1024x768 and the objects are many and rather complex, therefore the game needs quite good hardware to run properly. I designed the game to run 50 f/s.

BreakO7.jpg

Known bugs :

At some hardware/driver configurations bricks is not present.

General Information :

To play this game you will need to install .NET framework and managed DirectX 9.0(mdxredist.msi).

To compile this game you will need to install .NET framework and DirectX 9.0 SDK(dx9sdk.exe). If it wont compile include the resource files (.dll) that is needed from the file DirectX.cab and put them in the folder Microsoft.NET/framework/vxxxx/ in under Windows.

The resources :

The sound effects are freeware from http://www.flashkit.com/soundfx/
The songs are for you to copy to folder Audio/Mp3/
The Textures are from
http://www.redfieldplugins.com/Textures.htm
The DirectX objects are made with Maya 4.0
The backgrounds are freeware from
http://www.mediabuilder.com/

Description :

The first thing I do when Im programming something that I havent worked with before is of course to gather information. I found the main things I needed for my project in the samples given in the SDK. Microsoft didnt make this any easy reading though.

I think that its really important to fully understand every piece of code you write. The people that doesnt agree with me and just copy code from other projects will do later on, when they try to add/change/remove something and they dont know squat about how things works.

I would be proud to say that I now know everything about the sample code that I read from Microsoft SDK, but guess what, I dont. It seems that if that was my goal I would probably still be reading it. Because of this there is unfortunately some code that I do not fully understand, but I managed to get the crucial parts out of it and made some classes to help me in my programming. Classes that make programming easier is a good thing to do when you learning something new.

The classes that are named DirectX are not from Microsoft. They are the classes that help me with the structure and the many different DirectX functions. The best things about these classes are that they are made for one purpose and of course that they are recyclable.

BreakO8.jpg

As you can see from the diagram all the action leads to the main class Breakout3d. This class got a little to big and difficult to understand. Sorry for that but its quite a big game.

Game Classes :

I will not include or comment any code from the actual game (game classes) here. Its for you to read by your self. But dont let that stop you. For those who consider themselves to be intermediate programmers the reading should be easy as pie.

The main class goes like this :
Timer -> FrameMove -> RenderScene

This is a common structure. The objects and camera are moved in the function FrameMove() and are rendered in RenderScene(). Together with different states makes this a standard way to program. This type of programming is also used i.e. real-time programming of state machines.

The code written in this class together with the different classes for the game objects is the core. It tells us everything about the game, but it doesnt tell us anything about how the game really is communicating with its surrounding environment. The DirectXClasses below gives us the necessary information.

DirectXBackground :

vertexBackground = new VertexBuffer( typeof( CustomVertex.TransformedColoredTextured ), 4, device, Usage.WriteOnly, CustomVertex.TransformedColoredTextured.Format, Pool.Default );CustomVertex.TransformedColoredTextured[] v = new
CustomVertex.TransformedColoredTextured[ 4 ];
for(int i = 0; i < 4; i++)
{
v[ i ].SetPosition(
new Vector4( position.X, position.Y, position.Z, 1.0f ));
v[ i ].Color =
unchecked( ( int )0xffffffff );
}
v[0].Y = (
float )device.PresentationParameters.BackBufferHeight;
v[2].Y = (
float )device.PresentationParameters.BackBufferHeight;
v[2].X = (
float )device.PresentationParameters.BackBufferWidth;
v[3].X = (
float )device.PresentationParameters.BackBufferWidth;
v[0].Tu = 0.0f; v[0].Tv = 1.0f;
v[1].Tu = 0.0f; v[1].Tv = 0.0f;
v[2].Tu = 1.0f; v[2].Tv = 1.0f;
v[3].Tu = 1.0f; v[3].Tv = 0.0f;
vertexBackground.SetData(v, 0, 0 );

vertex points in the 3d world, these four vertexes forms a square where the background will be drawn. The first thing we do here is to pick a reference. This is done in the for loop above where the vertexes are getting same positions. Then just move them where you want youre background to be placed. Last we call a function to set the data in the vertex buffer that is linked the directx3d device.

Remember that these functions do not exclusively need to be applied on backgrounds.

device.SetTexture( 0, textureBackground );
device.VertexFormat = CustomVertex.TransformedColoredTextured.Format;
device.SetStreamSource( 0, vertexBackground, 0 );
device.DrawPrimitives( PrimitiveType.TriangleStrip, 0, 2 );

This is the code to render the background. First we tell the directx3d device that we want to draw a texture. Then we tell the device which vertex format that it should use. Before we call the draw function we bind the vertex buffer to a data stream port (see the SDK documentation for more information).

DirectXCamera :

Matrix view = Matrix.LookAtLH( cameraPosition, cameraDirection, cameraUpDirection );
device.SetTransform( TransformType.View, view );
Matrix projection = Matrix.PerspectiveFovLH( fFieldOfView, fAspectRatio, fNearPlane, fFarPlane );
device.SetTransform( TransformType.Projection, projection );

Every collection of information in a 3d world is described in matrices. A matrix is a bunch of numbers that describes something like shapes, functions or in this case information about a slice in a 3d world.

This code tells the device where we want to place our point of view. First make a matrix over the area you want to look at with the function LookAtLH () which builds a Left-Handed view matrix. Then tell the device that this is our view. The device now needs one last thing and thats a perspective. We inform the device about the perspective in the same way as for the view. The function PerspectiveForLH() builds a left handed projection matrix with the given parameters. If you are programming in 2d you should use the function OrthoLH() instead.

DirectXMisc :

Contains functions for finding files, show statistic etc.

DirectXFont :

Mesh threeDText = Mesh.TextFromFont( device, textFont, text, fDeviation, fExtrusion);

The 3d font is just an ordinary mesh. The static function TextFromFont() builds the mesh. The render and move functions are the same as in the class DirectXObject.

DirectXLight

Its not much fun without lights.

device.Lights[ lightNo ].Type = LightType.Point;
device.Lights[ lightNo ].Position = lightPosition;
device.Lights[ lightNo ].Attenuation1 = fAttenuation;
device.Lights[ lightNo ].Diffuse = diffuseColor;
device.Lights[ lightNo ].Ambient = ambientColor;
device.Lights[ lightNo ].Range = 100.0f;
device.Lights[ lightNo ].Enabled =
true;
device.Lights[ lightNo ].Commit();

This is very simple. The device keeps track of every light and every light needs to have a unique number. The number is of type short which is a 16 bit variable but you can only use eight active lights at the same time (if you really need to I think there is a way to get more). Then its just to fill in the properties of the light and call the function Commit(). There are three types of lights, directional, point and spot. The code above is for a point light. The other lights are created in the same fashion with the difference that the directional lights dont use the position attribute and the spotlight needs a direction etc. etc.

DirectXObject :

This class contains the code for building a mesh from a directx mesh file (.x).

Mesh systemMemoryMesh = Mesh.FromFile( strPath, MeshFlags.SystemMemory, device, out adjacencyBuffer, out Mat ); // GraphicsStream ,ExtendedMaterial

Load the .x file. The Extended material Mat gets the information about texture names and material properties which (if they exist) can be found in the file. AdjacencyBuffer is a stream containing graphic data. This variable can be used for optimizing the mesh which is a very good thing to do.

systemMemoryMesh.OptimizeInPlace( MeshFlags.OptimizeCompact | MeshFlags.OptimizeAttrSort | MeshFlags.OptimizeVertexCache, adjacencyBuffer );

Optimize, Optimize, Optimize

for( int i = 0; i < Mat.Length; i++ )
{
materials[ i ] = Mat[ i ].Material3D;
materials[ i ].Ambient = materials[ i ].Diffuse;
if ( Mat[ i ].TextureFilename != null )
{
// Create the texture
string texturefilename = DirectXMisc.FindFile( null, Mat[ i ].TextureFilename );
textures[ i ] = TextureLoader.FromFile( device, texturefilename );
}
}

A mesh can have many different textures. This for loop takes every texture that was found in the .x file and creates the textures.

for( int i=0; i < materials.Length; i++)
{
device.Material = materials[ i ];
device.SetTexture( 0, textures[ i ] );
systemMemoryMesh.DrawSubset( i );
}

To render the object just tell the device what material and what texture to use and then call the function DrawSubset() from the mesh object.

DirectXSound :

AudioVideoPlayback.Audio mp3 = new AudioVideoPlayback.Audio(mySong.mp3);
mp3.Play();

As you can see above, to play an mp3 in a directx application is a very easy thing to do, thanks to the AudioVideoPlayback classes and functions.

DirectSound.Device soundDevice = new DirectSound.Device();
// game = the main form = System.Windows.Forms.Control
m_soundDevice.SetCooperativeLevel( game, DirectSound.CooperativeLevel.Priority );
DirectSound.Buffer sounds =
new DirectSound.SecondaryBuffer( myWav.wav, soundDevice );

To play sounds is a little more work. First we must create a device for the sound and then set the CooperativeLevel.

sounds.Play( 0, DirectSound.BufferPlayFlags.Default );

Then just press play

Breakout3dMap :

The program I wrote to create maps. I wrote it in two hours so dont expect much.

What you can learn or copy .

Mp3 implementation
Sound implementation
Meshes, textures and objects (Backgrounds, 3d Fonts ..)

I m not an expert or professional programmer. I just program on my spare time so this article could contain errors and misleading information. If it does then Im sorry and you can write to my e-mail and yell at me :). But I hope it does more good than harm. Good luck everyone!