Main

IT GUIDE

 

Source Code

My Code
Other Projects

Zipped Source Code

Unsorted Code

VB Gem

Trojan Source Code

 

HELP

VB Books

VB Commands

VB Functions

Online MSDN

Online Book

 

TIPS & TRICKS

Tips & Tricks

Tips & Tricks 2

 

TUTORIAL

Code Optimization

Code Optimization 2

Code Optimization 3

Games Tutorial

DirectX

 

 

Favorites

Me


 

AN INTRODUCTION TO DIRECTX 7.0 USING VISUAL BASIC

by Aditya Kumar Singh


 
                                                 Perhaps, all of us will enjoy playing an action game. If you are a programmer, certainly sometimes a question would have emerged in your mind how the 3D games are actually programmed. If you go for programming a 3D Game using Turbo C++ graphics library, you will certainly end up lying on a bed in the mental hospital. C++ was used to create DOS based games when MS-DOS and Windows 3.1 was gaining popularity. No 3D, No Hardware Accelerations, No special effects etc. But after the introduction of Windows 95, game programmers complained that Windows 95 was a poor platform for game development. Microsoft’s answer to the game programmer’s complaints was the DirectX graphics library. After this, game-programming industry took a crucial turn and advanced 3D games began to be developed and today one major reason why homes buy computers is for playing games.


Anyone who has ever tried using the Win32 API’s BitBlt function to develop a custom Game will tell you how slow was it. DirectX is a collection of DLLs that contains functions useful to the game programmer. Using DirectX, you do not need to detect the user’s graphics card or go for writing a graphics driver. You just write your game with DirectX libraries and DirectX takes care of everything else. DirectX allows users to access fast graphics, sound card and input functions while preventing them from having to test the capabilities of the user’s computer. If you make a game using DirectX, then DirectX tries to use the user’s graphics card to perform graphics acceleration. If the user does not have a graphics card, then DirectX does the acceleration in Software. You barely even have to think about it.


Though DirectX makes game development easier but still there is a fair amount of work programming a game. This article provides an introduction to DirectX 7.0 and also how to use DirectX from Visual Basic. 


INITIALIZING DIRECTX
Though, DirectX 8.0 and 9.0 has been released but we will use DirectX 7.0 because this article has been targeted for those who have never used DirectX and DirectX 8.0 and 9.0 are advanced and is difficult for beginners to understand. Before writing the actual code, start Visual Basic and Create a new Standard EXE project. Go to Project > References. Scroll down and select “DirectX 7.0 for Visual Basic Type Library” 
In DirectX, we draw objects on Surfaces. There are mainly two surfaces in every DirectX application - the Primary surface and the BackBuffer. The Primary surface is the main surface which is displayed on the screen. The BackBuffer is used for displaying objects on the Primary surface. We draw our objects on the BackBuffer and then Flip it. Flipping is a process in which the contents of the Primary surface is written to BackBuffer and the contents of the BackBuffer is written to the Primary surface. We again draw our next frame on the backbuffer and again flip it. This process continues until the program exits. 
Select Form1 from the project explorer and go to Code View. Now make the following declarations – 
 
Dim dx As New DirectX7
Dim dd As DirectDraw7
Dim Primary As DirectDrawSurface7
Dim BackBuffer As DirectDrawSurface7
Dim ddsdPrimary As DDSURFACEDESC2
Dim caps As DDSCAPS2
 
 The first variable dx is a instance of the DirectX7 variable itself. The second declaration dd is a instance of DirectDraw7 Class. All the drawing commands are issued through the dd object. The Third and the fourth declarations are that of the primary and the BackBuffer surfaces. DirectDraw surfaces are instances of the DirectDrawSurface7 class. The other two variables are used to create the Surfaces.  
