Issue dated - 23rd August 2004

-


Previous Issues

CURRENT ISSUE
INDIA NEWS
SECURE SPACE
COLUMNS
TECH FORUM

THE C# COLUMN

BETWEEN THE BYTES
TECHNOLOGY
SPECIALS <NEW>
Symantec Report
Security Headquarters
JobsDB
MINDPRINTS
HMA BANKBIZ
EC SERVICES
ARCHIVES/SEARCH
IT APPOINTMENTS
Openings At Jobstreet.com
WRITE TO US
SUBSCRIBE/RENEW
CUSTOMER SERVICE
ADVERTISE
ABOUT US

 Network Sites
  IT People
  Network Magazine
  Business Traveller
  Exp. Hotelier & Caterer
  Exp. Travel & Tourism
  Exp. Pharma Pulse
  Exp. Healthcare Mgmt.
  Express Textile
 Group Sites
  ExpressIndia
  Indian Express
  Financial Express

 
Front Page > TechSpace > Story Print this Page|  Email this page

Animation using Direct Draw - II

The C# Column

(Continued from last week…)

In the last week, we were planning to see the InitializeDirectDraw( ) and CreateSurfaces( ) methods. Here they are:

private void InitializeDirectDraw( )
{
SurfaceDescription desc = new
SurfaceDescription( ) ;
desc.SurfaceCaps.PrimarySurface = true ;
desc.SurfaceCaps.Complex = true ;
desc.SurfaceCaps.Flip = true ;
desc.BackBufferCount = 1 ;
surfacePrimary = new Surface ( desc, localDevice ) ;
SurfaceCaps caps = new SurfaceCaps( ) ;
caps.BackBuffer = true ;
surfaceSecondary =
surfacePrimary.GetAttachedSurface ( caps ) ;
}

Here, firstly we have created a surface. To describe the surface we are creating we have used the SurfaceDescription class. The SurfaceCaps property of the SurfaceDescription class returns a reference to the DirectX.DirectDraw.SurfaceCaps class. We have specified that the new surface we are creating here is the primary surface by setting PrimarySurface data member to true. Setting the Complex data member to true means that we are creating more than one surface. The Flip property specifies that the new surface would be ready for flipping.

The BackBufferCount property sets the number of secondary surfaces (back buffers) attached to this primary surface. We have set this count to 1 as we want only one secondary surface. After describing the surface we have created the surfaces in the following statement:

surfacePrimary = new Surface ( desc, localDevice ) ;

The surfacePrimary is a reference to the Surface class that already stands added to the GraphicsClass class. To the constructor of the Surface class we have passed the surface description and the display device mode. This statement creates the primary surface and secondary surface. The secondary surface gets attached to the surfacePrimary reference.

Next we have obtained the reference to the secondary surface by calling the GetAttachedSurface( ) method. The GetAttachedSurface( ) method returns the surface matching to the specified capabilities. By setting the BackBuffer as true, we have specified that the GetAttachedSurface( ) should return the secondary surface attached to the surfacePrimary reference.

While the InitializeDirectDraw( ) method creates the primary and secondary surfaces, the CreateSurface( ) method creates the offscreen surface. We need to separate creation of surfaces because of one reason. While the application is running, if we shift to another application by pressing Alt + Tab, all the surfaces are destroyed. On activation, DirectDraw creates the primary and secondary surfaces but not the offscreen surface. Hence, we need to create the primary and secondary surfaces only for once. This is achieved by calling the InitializeDirectDraw( ) method only for once from the constructor. However, the CreateSurfaces( ) method is called every time to create the offscreen surface when there is need to create one.

We will load our bmp file on the offscreen surface. The image on offscreen surface is then drawn of the secondary surface and then flipped to the primary surface.

Add the following data members to the GraphicsClass class.

private Rectangle r ;
private Surface sprite ;
Now let us understand the CreateSurface( ) method.
private void CreateSurfaces( )
{SurfaceDescription desc =
new SurfaceDescription( ) ;
desc.SurfaceCaps.OffScreenPlain = true ;
sprite = new Surface (
“sprite.bmp”, desc, localDevice ) ;
PixelFormat pf = surfacePrimary.PixelFormat ;
ColorKey ck = new ColorKey( ) ;
ck.ColorSpaceHighValue = pf.RBitMask ;
ck.ColorSpaceLowValue = pf.RBitMask ;
sprite.SetColorKey (
ColorKeyFlags.SourceDraw, ck ) ;
r = new Rectangle ( 0 ,0, sprite.SurfaceDescription.Width,
sprite.SurfaceDescription.Height ) ;
}

Here, we have described the creation of an offscreen surface referred to by sprite. While creating the surface we have specified the bitmap file to be loaded and the display device mode along with the surface description. Next, we have retrieved the pixel and colour format of the primary surface using the PixelFormat property. Next few lines are for achieving transparency. Since the background of ‘sprite.bmp’ is red, we have masked the red colour bits by specifying RbitMask data member. We have stored the bounding rectangle where the image is initially displayed in r.

The bitmap file loaded in CreateSurfaces( ) is displayed on the primary surface in the RenderGraphics( ) method. This method is called from the StartLoop( ) method we have seen earlier.

public void RenderGraphics ( Point destination )
{
if ( !owner.Created )
return ;
if ( surfacePrimary == null |
surfaceSecondary == null )
return ;
try
{
surfaceSecondary.ColorFill ( Color.Black ) ;
surfaceSecondary.Draw (
r, sprite, DrawFlags.KeySource |
DrawFlags.Wait ) ;
surfacePrimary.Flip ( null, FlipFlags.Wait ) ;
r.X += 10 ;
if ( r.X >= (
800 - sprite.SurfaceDescription.Width ) )
r.X = 0 ;
}
catch ( SurfaceLostException e )
{
if ( localDevice.TestCooperativeLevel( ) == true )
{
localDevice.RestoreAllSurfaces( ) ;
CreateSurfaces( ) ;
}
}
}

As said earlier, surfaces are destroyed when the application window loose focus. On re-activation when the RenderGraphics( ) method is called, accessing the surfaces throws an exception.

Hence, we have added a try-catch block to write the code. In the try block we have filled the background with black color by calling the ColorFill( ) method.

We have then drawn the graphics from the surface referred to by sprite in the specified rectangle. The DrawFlags.KeySource flag is essential to get the transparency effect. The DrawFlags.Wait flag is to wait till the graphics is drawn. The graphics drawn on the secondary surface is flipped to the primary surface by calling the Flip( ) method.

The first parameter of the Flip( ) method is the surface that is to be flipped to. We have specified null so that flipping is done through the buffers in the order they are attached to each other. Next we have incremented the X coordinate by 10 so that the next time RenderGraphics( ) is called image would be drawn on a new position.

In the catch block firstly we have checked whether the device is valid or not. If it is then we have restored the primary and secondary surfaces by calling RestoreAllSurfaces( ) method and then called the CreateSurfaces( ) method to create the offscreen surface.

We are now finished with coding. Run the application. You will find the sprite moving on the window as shown below.

<Back to top>


© Copyright 2003: Indian Express Group (Mumbai, India). All rights reserved throughout the world. This entire site is compiled in
Mumbai by The Business Publications Division of the Indian Express Group of Newspapers.
Please contact our Webmaster for any queries on this site.