Direct Draw 7
by
Peter Kuchnio
11/03/00
introduction
This
is a revamped DirectDraw
tutorial, this time using DirectX 7. As many of you probably know, DirectX
7 has added official support for DirectX in Visual Basic. Before we had
to make do with Patrice Scribe's 3rd party tlbs. Before you start, you
might want to download the DirectX 7 SDK from MicroSoft's site.
The
SDK is not necessary but it will help you with the really specific functions.
Anyway, for this tutorial all you will need is DirectX 7 installed.
What
exactly is DirectDraw? It's a part of the DirectX API. It deals with your
2D video card. In other words it talks directly with the hardware which
is faster than GDI which has to deal with the system first. Plus GDI can't
take advantage of any specific hardware extras that come with your video
card. The thing is, you don't have to program any hardware specific instructions.
DirectDraw
deals with the video card through drivers that the card manufacterer has
produced, usually with help from Microsoft. DirectDraw uses the HAL and
the HEL (hardware emulation layer). First it tries to use the HAL, but
if the call or feature is not supported by the hardware it uses the HEL,
in which case it does the task through software.
What
is explained in this tutorial? First off, starting an Exclusive Fullscreen
mode DirectDraw session. Then using two surfaces to do some animation,
and of course using color-keying.
the
code
Before
you start, make sure that you have the DirectX 7 type-library checked under
Projects...References.
The
first part of starting DirectDraw is to declare the main DirectX and DirectDraw
objects. You should remember that the DirectX object has to be declared
with a New.
'Main
DirectX object
Dim
Dx As New DirectX7
'Maub
DirectDraw object
Dim
DDraw As DirectDraw7
Here
we declare our surfaces. Nothing too complicated so far!
'Surfaces
'Primary
surface
Dim
ddsPrimary As DirectDrawSurface7
'Backbuffer
Dim
ddsBackBuffer As DirectDrawSurface7
'Background
Dim
Background As DirectDrawSurface7
Dim
s640x480rect As RECT 'RECT variable
'Sprite
Dim
Sprite As DirectDrawSurface7
Dim
SpriteRECT As RECT 'Sprite's RECT variable
The
first two were our Primary surface (ie: the screen or stuff you actually
see) and the second one is the backbuffer, which we draw to first and do
all the dirty work on. This keeps the animation smooth and flicker free.
After this we declare our background and sprite surfaces and their RECTs.
A RECT is a set of coordinates that specifies the dimensions of the surface.
Ordinarily you would have to fill this out yourself, however for this sample
we are using a subroutine that will fill out our RECT for us. This saves
a lot of time to say the least =)
Below
we have the surface descriptions for the Primary surface and the Backbuffer.
'Surface
Descriptions
Dim
ddsdPrimary As DDSURFACEDESC2
Dim
ddsdBackbuffer As DDSURFACEDESC2
Dim
running As Boolean
Private
Sub Form_Click()
'If user clicks on form end the program
running = False
End
Sub
Private
Sub Form_Load()
running = True 'the app is running
'Initializing DirectDraw
On Error Resume Next
Below
we actually create the DirectDraw object.
'Create Directdraw
Set DDraw = Dx.DirectDrawCreate("")
Form1.Show 'show the form
Here
we set the display mode for DirectDraw. We set the cooperative level to
exclusive, so our app is the only one using the graphics card. We also
set it to fullscreen mode. We then set the resolution and the BPP (Bits
Per Pixel) or Colour Depth, in this case 16-bit or true colour. This is
one of the most common graphics modes at the moment.
'Setting cooperative level and display mode
'Fullscreen exclusive mode
DDraw.SetCooperativeLevel Form1.hWnd, DDSCL_FULLSCREEN Or DDSCL_ALLOWMODEX
Or DDSCL_EXCLUSIVE
'640x480 resolution in 16-bit colour (about 16 000 colours)
'This is the most common BPP (Bits-Per-Pixel) used today.
DDraw.SetDisplayMode 640, 480, 16, 0, DDSDM_DEFAULT
Below
we fill out the surface description for the Primary surface. It isn't anything
too complex, we just assign flags that, well, describe what the surface
does. In this case we describe it as the primary surface with 1 backbuffer
and then we actually create the surface.
'Fill out Primary Surface Description
ddsdPrimary.lFlags = DDSD_CAPS Or DDSD_BACKBUFFERCOUNT
'Using Video Memory for the primary surface and backbuffer
ddsdPrimary.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Or DDSCAPS_FLIP Or DDSCAPS_COMPLEX
ddsdPrimary.lBackBufferCount = 1 'One Backbuffer
'Create the Primary Surface
Set ddsPrimary = DDraw.CreateSurface(ddsdPrimary)
Then
we fill out the surface description for the backbuffer and attach it to
the primary surface.
'Backbuffer
Dim Caps As DDSCAPS2
Caps.lCaps = DDSCAPS_BACKBUFFER
Set ddsBackBuffer = ddsPrimary.GetAttachedSurface(Caps)
'Fill out description
ddsBackBuffer.GetSurfaceDesc ddsdBackbuffer
Here
we load our sprites from the disk into surfaces we declared before. Don't
let this fool you though, this isn't a DirectX call. We call a subroutine
which loads them. You might want to keep this, since with the bmp loading
sub we actually automatically fill out the RECT variable for the surface,
as opposed to doing it by hand. This saves a LOT of time in the long run.
'Load bitmap files into surfaces
DDCreateSurface Background, App.Path & "\background.bmp", s640x480rect
DDCreateSurface Sprite, App.Path & "\sprite.bmp", SpriteRECT
Now
we actually get to the render loop. First we do a colorfill, which fills
a surface with a specified colour. This is useful to make sure there aren't
any leftover graphics on the backbuffer before we blit. Then we actually
do the blitting. First the background, and then the sprite.
The
background is blitted without any transparency. The sprite however, is,
so the black around it is not drawn. This is accomplished by adding the
DDBLTFAST_SRCCOLORKEY flag to the call. The actual assigning of the colour-key
is done in the bitmap loading subroutine. Then we flip the backbuffer onto
the primary surface and we are technically done!
'Render loop
Do
DoEvents
'Colorfill the background with flat black
ddsBackBuffer.BltColorFill s640x480rect, RGB(0, 0, 0)
'Use BltFast to draw the background (no transparency)
ddsBackBuffer.BltFast 0, 0, Background, s640x480rect, DDBLTFAST_WAIT
'Use BltFast to draw the Sprite (transparent)
ddsBackBuffer.BltFast 50, 50, Sprite, SpriteRECT, DDBLTFAST_SRCCOLORKEY
Or DDBLTFAST_WAIT
'Flip the backbuffer to the primary surface
ddsPrimary.Flip Nothing, DDFLIP_WAIT
Loop Until running = False
The
following deals with unloading DirectDraw. We have to first destroy any
surfaces we created to free up the memory, then we restore the display
mode.
'Unloading
'With DirectDraw you must unload all your surfaces etc.
'to clear up memory.
Set Background = Nothing
Set Sprite = Nothing
Set ddsPrimary = Nothing
Set ddsBackBuffer = Nothing
DDraw.RestoreDisplayMode
'Restore to normal display mode
DDraw.SetCooperativeLevel Form1.hWnd, DDSCL_NORMAL
End
End
Sub
Here is the actual sub that
performs loading a bitmap from the disk into a surface. Basically we fill
out the surface's description, with the added feature of keeping the surfaces
in video memory or system memory.
Private
Sub DDCreateSurface(surface As DirectDrawSurface7, BmpPath As String, RECTvar
As RECT, Optional TransCol As Integer = 0, Optional UseSystemMemory As
Boolean = True)
'This sub will load a bitmap from a file
'into a specified dd surface. Transparent
'colour is black (0) by default.
Dim tempddsd As DDSURFACEDESC2
Set surface = Nothing
'Load sprite
tempddsd.lFlags = DDSD_CAPS
If UseSystemMemory = True Then
tempddsd.ddsCaps.lCaps = DDSCAPS_SYSTEMMEMORY Or DDSCAPS_OFFSCREENPLAIN
Else
tempddsd.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
End If
Set surface = DDraw.CreateSurfaceFromFile(BmpPath, tempddsd)
'set the RECT dimensions
RECTvar.Right = tempddsd.lWidth
RECTvar.Bottom = tempddsd.lHeight
'Colour key
Dim ddckColourKey As DDCOLORKEY
ddckColourKey.low = TransCol
ddckColourKey.high = TransCol
surface.SetColorKey DDCKEY_SRCBLT, ddckColourKey
End
Sub
That's pretty much it for
this DirectDraw tutorial. Feel free to download
the source. If you're still having trouble with DirectDraw you can
email me or talk about it on our forum!
Peter
|