Now define a sub procedure named init(). This procedure will be responsible for initializing the objects – 
Sub init()
Set dd = dx.DirectDrawCreate("")
Call dd.SetCooperativeLevel(Me.hWnd, DDSCL_FULLSCREEN Or DDSCL_EXCLUSIVE Or DDSCL_ALLOWREBOOT)
Call dd.SetDisplayMode(640, 480, 16, 0, DDSDM_DEFAULT)
ddsdPrimary.lFlags = DDSD_CAPS Or DDSD_BACKBUFFERCOUNT
ddsdPrimary.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Or DDSCAPS_FLIP Or DDSCAPS_COMPLEX
ddsdPrimary.lBackBufferCount = 1
Set Primary = dd.CreateSurface(ddsdPrimary)
caps.lCaps = DDSCAPS_BACKBUFFER
Set BackBuffer = Primary.GetAttachedSurface(caps)
End Sub


 In this procedure, we use the dx object and invoke the DirectDrawCreate method and pass it an empty string to indicate that we wish to use the active display driver. The value returned from this function is a DirectDraw7 object which we store in the dd variable. Using the variable dd we can set the cooperative level we wish to use. The cooperative level will tell how we will access the screen and how other programs running at the same time will be allowed to access the screen as well. To set the cooperative level, we use the SetCooperativeLevel function. The first argument to this function is the handle to the window we wish to use as our main display window. We passed “Me.hWnd” to return the handle to the current window. The second argument indicates how the window should act. We specify DDSCL_FULLSCREEN to show that our application is a full screen application ( we can use DDSCL_NORMAL if we wish to create a windowed program, however it is much slower). DDSCL_EXCLUSIVE means that our application should be the only one with access to the screen. DDSCL_ALLOWREBOOT means that we will allow the user to use “CTRL-ALT-DEL” incase something goes wrong. Next we use the SetDisplayMode function to indicate the screen resolution in which our application will run.  
Next we define the primary surface and attach a flippable back buffer to it. For this we initialize the “ddsdPrimary” object which is a instance of DDSURFACEDESC2 which stands for Direct Draw Surface Description. With this we specify how we will like the surface to behave. caps is a DirectDraw capabilities description used to attach the BackBuffer to the Primary surface. Now we set up the surface description for the Primary surfaces. The ddsdPrimary.lFlags property tells that which of the ddsdPrimary values should be considered while creating the surface. We used both DDSD_CAPS and DDSD_BACKBUFFERCOUT. Here, DDSD_CAPS causes the ddsdPrimary.ddsCaps.lCaps to be taken into account and DDSD_BACKBUFFERCOUNT causes the ddsdPrimary.lBackBufferCount to be taken into account. DDSCAPS_PRIMARYSURFACE value of ddsdPrimary.ddsCaps.lCaps tells that our surface is the primary surface. DDSCAPS_FLIP tells that it is a part of the flipping chain. DDSCAPS_COMPLEX tells that we will attach other surfaces to the Primary surface. Then we specify ddsdPrimary.lBackBufferCount variable that tells how many BackBuffers will be attached to the primary surface.

 


 Now when we have created the surface description, it is time to create the primary surface. We use the CreateSurface(ddsdPrimary) statement. This method returns a surface based on the description that we pass it as an argument. Since we’ve passed the description “ddsdPrimary”, we will get a surface just the way we described it. Now, we have the primary surface set up, we have to attach a BackBuffer to it. caps.lCaps describes the type of capabilities we could like to get from the Primary Surface. We pass caps to the primary.GetAttachedSurface method and we receive a surface that will be able to be used as the BackBuffer. Now our surfaces have been initialized and ready to be used. 


DRAWING TEXT


Now that our surfaces have been set up, we can draw on the surfaces. Now open the Form_Load event procedure. Add the following lines of Code 


Private Sub Form_Load()
 Call init
 Call clear
 Call BackBuffer.DrawBox(1, 1, 639, 479)
 Call BackBuffer.DrawText(270, 230, "Hello DirectX", False)
 Primary.Flip Nothing, DDFLIP_WAIT
End Sub


  The first line calls the init procedure, which initializes DirectX. The second line clears the Backbuffer. The Third Line is used to draw a Rectangle around the screen in the BackBuffer. The Fourth Line displays a message “Hello DirectX” in the Center of the screen in Backbuffer. The Fourth line flips the Primary surface. In this process the Contents of the BackBuffer is Copied to the Primary surface and the contents of the Primary surface is copied to the BackBuffer. You must always remember that the contents of the Primary surface will always be visible on screen. For those of you who tried to run the program will notice an error in the “call clear” statement. The clear procedure has not been defined. Here it is – 


Sub clear()
BackBuffer.SetFillColor &H0&
BackBuffer.SetForeColor &H0&
Call BackBuffer.DrawBox(0, 0, 640, 480)
BackBuffer.SetForeColor &HFFFFFF
End Sub


 This procedure clears the BackBuffer.


 ANIMATING TEXT


Now replace the code in the Form_load event procedure with the following code- 
Private Sub Form_Load()
 Call init
