Listing 4.5. Starting the Game
try
{
#if (!DEBUG)
// In retail mode, force the app to fullscreen mode
sampleFramework.IsOverridingFullScreen = true;
#endif
// Show the cursor and clip it when in full screen
sampleFramework.SetCursorSettings(true, true);
// Initialize the sample framework and create the desired window and
// Direct3D device for the application. Calling each of these functions
// is optional, but they allow you to set several options that control
// the behavior of the sampleFramework.
sampleFramework.Initialize( false, false, true );
sampleFramework.CreateWindow("Blockers - The Game");
sampleFramework.CreateDevice( 0, true, Framework.DefaultSizeWidth,
Framework.DefaultSizeHeight, blockersEngine);
// Pass control to the sample framework for handling the message pump and
// dispatching render calls. The sample framework will call your FrameMove
// and FrameRender callback when there is idle time between handling
// window messages.
sampleFramework.MainLoop();
}
#if(DEBUG)
catch (Exception e)
{
// In debug mode show this error (maybe - depending on settings)
sampleFramework.DisplayErrorMessage(e);
#else
catch
{
// In release mode fail silently
#endif
// Ignore any exceptions here, they would have been handled by other areas
return (sampleFramework.ExitCode == 0) ? 1 : sampleFramework.ExitCode;
// Return an error code here
}
What is going on here? The first thing to notice is that the entire code section is wrapped in a TRy/catch block, and the catch block varies depending on whether you're compiling in debug or release mode. In debug mode, any errors are displayed, and then the application exits. In release mode, all errors are ignored, and the application exits. The first thing that happens in the block is that the sample framework is told to render in full-screen mode if you are not in debug mode. This step ensures that while you're debugging, the game runs in a window, allowing easy debugging, but when it's complete, it runs in full-screen mode, as most games do.
The next call might seem a little strange, but the basic goal of the call is to determine the behavior of the cursor while in full-screen mode. The first parameter determines whether the cursor is displayed in full-screen mode, and the second determines whether the cursor should be clipped. Clipping the cursor simply ensures that the cursor cannot leave the area of the game being rendered. In a single monitor scenario, it isn't a big deal either way, but in a multimon scenario, you wouldn't want the user to move the cursor to the other monitor where you weren't rendering.
The Initialize call sets up some internal variables for the sample framework. The three parameters to the call determine whether the command line should be parsed (no), whether the default hotkeys should be handled (no again), and whether message boxes should be shown (yes). You don't want the game to parse the command line or handle the default hotkeys because they are normally reserved for samples that ship with the DirectX SDK. The CreateWindow call is relatively self-explanatory; it creates the window where the rendering occurs with the title listed as the parameter.
Finally, the CreateDevice call is created. Notice that this is where you pass in the instance of the game engine class for the IDeviceCreation interface. Before the device is created, every combination is enumerated on your system, and the IsDeviceAcceptable method that you wrote in the last chapter is called to determine whether the device is acceptable to you. After the list is created, the ModifyDevice method is called to allow you to modify any settings right before the device is created. The constructor that you use for the device creation looks like this:
public Device ( System.Int32 adapter ,
Microsoft.DirectX.Direct3D.DeviceType deviceType ,
System.IntPtr renderWindowHandle ,
Microsoft.DirectX.Direct3D.CreateFlags behaviorFlags ,
params Microsoft.DirectX.Direct3D.PresentParameters[]
presentationParameters )
The adapter parameter is the ordinal of the adapter you enumerated earlier. In the majority of cases, it is the default parameter, which is 0. The deviceType parameter can be one of the following values:
* DeviceType.Hardware A hardware device. This is by far the most common device type created. The hardware device will most likely not support every feature of the Direct3D runtime. You need to check the capabilities of the device for specific features. This option is naturally the fastest option.
* DeviceType.Reference A device using the reference rasterizer. The reference rasterizer performs all calculations for rendering in software mode. Although this device type supports every feature of Direct3D, it does so very, very slowly. You should also note that the reference rasterizer only ships with the DirectX SDK. End users will most likely not have this rasterizer installed.
* DeviceType.Software A software rendering device. It is extremely uncommon to use this option. Unless you have written a software rendering library, and you have it pluggable with Direct3D, you will not be using this device type.
Obviously, because you are dealing with graphics, you need someplace to actually show the rendered image. In this overload of the device constructor, the sample framework uses the window it has created, but you could pass in any control from the System.Windows.Forms library that comes with the .NET framework. Although it won't be used in this game, you could use any valid control, such as a picture box.
The next parameter is the behavior of the device. You might remember from the last chapter when you determined the best set of flags, including whether the device supported transforming and lighting in hardware and whether the device can be pure. You find the possible value of this parameter by combining the values in Table 4.1. |