DirectX 7 Tutorials

 

        This is my DirectX 7 Tutorial written for CSC 455 - Structures of Programming Languages.  This tutorial covers various aspects of

        DirectX including:  DirectDraw and DirectSound.  First up, DirectDraw...

 

DirectDraw Tutorial

 

        Definition:  DirectDraw provides a way for software developers to access the display's attributes - including the size of the desktop and how

        many colors can be displayed at once - and the display's features, such as playing back video, displaying images and bitmaps, and so on.

        DirectDraw is not a graphics library, in that it cannot draw lines, polygons, or text, but it is still nonetheless invaluable for all of today's 3D

        games.

 

        Under DirectDraw, I will be explaining (or trying to anyways :) ) how certain features in DirectDraw work.  But first, we need to get

        some of the basics of graphics down first.  There are two words that need to be explained:  Surfaces and Blitting.  A surface in

        DirectDraw is a rectangular piece of memory, located either on the video card itself or in system memory.  This memory is used to store

        graphically related data.  Blitting is the process of transferring one surface, called the source, to another, called the destination.  With that

        out of the way, we can get on to DirectDraw!!!

 

        There are two ways to run DirectDraw in any program, Full Screen Mode or Windowed Mode.  Let's take a look at Full Screen Mode first:

        Full Screen Mode:

                This would be some sample code in Visual Basic 6.0 for a Full Screen Mode application:

             

Option Explicit 'DirectX likes all it's variables to be predefined

Dim binit As Boolean 'A simple flag (true/false) that states whether we've initialised or not. If the initialisation is successful this changes to true, the program also checks before doing any drawing if this flag is true. If the initialisation failed and we try and draw things we'll get lots of errors...

Dim dx As New DirectX7 'This is the root object. DirectDraw is created from this
Dim dd As DirectDraw7 'This is DirectDraw, all things DirectDraw come from here
Dim Mainsurf As DirectDrawSurface7 'This holds our bitmap
Dim primary As DirectDrawSurface7 'This surface represents the screen - see earlier in the tutorial
Dim backbuffer As DirectDrawSurface7 'This was mentioned earlier on...
Dim ddsd1 As DDSURFACEDESC2 'this describes the primary surface
Dim ddsd2 As DDSURFACEDESC2 'this describes the bitmap that we load
Dim ddsd3 As DDSURFACEDESC2 'this describes the size of the screen

Dim brunning As Boolean
'this is another flag that states whether or not the main game loop is running.
Dim CurModeActiveStatus As Boolean 'This checks that we still have the correct display mode
Dim bRestore As Boolean 'If we don't have the correct display mode then this flag states that we need to restore the display mode

Sub Init()
On Local Error GoTo errOut
'If there is an error we end the program.

Set dd = dx.DirectDrawCreate("")
'the ("") means that we want the default driver
Me.Show
'maximises the form and makes sure it's visible


'The first line links the DirectDraw object to our form, It also sets the parameters
'that are to be used - the important ones being DDSCL_FULLSCREEN and DDCSL_EXCLUSIVE. Making it
'exclusive is important, it means that while our application is running nothing else can
'use DirectDraw, and it makes windows give us more time/attention

Call dd.SetCooperativeLevel(Me.hWnd, DDSCL_FULLSCREEN Or DDSCL_ALLOWMODEX Or DDSCL_EXCLUSIVE)
'This is where we actually see a change. It states that we want a display mode
'of 640x480 with 16 bit colour (65526 colours). the fourth argument ("0") is the
'refresh rate. leave this to 0 and DirectX will sort out the best refresh rate. It is advised
'that you don't mess about with this variable. the fifth variable is only used when you
'want to use the more advanced resolutions (usually the lower, older ones)...

Call dd.SetDisplayMode(640, 480, 16, 0, DDSDM_DEFAULT)


'get the screen surface and create a back buffer too
ddsd1.lFlags = DDSD_CAPS Or DDSD_BACKBUFFERCOUNT
ddsd1.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Or DDSCAPS_FLIP Or DDSCAPS_COMPLEX
ddsd1.lBackBufferCount = 1
Set primary = dd.CreateSurface(ddsd1)

