Drawing Splash Screens


In the first chapter, I mentioned presenting the player with splash screens that credit the developer of the game and serve as an opening for the game. In a more advanced game or a commercial game, either or both of these could be a static image or a short video. The video aspect of this was handled by the DirectShow component of DirectX in previous versions as well as in the current C++ version of DirectX. This is supported by the AudioVideo class in Managed DirectX. The video texture sample provided by Microsoft illustrates how this would be done.

Microsoft refers to a structure in memory that holds an image as either a surface or a texture depending on how the image will be used. If the image is being presented in a two-dimensional fashion on the screen, it is called a surface. If all or a portion of the image is being applied to a three-dimensional shape, it is called a texture. Our splash screens will use textures to hold the image. To make the textures easier to work with, we will wrap the textures in a new class called Image. This class, like the GameInput class discussed earlier, will inherit the IDisposable interface so that we can control when and how the class gets cleaned up. The class will hold three attributes: a string with the name of the file from which the image is loaded, an ImageInformation structure that provides information about the image, and the texture itself. The attribute definitions are shown in Listing 2 “5.

Listing 2.5: Image Class members
start example
 private Texture   m_image  = null;  private ImageInformation m_info   = new ImageInformation();  private string    m_sFilename; 
end example
 

The constructor for the class has one argument, the filename of the image file. The file can be in a number of formats including bitmap (.bmp), JPEG compressed (.jpg), and DirectDraw Surface (.dds). The third format takes a bit more work to set up, but includes alpha channel information for transparency. For now I recommend using JPEG because files in this format are easy to manipulate in most imaging software and are much smaller. The constructor saves a copy of the filename and calls another method, Load , to actually load the image from the file onto the surface. We separate the loading into another method because we may need to reload the image later. The Load method, shown in Listing 2 “6, does the majority of the work for this class.

Listing 2.6: Image Load Method
start example
 public void Load()  {     try     {        m_info = new ImageInformation();        m_info = TextureLoader.ImageInformationFromFile(m_sFilename);        m_image = TextureLoader.FromFile(CGameEngine.Device3D ,m_sFilename);     }     catch (DirectXException d3de)     {        Console.AddLine("Unable to load image" + m_sFilename);        Console.AddLine(d3de.ErrorString);     }     catch ( Exception e )     {        Console.AddLine("Unable to load image" + m_sFilename);        Console.AddLine(e.Message);     }  } 
end example
 

The first thing that you will notice is that everything is wrapped within a Try/Catch block. Since there are several ways that this function can fail, it is important to catch the exceptions. The file that we are trying to load might not be there to load or it may not be possible to create the texture due to low memory conditions. Our solution to the errors at this point is to just display an error message on the console. I will describe the console in much greater detail later in this chapter in the Developing the Console section.

The first thing the Load method does is to create and load an ImageInformation structure for the file. This will give us the size of the image so that we can create a texture that is the proper size to hold the image. The next step is to create the surface for the image. The TextureLoader class has a method, FromFile , that is used for this purpose.

If everything has worked as expected, we now have our image in a texture ready to be rendered to the screen. This class does not handle the rendering itself. Instead, it has two methods that expose the texture and its size as both a Size and a Rectangle structure. This empowers any class that has instantiations of the Image class to render the image as it sees fit.

Now that we have a class to hold our image, we are ready to build a splash screen. The SplashScreen class will provide the required functionality. Like every other class we have built, it too will inherit from IDisposable . The Dispose method in this class simply calls the Dispose method for the image it will load. The constructor for the splash screen will need two arguments: the name of the image file to display and the number of seconds that the splash screen should be displayed. The filename is passed to the image s constructor to create the splash screen image. The duration in seconds is added to the current system time in seconds to set the ending time for the splash screen. A vertex buffer is also created to hold the points used to draw the image to the screen. This much of the SplashScreen class is shown in Listing 2 “7.

