Home > Articles

Understanding the Sample Framework

This chapter is from the book

This chapter is from the book

Now that the idea is complete, the object model has enough information, and you've laid out the specification, you're almost ready to jump into what you've been waiting for: actually writing the code for the game. Normally, you would need to write a lot of "boilerplate" code before you begin this development, which would include such things as enumerating through the devices on your system and picking the most appropriate one to render your scene, as well as creating and maintaining this device. Because the DirectX SDK Summer 2004 Update now includes a robust sample framework that is designed to be used directly by your code and that handles much of this work for you, you can save yourself a lot of time and hassle by simply using that.

The examples in this book use this sample framework, so you will spend this chapter examining it.

In this chapter, you'll learn

  • How to create your project

  • How to use the sample framework to enumerate devices

Creating Your Project

NOTE

For the rest of this book, I assume that you are using Visual Studio .NET 2003 for all your development needs. If you do not want to use this environment, you can look back to Chapter 1, "Game Development and Managed Code," to see the discussion on compiling code on the command line, which allows you to use any text editor or integrated development environment (IDE) you want. All the sample code included with the CD has an accompanying Visual Studio .NET 2003 project and solution file for easy loading.

Go ahead and load up Visual Studio .NET 2003, and click the New Project button on the start page. If you do not use the start page, click the Project item under the New submenu on the File menu, or use the shortcut Ctrl+Shift+N. Choose the Windows Application item under the Visual C# Projects section. (See Figure 1.3 in Chapter 1 for a reminder of what this dialog looks like.) Name this project Blockers because that is what the name of the game will be.

Before you start looking at the code that was automatically generated, first add the code files for the sample framework into your project. Normally, I put these files into a separate folder by right-clicking on the project in the solution explorer and choosing New Folder from the Add menu. Call this folder Framework. Right-click on the newly created folder and this time choose Add Existing Item from the Add menu. Navigate to the DirectX SDK folder, and you will find the sample framework files in the Samples\Managed\Common folder. Select each of these files to add to your project.

With the sample framework added to the project now, you can get rid of the code that was automatically generated. Most of it is used to make fancy Windows Forms applications, so it's irrelevant to the code you will be writing for this game. Replace the existing code and class (named Form1) with the code in Listing 3.1.

Listing 3.1 The Empty Framework

using System;
using System.Configuration;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.Samples.DirectX.UtilityToolkit;

public class GameEngine : IDeviceCreation
{
  /// <summary>
  /// Entry point to the program. Initializes everything and goes into a 
  /// message processing loop. Idle time is used to render the scene.
  /// </summary>
  static int Main() 
  {
    using(Framework sampleFramework = new Framework())
    {
      return sampleFramework.ExitCode;
    }
  }
}

Three things should stand out from this new code. First, you'll notice that everything was removed, with the exception of the static main method, which was modified. The rest of the code was support code for the Windows Form designer. Because you won't be using that designer for this application, the code isn't relevant and can be removed. Second, this code won't compile because the two interfaces the game engine class is supposed to implement haven't been implemented yet. Third, the code doesn't actually do anything.

Before you begin fixing those last two problems, you'll need to add some references. Because you will be rendering fancy 3D graphics during this project, you probably need to add references to an assembly capable of doing this rendering. This book focuses on using the Managed DirectX assemblies to do this work, so in the Project menu, click Add Reference. It brings up a dialog much like you see in Figure 3.1.

Figure 3.1Figure 3.1 The Add Reference dialog.

If you have the Summer 2004 SDK update of DirectX 9 installed (which you should because the code in this book requires it), you notice that there might be more than one version of each of the Managed DirectX assemblies. Pick the latest version (marked with version 1.0.2902.0). For this project, you add three different assemblies to your references:

  • Microsoft.DirectX

  • Microsoft.DirectX.Direct3D

  • Microsoft.DirectX.Direct3DX

The root DirectX assembly contains the math structures that help formulate any computations needed for the rendering. The other two assemblies contain the functionality of Direct3D and D3DX, respectively. With the references added, you should look briefly at the using clause you added in Listing 3.1 to make sure that the namespaces referenced as well. This step ensures that you don't have to fully qualify your types. For example, without adding the using clause, to declare a variable for a Direct3D device, you would need to declare it as

Microsoft.DirectX.Direct3D.Device device = null;

The using clauses allow you to eliminate the majority of this typing. (No one wants to type all that stuff for every single variable you would be declaring.) Because you've already added the using clauses, you could instead declare that same device in this way:

private Device device = null;

As you can see, declaring the device in this way is much easier. You've saved yourself an immense amount of typing. With these few things out of the way, now you begin to fix the compilation errors in the application and get ready to write your first 3D game. The only interface you've currently got to implement is IDeviceCreation, which is designed to let you control the enumeration and creation of your device.