'Get the backbuffer
Dim caps As DDSCAPS2
caps.lCaps = DDSCAPS_BACKBUFFER
Set backbuffer = primary.GetAttachedSurface(caps)
backbuffer.GetSurfaceDesc ddsd3


' init the surfaces
InitSurfaces

'This is the main loop. It only runs whilst brunning=true
binit = True
brunning = True
Do While brunning
blt
DoEvents
'you MUST have a doevents in the loop, otherwise you'll overflow the
'system (which is bad). All your application does is keep sending messages to DirectX
'and windows, if you dont give them time to complete the operation they'll crash.
'adding doevents allows windows to finish doing things that its doing.

Loop


errOut:
'If there is an error we want to close the program down straight away.
EndIt
End Sub

Sub InitSurfaces()
'This procedure may look small, but when you make a program this procedure could
'take a good 60-120 seconds to process, and run into 1000's of lines of code.


Set Mainsurf = Nothing
'Although the first time we call this procedure this
'variable will be empty, it must be cleared. As you'll see in the blt procedure
'the program may try and re-load the surfaces, at which point the "mainsurf" object
'will have some information in it. If we try and recreate a surface that already has
'information in it DirectDraw will crash, because of this we must clear the buffer first.



'load the bitmap into a surface - backdrop.bmp
ddsd2.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH
'default flags
ddsd2.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
'An offscreenplain means that
'the user never actually gets to see the surface - it is just an are in memory.

ddsd2.lWidth = ddsd3.lWidth
'the ddsd3 structure already holds the size
'of the screen. We could replace it with 640 and 480 - it would have the same effect

ddsd2.lHeight = ddsd3.lHeight
'this is where the surface is created. You use the DDraw object to create a
'surface from the specified file name using the above description.

Set Mainsurf = dd.CreateSurfaceFromFile(App.Path & "\backdrop.bmp", ddsd2)

End Sub

Sub blt()
'again, this procedure looks fairly simple - it is!
'You should try and keep this procedure as short as possible, and as fast as possible


On Local Error GoTo errOut
'If there is an error don't do anything - just skip
'the procedure

If binit = False Then Exit Sub
'If we haven't initiaised then don't try anything
'DirectDraw related.


Dim ddrval As Long
'Every drawing procedure returns a value, so we must have a
'variable to hold it. From this value we can check for errors.


Dim rBack As RECT
'a RECT is the rectangle that i've mentioned.



' this will keep us from trying to blt in case we lose the surfaces (alt-tab)
bRestore = False
Do Until ExModeActive
DoEvents
bRestore = True
Loop

' if we lost and got back the surfaces, then restore them
DoEvents
If bRestore Then
bRestore = False
dd.RestoreAllSurfaces
'this just re-allocates memory back to us. we must
'still reload all the surfaces.

InitSurfaces
' must init the surfaces again if they we're lost
End If


'get the area of the screen where our window is
'this sets the rectangle to be the size of the screen.

rBack.Bottom = ddsd3.lHeight
rBack.Right = ddsd3.lWidth

'blt to the backbuffer from our surface to
'the screen surface such that our bitmap
'appears over the window
'This Blits to the screen starting from 0,0 on the screen. the DDBLTFAST_WAIT
'flag tells Directdraw to wait if the blitter is busy at the time of the call.

ddrval = backbuffer.BltFast(0, 0, Mainsurf, rBack, DDBLTFAST_WAIT)
'Flip the back buffer to the screen
primary.Flip Nothing, DDFLIP_WAIT
errOut:
                                                                                                                                                                                                         'Please please please please don't put any message box in here!!!  This is running around 100 frames per second meaning that windows will           'try to open 100 message boxes per second!!!
End Sub

Sub EndIt()
     Call dd.RestoreDisplayMode
     'We have become good and no longer want exclusive access.  Awwwww...  But why can't I be evil?
     Call dd.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL)
     End
End Sub

Private Sub Form_Click()
     EndIt
End Sub

Private Sub Form_Load()
     Init
End Sub

Private Sub Form_Paint()
'If windows wants to paint then change that command to a DirectDraw command:
     blt