Listing 2.7: SplashScreen Declaration and Constructor
start example
 public class SplashScreen : IDisposable  {     private Image image = null;     private float m_StartTime;     private float m_EndTime = 0.0f;     private VertexBuffer m_vb;     public bool m_bInitialized = false;     public float fTimeLeft;     public SplashScreen( string filename, int nDuration)     {        image = new Image( filename );        m_StartTime = DXUtil.Timer( TIMER.GETABSOLUTETIME );        m_EndTime = m_StartTime + nDuration;        m_ vb = new VertexBuffer( typeof(CustomVertex.TransformedTextured), 4,           CGameEngine.Device3D, Usage.WriteOnly,           CustomVertex.TransformedTextured.Format,           Pool.Default );     } 
end example
 

The other major method in this class is the Render method. This is where the splash screen actually gets drawn on the system s screen for the player to see. The method returns false if the splash screen has not timed out yet and true if it has. The first step in rendering the splash screen is to create an array of transformed vertices at the four corners of the screen. Each vertex will include the texture coordinate information for placing the texture on the screen. Once the data structure has been populated , the data is copied into the vertex buffer.

Note

The vertex buffer typically resides in the video card s memory to improve rendering speed.

Once the vertex data is in the buffer, we need to set up the rendering device to draw the image to the screen. The first step is to capture the current fog state and then turn off fogging. We don t want the fogging to affect the splash screen. We then set our vertex buffer as the current stream source and let the device know the format of the data within the stream. We also need to set the current texture to the one held within the splash screen image. The actual rendering takes place when we command the device to render a strip of two triangles to the screen using the data in the vertex buffer.

After rendering, the only thing left to do is to check the time to see if the splash screen has timed out. The code for all of this appears in Listing 2 “8.

Listing 2.8: SplashScreen Render Method
start example
 public bool Render()  {     try     {        bool fog_state = CgameEngine.Device3D.RenderState.FogEnable;        CgameEngine.Device3D.RenderState.FogEnable = false;        CustomVertex.TransformedTextured[] data =           new CustomVertex.TransformedTextured[4];        data[0].X =    0.0f;        data[0].Y =    0.0f;        data[0].Z =    0.0f;        data[0].Tu =   0.0f;        data[0].Tv =   0.0f;        data[1].X =  CGameEngine.Device3D.Viewport.Width;        data[1].Y =    0.0f;        data[1].Z =    0.0f;        data[1].Tu =   1.0f;        data[1].Tv =   0.0f;        data[2].X =    0.0f;        data[2].Y =  CGameEngine.Device3D.Viewport.Height;        data[2].Z =    0.0f;        data[2].Tu =   0.0f;        data[2].Tv =   1.0f;        data[3].X =  CGameEngine.Device3D.Viewport.Width;        data[3].Y =  CGameEngine.Device3D.Viewport.Height;        data[3].Z =    0.0f;        data[3].Tu =   1.0f;        data[3].Tv =   1.0f;        m_vb.SetData(data, 0, 0);        CGameEngine.Device3D.SetStreamSource( 0, m_vb, 0 );        CGameEngine.Device3D.VertexFormat =            CustomVertex.TransformedTextured.Format;        // Set the texture.        CGameEngine.Device3D.SetTexture(0, image.GetTexture() );        // Render the face.        CGameEngine.Device3D.DrawPrimitive( PrimitiveType.TriangleStrip, 0, 2 );        CgameEngine.Device3D.RenderState.FogEnable = fog_state;     }     catch (DirectXException d3de)     {        Console.AddLine( "Unable to display SplashScreen" );        Console.AddLine( d3de.ErrorString );     }     catch ( Exception e )     {        Console.AddLine( "Unable to display SplashScreen" );        Console.AddLine( e.Message );     }     // Check for timeout.     float fCurrentTime = DXUtil.Timer( TIMER.GETABSOLUTETIME );     return ( fCurrentTime > m_EndTime );  } 
end example
 



Introduction to 3D Game Engine Design Using DirectX 9 and C#
Introduction to 3D Game Engine Design Using DirectX 9 and C#
ISBN: 1590590813
EAN: 2147483647
Year: 2005
Pages: 98

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net