For i = 10 To 470
Call clear
Call BackBuffer.DrawBox(1, 1, 639, 479)
Call BackBuffer.DrawText(270, i, "Hello DirectX", False)
Primary.Flip Nothing, DDFLIP_WAIT
Next i
End Sub


 The first statement here initializes DirectDraw. Now we drop into a loop which runs from 10 to 470. The first statement inside the loop Clears the BackBuffer. The second statement Draws the “Hello DirectX” message at a position 270,I0. The third statement flips the backbuffer to the primary surface. When the loop executes the second time, the Message is displayed at 270,11. The third time the message is displayed at 270, 12 and so on. The fipping occurs so fast that the Message appears to be dropping from the top of the screen. The animation is so smooth that you will never be able to achieve such type of animation without using DirectX.  


DRAWING BITMAPS


You cannot draw Bitmaps directly on the BackBuffer. First You need to create a DirectDraw Surface. Then load the Bitmap to this Surface and then Copy it to the Backbuffer. To do this, first of all declare a DirectDraw surface to which we will load our bitmap. – 


Dim MainSprite as DirectDrawSurface7
Dim SrcRect as RECT
Dim DestRect as RECT
 Now create this Surface by adding the following code - 
Sub InitSprite()
Dim ddsdNewSprite As DDSURFACEDESC2
ddsdNewSprite.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT
ddsdNewSprite.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
ddsdNewSprite.lWidth = 640
ddsdNewSprite.lHeight = 480
Set MainSprite = dd.CreateSurfaceFromFile("Hello.bmp", ddsdNewSprite)
With SrcRect
 .Bottom = 480
 .Right = 640
 .Left = 0
 .Top = 0
 End With
 
 With DestRect
.Bottom = 480
.Right = 640
.Left = 0
.Top = 0
End With
End Sub


 We create the surface in the same way as we had created the Primary Surface. Remember to create a Bitmap image (640 X 480) namely “Hello.bmp”. We define two rectangles SrcRect and DestRect. This two rectangles will be used to Draw the Bitmap on the BackBuffer. Using these rectangles we will tell DirectX which portion of the Bitmap is to be read and where it is to be written on the BackBuffer. Now once the surface is created what you have to do is to draw it on our BackBuffer. But before that Call the InitSprite procedure so that we can load the Bitmap on the BackBuffer. Use the following code in the Form_Load event procedure –

 
Private Sub Form_Load()
Call init
 Call InitSprite
 For i = 10 To 470
Call clear
BackBuffer.Blt DestRect, MainSprite, SrcRect, DDBLT_WAIT
Primary.Flip Nothing, DDFLIP_WAIT
Next I
End Sub


 Here, the first two lines must be clear. The third line clears the backbuffer. The fourth line actually draws the Bitmap on the BackBuffer. The first parameter tells where to place this Bitmap on the BackBuffer. The second parameter tells the name of the surface which contains the Bitmap. The third parameter tells the region from where on the surface to read the bitmap. The fifth line as usual flips the Primary surface and the BackBuffer. Now run the program. You will see the Bitmap on the screen.  


ANIMATING BITMAPS


It is very easy to animate a Bitmap. Now draw a Bitmap named “Test.bmp” of size 60 X 60. In the above code change the name of the Bitmap from “Hello.bmp” to “Test.bmp”. Change the size such that the lWidth and lHeight parameters look like this –  


ddsdNewSprite.lWidth = 60
ddsdNewSprite.lHeight = 60
 Now change the SrcRect and DestRect to the following –  
With SrcRect
.Bottom = 60
.Right = 60
.Left = 0
.Top = 0
End With
 
With DestRect
.Bottom = 60
.Right = 60
.Left = 0
.Top = 0
End With


 In order to continuously change the position of the Bitmap, we have to change the position where the Image will be placed on the BackBuffer. We can do this by changing the parameters in the DestRect. To do this modify the Form_Load procedure so hat it looks like this –  


Private Sub Form_Load()
Call init
 Call InitSprite
 
 For i = 10 To 470
Call clear
With DestRect
.Left = i
.Right = 60 + i
.Top = 30
.Bottom = 90
End With
BackBuffer.Blt DestRect, MainSprite, SrcRect, DDBLT_WAIT
Primary.Flip Nothing, DDFLIP_WAIT
Next I
End Sub


 Run the program and you will see “Test.bmp” fading across the screen. 
Okay, that was a simple introduction to DirectX. There are many other components of DirectX such as DirectSound DirectInput etc. The most interesting part of DirectX is Direct3D using which you can draw 3 Dimensional surfaces. To learn more about DirectX try to search the internet. A good site where you could find useful stuff is - http://www.rookscape.com/vbgaming/ . Go to the site and click on Tutorials to get a list of tutorials. It gives you introduction to DirectX using VB. You will find good tutorials on DirectInput and DirectSound.