|
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
|