|
|
![Sample Image - mdxtutorial1.jpg]()
Introduction
Welcome to my first tutorial on Managed DirectX, included with DirectX 9 SDK. Most C# developers were waiting for this release. Before Managed DirectX, C# developers were using DirectX via COM Interop of DirectX 7 or 8 VB component. The new Managed DirectX components offers best performance and easier programming over DirectX COM Interop. This tutorial is for newcomers in DirectX development, like me, or for people who were using COM Interop for DirectX development.
In this tutorial, we will make a clone of Super Metroid game called Managed Metroid. We will try to use all the components of Managed DirectX (DirectDraw, DirectSound, DirectInput, Direct3D, DirectPlay and AudioVideoPlayback). In part 1, we will start with basic DirectDraw implementation by showing the title screen and text in full screen.
Requirements
These articles require some knowledge of C#. Also a basic game development background would be useful.
Software requirements:
- Microsoft Windows NT4 SP6, Windows 2000, Windows XP Pro (for compiling only)
- Visual C# .NET or Visual Studio .NET
- DirectX 9 SDK Full or only C# Part (available from Microsoft
- Image editing tool (optional but useful)
- SNES Emulator with Super Metroid ROM (optional)
The Title Screen
Adding DirectX namespaces to the project
Add the references to Microsoft.DirectX.dll and Microsoft.DirectX.DirectDraw.dll to your project and add these namespaces to the project. using Microsoft.DirectX;
using Microsoft.DirectX.DirectDraw;
Adding DirectX variables
First of all, we need to create a DirectDraw device. After that, we create the Surfaces. A Surface is a part of memory where you draw the needed stuff; it also acts like a layer. The Clipper is the boundaries you set to the device, so the device will not draw over the Clipper. The back Surface represents the BackBuffer. The title and text represents the layers of the title screen. Finally, the titlescreen string point to the bitmap to load into title Surface.
private Device display;
private Surface front = null;
private Surface back = null;
private Surface title = null;
private Surface text = null;
private Clipper clip = null;
string titlescreen = Application.StartupPath + "\\title.bmp";
Initialize DirectDraw
For initializing any Managed DirectX component, I suggest you to create methods for each component you use. Here is the method I used to init my DirectDraw stuff. private void InitDirectDraw()
{
SurfaceDescription description = new SurfaceDescription();
display = new Device();
#if DEBUG
display.SetCooperativeLevel(this, CooperativeLevelFlags.Normal);
#else
display.SetCooperativeLevel(this,
CooperativeLevelFlags.FullscreenExclusive);
display.SetDisplayMode(640, 480, 16, 0, false);
#endif
description.SurfaceCaps.PrimarySurface = true;
#if DEBUG
front = new Surface(description, display);
#else
description.SurfaceCaps.Flip = true;
description.SurfaceCaps.Complex = true;
description.BackBufferCount = 1;
front = new Surface(description, display);
#endif
description.Clear();
#if DEBUG
description.Width = front.SurfaceDescription.Width;
description.Height = front.SurfaceDescription.Height;
description.SurfaceCaps.OffScreenPlain = true;
back = new Surface(description, display);
#else
SurfaceCaps caps = new SurfaceCaps();
caps.BackBuffer = true;
back = front.GetAttachedSurface(caps);
#endif
clip = new Clipper(display);
clip.Window = this;
front.Clipper = clip;
description.Clear();
title = new Surface(titlescreen, description, display);
description.Clear();
description.Width = 600;
description.Height = 16;
description.SurfaceCaps.OffScreenPlain = true;
text = new Surface(description, display);
text.ColorFill(Color.Black);
text.ForeColor = Color.White;
text.DrawText(0, 0,
"Managned DirectX Tutorial 1 - Press Enter or Escape to exit",
true);
}
The Draw method
The Draw is called each time we need to draw the content of the Surface to the screen. private void Draw()
{
if (front == null)
{
return;
}
if(this.WindowState == FormWindowState.Minimized)
{
return;
}
try
{
back.DrawFast(0, 0, title, DrawFastFlags.Wait);
back.DrawFast(10, 10, text, DrawFastFlags.Wait);
#if DEBUG
front.Draw(back, DrawFlags.Wait);
#else
front.Flip(back, FlipFlags.Wait);
#endif
}
catch(WasStillDrawingException)
{
return;
}
catch(SurfaceLostException)
{
RestoreSurfaces();
}
}
The RestoreSurfaces method
The RestoreSurfaces method is called when the user defocus the application and then refocus the application (like an Alt-Tab switch). private void RestoreSurfaces()
{
SurfaceDescription description = new SurfaceDescription();
display.RestoreAllSurfaces();
text.ColorFill(Color.Black);
text.DrawText(0, 0,
"Managned DirectX Tutorial 1 - Press Enter or Escape to exit",
true);
title.Dispose();
title = null;
title = new Surface(titlescreen, description, display);
return;
}
The Final touch
At last, add the method InitDirectDraw to the constructor. Also implement the main loop of the application where the Draw method is used. Application.DoEvents() makes the application, process the messages event if the application is in a loop. public Tutorial1()
{
InitializeComponent();
InitDirectDraw();
this.Cursor.Dispose();
this.Show();
while(Created)
{
Draw();
Application.DoEvents();
}
}
Made a change to the Main method. Application.Run method doesn't work in this context. You need to create the form by yourself. static void Main()
{
Tutorial1 app = new Tutorial1();
Application.Exit();
}
The KeyUp event, is used to quit the Tutorial. private void Tutorial1_KeyUp(object sender,
System.Windows.Forms.KeyEventArgs e)
{
if(e.KeyCode == Keys.Escape || e.KeyCode == Keys.Enter)
this.Close();
}
Conclusion
In this tutorial, we learned how to show a bitmap in full screen using DirectDraw with Managed DirectX. The next tutorial will be on sprite animation and background music with AudioVideoPlayback. If you have any comments, suggestions, code corrections, please make me a remark in the bottom of the article.
History
Update 1.1
- Fixed drawing on slower machines
- Separated code for Debug and Release, suggestion by kalme
- Release version more faster, doing a flip instead of a drawing
Update 1.0
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
About the Author
Shock The Dark Mage
![]()
|
I'm currently in College(Cegep) in Computer Science.
I'm developping since 2 years starting with C and now i'm an active C# developper.
1998 - Got my PC
1999 - Make my first web page
2000 - Started ROM Translation
2001 - Learned programming with C, first program(Final Fantasy 1 Trainer)
2002 - Learned C#, got VS.NET, started my first big programming project(Aeru IRC)
2003 - Continue Aeru IRC, Learn Managed DirectX, go to CEGEP.
2004 - Dumped Windows as my main desktop(using Gentoo Linux), remake Contra on GBA in C, learn x86 and ARM7 assembler. 2005 - Gamefu (http://sf.net/projects/gamefu/)
My current knowlegde in computer language: ARM7 assembler, C, C++, C#, PHP and Delphi.
My current active projects is a coding group called Pixel Coders found at http://www.pixel-coders.tk
| Location: |
Canada |
|
Other popular DirectX articles:
|
|
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 93 (Total in Forum: 93) (Refresh) | FirstPrevNext |
|
|
![]() |
|
|
I want to set transparent in bitmap image,don't use text.FillColor(Color.Black). Microsoft.DirectX.DirectDraw.PixelFormat _pf = front.PixelFormat; ColorKey _ck = new ColorKey(); _ck.ColorSpaceHighValue = _pf.RgbAlphaBitMask; _ck.ColorSpaceLowValue = _pf.RgbAlphaBitMask; text.SetColorKey(ColorKeyFlags.SourceDraw, _ck);
It's doen't work~
thank you~
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
Can you please give a little hint for applying alpha (for fade-in and fade-out effects). I am trying my luck in using SurfaceCaps.Alpha ne way or the other but not getting it right. There is least given on msdn about it.![]()
If there is any link for a tutorial... will be helpful
Regards
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
Ive got similar problems as 2 otehr guys who'v posted i get the "An unhandled exception of type 'System.ArgumentException' occurred in microsoft.directx.directdraw.dll
Additional information: Value does not fall within the expected range."
problem, if i comment out the line it then dose similar on the fast draw line. I use VS 2003 and sharp develope same problems in each, i downloaded octobers directX 9C files and reinstalled it same problem and im using .net 1.1 Anyone got any idea?
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
![]() |
|
|
![]() |
|
|
Hi
Nice article but check out your comments: they duplicate what the code is doing in nearly all cases. Get rid of them! If you get a job as a software developer you'll have to delete them during a code review anyway ![]()
Take it easy
Emma
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
![]() |
|
|
I think you should disregard the above comment. Most good software engineering companies require code comments, even if you are repeating what a pretty straightforward line of code does.
Do not get rid of your comments. They are informative and useful to people who have not worked in directX before.
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
I agree, it is easier to read in english than in C#. I work professionally as a software developer for years and nobody ever removed my comments. Thanks!
MCP, MCAD, MCSD.NET
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
The comments would be more helpful if they said WHY something is happening, rather than just re-iterating what the code already says.
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
you'll have to delete them during a code review anyway
Ofcourse I disagree. Today's company needs good comments inside the sourcecode. It is very helpful when one developer resigns and a new developer starts the same project... or when the project is needed to be modified years back.
PraVeeN blog.ninethsense.com/
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
I could not get the reference to Microsoft.directx.dll and Micrososft.Directx.DirectDraw.dll. I Browses to %SystemRoot%\Microsoft.NET\DirectX for Managed Code\1.0.2902.0 for August 2005 DLLs.
I found some xml files in there but there was no directory "DirectX for Managed Code". I installed DirectX9SDK full installation but could not find this dll to add to reference.Can anyone help me?
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
![]() |
|
|
I could not get the reference you made Microsoft.directx.dll and Micrososft.Directx.DirectDraw.dll. How can I get it??? I searched all dll in the system but was unable to get the same. Even if , I installed the latest version of Directx SDk but the problem is still the same . Iam unable to get those dlls. If some body can help then plz. regards sajjad
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
![]() |
|
|
Anonymous wrote: Browse to %SystemRoot%\Microsoft.NET\DirectX for Managed Code\1.0.2902.0 for August 2005 DLLs.
I found some xml files in there but there was no directory "DirectX for Managed Code". I installed DirectX9SDK full installation but could not find this dll to add to reference.Can anyone help me?
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
Hi there!![]()
I took a look around your problem and fixed it! Microsoft has made a directory named assembly in windows directory and made it inaccessibly to users! All assemblies you need are there! But what to do about it? Just make a project in C# in Windows Console mode and remove everything in the Program.cs and copy and past this code I made, do the things I wrote in code comments first and them run the project and enjoy hacking inaccessible assemblies of windows! ![]()
using System; using System.Collections.Generic; using System.Text; using System.IO;
namespace AssemblyHack { class Program { static void Main(string[] args) { //Change this string to any path were your windows directory is placed! string assemblyPath = "C:\\WINDOWS\\assembly\\"; //First create some directory and then change this string to the directory path you created! string hackResult = "C:\\Hacked assembly\\"; //Now just run the project and enjoy the hack! Sojaner! Copy(assemblyPath, hackResult); }
static void Copy(string rootPath, string rootDes) { DirectoryInfo info = new DirectoryInfo(rootPath); FileInfo[] fileInfo = info.GetFiles(); for (int i = 0; i < fileInfo.Length; i++) { try { fileInfo[i].CopyTo(rootDes + "\\" + Path.GetFileName(fileInfo[i].FullName), true); } catch(Exception e) { Console.WriteLine(e.Message); } } DirectoryInfo[] dirInfo = info.GetDirectories(); for (int i = 0; i < dirInfo.Length; i++) { string tempPath; if (dirInfo[i].FullName.LastIndexOf("\\") < (dirInfo[i].FullName.Length - 1)) { tempPath = dirInfo[i].FullName.Substring(dirInfo[i].FullName.LastIndexOf("\\")); } else { int index = dirInfo[i].FullName.LastIndexOf("\\", dirInfo[i].FullName.Length - 2); tempPath = dirInfo[i].FullName.Substring(index); } string newPath = rootDes + "\\" + tempPath; Directory.CreateDirectory(newPath); try { Copy(dirInfo[i].FullName, newPath); } catch (Exception e) { Console.WriteLine(e.Message); } } } } }
Just remember that the assembly files you are looking for are those placed in subfolders named 1.0.900.0__31bf3856ad364e35 . Go and use all my hints and make sure you can make it!:-> Have fun and let me know what happened to you at last!![]() ![]()
Sojaner!
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
the directX .dll r missing in my project but they r present in the article project...wat is the reason plz.......
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
![]() |
|
|
Hi there!
I took a look around your problem and fixed it! Microsoft has made a directory named assembly in windows directory and made it inaccessibly to users! All assemblies you need are there! But what to do about it? Just make a project in C# in Windows Console mode and remove everything in the Program.cs and copy and past this code I made, do the things I wrote in code comments first and them run the project and enjoy hacking inaccessible assemblies of windows!
using System; using System.Collections.Generic; using System.Text; using System.IO;
namespace AssemblyHack { class Program { static void Main(string[] args) { //Change this string to any path were your windows directory is placed! string assemblyPath = "C:\\WINDOWS\\assembly\\"; //First create some directory and then change this string to the directory path you created! string hackResult = "C:\\Hacked assembly\\"; //Now just run the project and enjoy the hack! Sojaner! Copy(assemblyPath, hackResult); }
static void Copy(string rootPath, string rootDes) { DirectoryInfo info = new DirectoryInfo(rootPath); FileInfo[] fileInfo = info.GetFiles(); for (int i = 0; i < fileInfo.Length; i++) { try { fileInfo[i].CopyTo(rootDes + "\\" + Path.GetFileName(fileInfo[i].FullName), true); } catch(Exception e) { Console.WriteLine(e.Message); } } DirectoryInfo[] dirInfo = info.GetDirectories(); for (int i = 0; i < dirInfo.Length; i++) { string tempPath; if (dirInfo[i].FullName.LastIndexOf("\\") < (dirInfo[i].FullName.Length - 1)) { tempPath = dirInfo[i].FullName.Substring(dirInfo[i].FullName.LastIndexOf("\\")); } else { int index = dirInfo[i].FullName.LastIndexOf("\\", dirInfo[i].FullName.Length - 2); tempPath = dirInfo[i].FullName.Substring(index); } string newPath = rootDes + "\\" + tempPath; Directory.CreateDirectory(newPath); try { Copy(dirInfo[i].FullName, newPath); } catch (Exception e) { Console.WriteLine(e.Message); } } } } }
Just remember that the assembly files you are looking for are those placed in subfolders named 1.0.900.0__31bf3856ad364e35 .:-> Go and use all my hints and make sure you can make it! Have fun and let me know what happened to you at last!
Sojaner!![]() ![]()
Sojaner!
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
I am trying to make a simple animation program. I have 3 surfaces, the front one, the back surface and a surface with a picture of a man who is surrounded by a gray area, I want this gray to be transparent. I am trying use the ColorKey to make it so. ColorKey ck=new ColorKey(); ck.ColorSpaceHighValue=10066329; //the gray color ck.ColorSpaceLowValue=10066329; man=new Surface("image8.bmp",description,display); man.SetColorKey(ColorKeyFlags.SourceDraw,ck);
then I draw it like that: back.ColorFill(Color.Blue); back.DrawFast(20+x*30, 20, man, frames[frame], DrawFastFlags.SourceColorKey | DrawFastFlags.Wait); front.Flip(back,FlipFlags.Wait); it looks ok except for the fact that the Gray area still exists. I tried to change the ck.ColorSpaceHighValue and ck.ColorSpaceLowValue to other numbers but it doesn't seem to do any difference. Please help me. Yours Michael.
Expand AllCollapse All
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
Microsoft.DirectX.DirectDraw.PixelFormat _pf = _primarySurface.PixelFormat; ColorKey _ck = new ColorKey(); _ck.ColorSpaceHighValue = _pf.RBitMask; _ck.ColorSpaceLowValue = _pf.RBitMask; _temp.SetColorKey(ColorKeyFlags.SourceDraw, _ck);
first; i can't speak eng. very well. (i'm from Turkiye)
when i used this code for creating surfaces, it is work.
RBitMask's means is, set transparent in the bitmap image all Red(FF0000) bits. u can use BBitMask for blue, GBitMask for green.
(_temp is any offscreenplain surface)
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
hi,Mishan Pog: throught your idea,I still make message transparency.so i need your help.could help me? my code under here.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Configuration; using System.Collections; using Microsoft.DirectX.DirectDraw; using System.IO;
namespace KTV { public partial class Main : Form { // The DirectDraw Device, used in all the application private Device display; // The Front Surface private Surface front = null; // The Back Surface private Surface back = null; // Surface to store the title screen private Surface title = null; // Surface to store the text private Surface text = null; // The Clipper private Clipper clip = null; string titlescreen = Application.StartupPath + "\\skin\\default\\main.jpg";
public static byte Banlance = 0; public Main() { InitializeComponent(); InitializeGraphics(); this.Cursor.Dispose(); this.Show(); while (Created) { Draw(); Application.DoEvents(); } }
public static List Songs = new List();
public static int CurrentIndex = 1; public void InitializeGraphics() { // Used to describe a Surface SurfaceDescription description = new SurfaceDescription(); // Init the Device display = new Device(); //#if DEBUG //display.SetCooperativeLevel(this, CooperativeLevelFlags.FullscreenExclusive); //#else // Set the Cooperative Level and parent, //Setted to Full Screen Exclusive to the form) display.SetCooperativeLevel(this,CooperativeLevelFlags.FullscreenExclusive); // Set the resolution and color depth //used in full screen(640x480, 16 bit color) display.SetDisplayMode(800, 600, 16, 0, false); //#endif // Define the attributes for the front Surface description.SurfaceCaps.PrimarySurface = true;
#if DEBUG front = new Surface(description, display); #else description.SurfaceCaps.Flip = true; description.SurfaceCaps.Complex = true;
// Set the Back Buffer count description.BackBufferCount = 1; desc. // Create the Surface with specifed description and device) front = new Surface(description, display); #endif description.Clear(); #if DEBUG description.Width = front.SurfaceDescription.Width; description.Height = front.SurfaceDescription.Height; description.SurfaceCaps.OffScreenPlain = true; back = new Surface(description, display); #else // A Caps is a set of attributes used by most of DirectX components SurfaceCaps caps = new SurfaceCaps(); // Yes, we are using a back buffer caps.BackBuffer = true; // Associate the front buffer to back buffer with specified caps back = front.GetAttachedSurface(caps); #endif // Create the Clipper clip = new Clipper(display); /// Set the region to this form clip.Window = this; // Set the clipper for the front Surface front.Clipper = clip; // Reset the description description.Clear(); // Create the title screen //title = new Surface(titlescreen, description, display); Bitmap bitmap = new Bitmap(Image.FromFile(titlescreen)); title = new Surface(bitmap, description, display); description.Clear(); // Set the height and width of the text. description.Width = 600; description.Height = 16; // OffScreenPlain means that this Surface //is not a front, back, alpha Surface. description.SurfaceCaps.OffScreenPlain = true; // Create the text Surface text = new Surface(description, display); // Set the fore color of the text //text.ForeColor = Color.Black; // Set the backgroup color text.FillColor = Color.Transparent; //text.ColorFill(Color.Transparent); // Draw the Text to the Surface to coords (0,0) ColorKey ck = new ColorKey(); ck.ColorSpaceLowValue = 255; ck.ColorSpaceHighValue = 255; title.SetColorKey(ColorKeyFlags.SourceDraw, ck); text.DrawText(0, 0,"This is some message",false); }
private void Draw() { // If the front isn't create, ignore this function if (front == null) { return; }
// If the form is minimized, ignore this function if (this.WindowState == FormWindowState.Minimized) { return; } try { // Draw the title to the back buffer using source copy blit back.DrawFast(0, 0, title, DrawFastFlags.Wait);
// Draw the text also to the back buffer using source copy blit back.DrawFast(10, 10, text, DrawFastFlags.Wait); #if DEBUG // Draw all this to the front front.Draw(back, DrawFlags.Wait); #else // Doing a flip to transfer back buffer to the front, faster front.Flip(back, FlipFlags.Wait); #endif }
catch (WasStillDrawingException) { return; } catch (SurfaceLostException) { // If we lost the surfaces, restore the surfaces RestoreSurfaces(); } }
private void RestoreSurfaces() { // Used to describe a Surface SurfaceDescription description = new SurfaceDescription();
// Restore al the surface associed with the device display.RestoreAllSurfaces(); // Redraw the text //text.ColorFill(Color.Black); // text.DrawText(0, 0, "I Love you",true);
// For the title screen, we need to //dispose it first and then re-create it title.Dispose(); title = null; title = new Surface(titlescreen, description, display); return; }
} }
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
I wrote the same program like on your page and everything works fine until I try to load a bitmap file into a surface... private Surface Picture=null; description.SurfaceCaps.OffScreenPlain=true; Picture=new Surface("america.bmp",description,display); now when I use : backSurface.DrawFast(1,1,Picture,DrawFastFlags.DoNotWait); it does not work and throws an unkown exception but when I use : backSurface.Draw(Picture,DrawFlags.DoNotWait); instead it works ok.. I can't use drawFast at all, what might be the problem? Thanks in advance!
|
| Sign In·View Thread·PermaLink | 3.00/5 (2 votes) |
|
|
|
![]() |
|
|
it's wrong! replace it with something like
protected override void OnPaint(PaintEventArgs e) { base.OnPaint (e);
Draw(); }
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
![]() |
|
|
I copied the code above... added a reference to the Microsoft.Directx and Microsoft.Directx.directDraw.. it passed the compilation.. but it does not work when I run it, instead it runs the debugged... and when I run it through the debugger it stops on the line: description.SurfaceCaps.PrimarySurface = true; and says: An unhandled exception of type 'System.ArgumentException' occurred in microsoft.directx.directdraw.dll
Additional information: Value does not fall within the expected range.
I face the same problem by the way when I try to use the directsound, and direct3d, as I see it I cannot create a device instance.. but I can't understand why. I've updated both the sdk and the VS... please help.. Thanks in advance. Michael
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
![]() |
|
|
I ran into the same problem, you are using VS 2002 which supports only .NET 1.0 not .NET 1.1 and directX9 requires .NET 1.1. The only way to fix this is to go out and buy Microshafts Visual Studio 2003.
|
| Sign In·View Thread·PermaLink | |
|
|
|
![]() |
|
|
General News Question Answer Joke Admin
|