You might be thinking, "Enumerating devices? I've only got one monitor!" Although most top-of-the-line, modern graphics cards actually do support multiple monitors (multimon for short), even if you have only a single device, you still have many different modes to choose from. The format of the display can vary. (You might have even seen this variety in your desktop settings on the Windows desktop, as in 16-bit or 32-bit colors.) The width and height of the full-screen modes can have different values, and you can even control the refresh rate of the screen. All in all, there are quite a few things to account for.

To fix the compilation errors in the application, add the code in Listing 3.2.

Listing 3.2 Implementing the Interface

/// <summary>
/// Called during device initialization, this code checks the device for a
/// minimum set of capabilities and rejects those that don't pass by 
/// returning false.
/// </summary>
public bool IsDeviceAcceptable(Caps caps, Format adapterFormat,
 Format backBufferFormat, bool windowed)
{
  // Skip back buffer formats that don't support alpha blending
  if (!Manager.CheckDeviceFormat(caps.AdapterOrdinal, caps.DeviceType, 
    adapterFormat, Usage.QueryPostPixelShaderBlending, 
    ResourceType.Textures, backBufferFormat))
    return false;

  // Skip any device that doesn't support at least a single light
  if (caps.MaxActiveLights == 0)
    return false;

  return true;
}

/// <summary>
/// This callback function is called immediately before a device is created 
/// to allow the application to modify the device settings. The supplied 
/// settings parameter contains the settings that the framework has selected 
/// for the new device, and the application can make any desired changes 
/// directly to this structure. Note however that the sample framework
/// will not correct invalid device settings so care must be taken 
/// to return valid device settings; otherwise, creating the device will fail.
/// </summary>
public void ModifyDeviceSettings(DeviceSettings settings, Caps caps)
{
  // This application is designed to work on a pure device by not using 
  // any get methods, so create a pure device if supported and using HWVP.
  if ( (caps.DeviceCaps.SupportsPureDevice) && 
    ((settings.BehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0 ) )
    settings.BehaviorFlags |= CreateFlags.PureDevice;
}

Look at the first method you declared, the IsDeviceAcceptable method. While the sample framework is busy enumerating the devices on the system, it calls this method for every combination it finds. Notice how the method returns a bool value? This is your opportunity to tell the sample framework whether you consider this device acceptable for your needs. Before you look at the code in that first method, however, notice the second method that's been declared, ModifyDeviceSettings. This method is called by the sample framework immediately before the device is created, allowing you to tweak any options you want. Be careful with the options you choose because you could cause the device creation to fail.

Now, back to that first method: first take a look at the parameters that it accepts. First, it takes a type called Caps, which is short for capabilities. This structure has an amazing amount of information about the particular device that will help you decide whether this is the type of device you want to use. The next two parameters are formats that are specific to the device: one for the back buffer and the other the device's format.

NOTE

The back buffer is where the actual rendered data (the pixels) is stored before that data is sent to the video card to be processed and put onscreen. The back buffer formats determine how many colors can be displayed. Most of the formats follow a particular naming convention, each character followed by a number, such as A8R8G8B8. The component specified by the character has a number of bits equal to the number. In A8R8G8B8, the format can contain 32 bits of information for color, with 8 each for alpha, red, green, and blue. The most common components are

A Alpha

R Red

G Green

B Blue

X Unused

You can look in the DirectX SDK documentation for more information on formats.

Because it's also important to know whether this device can render to a window, that is the last parameter to this method. Although the majority of games run in full-screen mode, it can be difficult to write and debug a game running in full-screen mode. During debugging, this application renders in windowed mode rather than full-screen mode.

NOTE

Windowed mode is how most of the applications you run are opened. Many of them have a border and the control menu, the minimize and maximize buttons, and a close button in the upper-right corner. In full-screen mode, the application covers the entire screen and in most cases does not have a border. You can change the desktop resolution if the full-screen mode is using a different screen size from your currently running desktop.

You'll notice that the default behavior is to accept the device, but before it is accepted, two specific checks happen. The first check ensures that the device passed in can perform alpha blending (the user interface for the game will require this), and if it cannot, it returns false to signify that this device is not acceptable. Next, the capabilities are checked to see whether there is support for active lights. Scenes with no lighting look flat and fake, so you always want at least a single light.

There's also code that actually modifies the device before creation, and even though you won't be creating the device in this chapter, you'll want to know what this code is for. Devices can do the processing required to render vertices in various ways, by either performing the calculations in hardware, performing them in software, or doing a mixture of both. If the processing happens entirely in hardware, another mode, called a pure hardware device, allows potentially even greater performance. This code checks whether you are currently going to create a hardware processing device; if you are and the pure device is available, it switches to using that instead. The only time you cannot create a pure device (if it is available) is if you are planning to call one of the many get methods or properties on a device. Because you won't be doing that in any of the applications in this book, you're free to use this more powerful device.

There is one last thing to do before you're ready to go on. The sample framework has some unsafe code in it, so you need to update your project to handle it. See Figure 3.2.

Figure 3.2Figure 3.2 Allowing unsafe code.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020