|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThis is the framework of a Managed DirectX render loop. These loops are used to cause a game or simulation to render graphics and update state with the highest possible performance while still being responsive to user input and system events, without bogging down the entire system. This article does not explain how to use DirectX or Direct3D, only how to best arrange the main engine loop of your game or simulation for the best performance and responsiveness. BackgroundThis implementation comes directly from Tom Miller's blog entry on May 05, 2005. Tom Miller is a well known author and the lead developer on the Managed DirectX team at Microsoft. After many iterations, he has discovered that this pattern will provide the best possible performance that a .NET managed application can attain without resorting to WinAPI tricks. A more complete framework is included in the June '05 version of the DirectX SDK, but I'm going to show you the simplest possible implementation and explain why/how it works and why it is the best. Using C++ and avoiding the .NET WinForms base classes can be even faster, but there are many published techniques already available. The purpose here is to create a 100% managed solution using only .NET code. Using the codeI'm going to analyze the whole class by looking at snippets at a time. The downloadable source includes a complete When the application starts up, while still in the [STAThread]
public static void Main(){
MainForm myForm = new MainForm();
Application.Idle += new EventHandler(myForm.Application_Idle);
Application.Run(myForm);
}
If you are unfamiliar with Windows messages, they are simple notifications of events like key-presses and mouse movements, but can also cover things like system shutdown, minimizing your application, etc. Almost everything that happens within your computer ends up as a Windows message. The Here is our protected void Application_Idle(object sender, EventArgs e){
while(AppStillIdle){
// TODO: Main game loop goes here.
}
}
public bool AppStillIdle{
get{
PeekMsg msg;
return !PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
}
}
The According to the Win32 API documentation, [StructLayout(LayoutKind.Sequential)]
public struct PeekMsg {
public IntPtr hWnd;
public Message msg;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public System.Drawing.Point p;
}
The Here's the native method definition for [DllImport("User32.dll", CharSet=CharSet.Auto)]
private static extern bool PeekMessage(out PeekMsg msg, IntPtr hWnd,
uint messageFilterMin, uint messageFilterMax, uint flags);
Making it FasterThere are a few enhancements we can make to this application. Some of them aren't hard to do, but the reasons for them aren't very clear. The first, is setting the this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
These lines cause the form to not use the standard .NET and Windows form-drawing code, as well as bypass extra drawing-related messages and events. Obviously if we are going to be using DirectX to draw our game or simulation, we don't need Windows and GDI+ to be doing a whole bunch for us that will never be visible. This is the case for Full-Screen as well as Windowed games and simulations. Another thing we can do is to modify our native method definition for [System.Security.SuppressUnmanagedCodeSecurity]
[DllImport("User32.dll", CharSet=CharSet.Auto)]
private static extern bool PeekMessage(out PeekMsg msg, IntPtr hWnd,
uint messageFilterMin, uint messageFilterMax, uint flags);
By adding the Points of InterestDid you notice that we did nothing at all with the History
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||