End Sub

Function ExModeActive() As Boolean
'This functions responds to the question:  Are we in the right resolution???
     Dim TestCoopRes As Long
     TestCoopRes = dd.TestCooperativeLevel
     If (TestCoopRes = DD_OK) Then
          ExModeActive = True
     Else
          ExModeActive = False
     End If
End Function

 

        There are five main things we are doing here.  Defining the variable of DirectX and DirectDraw.  Initializing DirectDraw.

         Initializing the surfaces or bitmaps.  Drawing those surfaces to the screen using DirectDraw functions.  And finally, adding

         finishing touches so that it runs a little faster and smoother.  Windowed mode is a bit more intricate, because we must

         keep track of the window size and if the picture should stretch or not and a few other variables.  Windowed mode will not

         be shown here.  If you like the above tutorial then look for others from Jack Hoxley who I give a big thanks to in helping

         me learn DirectDraw with his tutorials.  His website is www.cse.unsw.edu.au/~atan164/ddraw_print.html

 

         Many other things can be done with DirectDraw including finding out what device the computer using your application is using to display

         its video, drawing primitave pictures, and even using basic animation.  Unfortunately, DirectDraw does not get into the 3D aspects of

         game programming, however, Direct3D does.  Although, I did not have enough time to learn any Direct3D, I enjoyed my DirectDraw

         experience in Visual Basic very much and plan on learing DirectX thoroughly in the future.

 

DirectSound Tutorial

 

        Definition:  DirectSound can play, mix, and apply effects to sounds on a variety of hardware devices.  Many programmers rely on

        DirectSound for all of their sound output.

       

        The only thing I managed to get out of DirectSound is how to output a wav file.  Fortunately, this is fairly easy:

Set DS = DX.DirectSoundCreate("")

'Checking for Errors:

If Err.Number <> 0 Then
     MsgBox "Unable to Continue, Error creating Directsound object."
     Exit Sub
End If

'The Cooperative Level is set at Normal for now.  That means that the sound is shared between this application and 'other applications currently running.  If it were at exclusive only, then we would have all the sound for us because  'we are evil!!!  Hee hee hee...
Ds.SetCooperativeLevel Form1.hWnd, DSSCL_NORMAL

DsDesc.lFlags = DSBCAPS_CTRLFREQUENCY Or DSBCAPS_CTRLPAN Or DSBCAPS_CTRLVOLUME Or DSBCAPS_STATIC

'The sound must be set to PCM on the following line or else we get some really nasty errors with big sharp pointy     'teeth!!!!                                                                                                                          DsWave.nFormatTag = WAVE_FORMAT_PCM
DsWave.nChannels = 2
  '1= Mono, 2 = Stereo
DsWave.lSamplesPerSec = 22050
DsWave.nBitsPerSample = 16
  '16 =16bit, 8=8bit
DsWave.nBlockAlign = DsWave.nBitsPerSample / 8 * DsWave.nChannels
DsWave.lAvgBytesPerSec = DsWave.lSamplesPerSec * DsWave.nBlockAlign
Set DsBuffer = DS.CreateSoundBufferFromFile(App.Path & "\Your wav here.wav", DsDesc, DsWave)

Sub PlaySound()
DsBuffer.Play DSBPLAY_LOOPING 'Looping = A lot, Default = Once
End Sub

Sub StopSound()
DsBuffer.Stop 'Stop the Sound
DsBuffer.SetCurrentPosition 0 'Start back at the beginning of the wav.
End Sub

       Well, that's about all there is to making a wav file play in DirectSound.  If you want to play more, just create more using the

        CreateSoundBufferFromFile function on each buffer you create and assign a different wav file everytime.  Hope you enjoy.

 

        Big thanks to Jack Hoxley for his tutorial help.  Also, I used 3D Game Programming in C++ text by John De Goes for these tutorials for

        help with some of the definitions.  Great book for referencing DirectX components, functions and aspects for C++.  Pick that one up for a

        good read on DirectX.  Hopefully, I'll have the chance to update this later and give even more info on all the rest of DirectX and its

        components.  See ya later...