Squirm
10-06-2001, 10:11 AM
Hi, me again. After giving you an introduction to DirectX with DirectMusic, its time to move towards the mainstream of what people want, with the second-hardest topic, DirectDraw.
For this tutorial I will be using DirectX 7. DirectX 8 does not have support for DirectDraw, instead you have to do everything through Direct3D. Hopefully by DX9 it will have returned. Hopefully.......
Firstly, Im going to assume you've read the first tutorial. If you haven't, click here (http://www.visualbasicforum.com/showthread.php?s=&threadid=11945). You will need to reference DirectX in just the same way. Apart from that, things will be very different.....
First, we need some objects to work with:
Option Explicit
Dim DX As New DirectX7
Dim DD As DirectDraw7
Dim Primary As DirectDrawSurface7
Dim BackBuffer As DirectDrawSurface7
Dim BitSurf As DirectDrawSurface7
Dim ddsd1 As DDSURFACEDESC2
Dim ddsd2 As DDSURFACEDESC2
Dim ddsd3 As DDSURFACEDESC2
WOA! Loads of new objects there..... here's an explanation:
DirectDraw7 - The main DirectDraw object
DirectDrawSurface7 - This is a 'surface' , an area of main memory or video memory where we can take images from, or send them to. The Primary will be the main surface which we see. The BackBuffer is a hidden surface which we draw to, and the BitSurf is where we hold a loaded bitmap.
DDSURFACEDESC2 - tricky one to remember. This type stores information about a surface. We have dimmed one for each of our surfaces.
Right, now thats out the way, we can get on with some general dimming:
Dim bInit As Boolean
Dim bRunning As Boolean
Just 2 simple booleans to check various things along the way... now we need to code DirectDraw to DO something:
Set DD = DX.DirectDrawCreate("")
Form1.Show
Following so far? The above code has set DirectDraw, and "" means with the default driver, usually the best one images/icons/wink.gif. Form1.Show merely shows the form which we are drawing to.
Call DD.SetCooperativeLevel(Form1.hWnd, DDSCL_FULLSCREEN Or DDSCL_ALLOWMODEX Or DDSCL_EXCLUSIVE)
Call DD.SetDisplayMode(640, 480, 16, 0, DDSDM_DEFAULT)
Wow, tricky code there. These two lines setup DirectDraw to draw onto Form1. EXCULSIVE means that our app has complete control over DirectDraw, so other windows stuff is kept out. FULLSCREEN means we will be using DirectDraw in fullscreen mode (windowed mode will be covered in my next tutorial). The second line sets the display to 640x480x16. You can set anything you like, such as 1152x864x32, which I use a lot, since its my normal desktop resolution. Anyway, moving on......
Now we need to set up our surfaces which we dimmed before. First is the Primary:
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)
This has initialised the surface we called Primary to be the displayed surface, and has set it up to have one attatched BackBuffer. You might use two if you were doing triplebuffering, or Zbuffering, but those are more advanced topics. Now, we set up the BackBuffer surface:
Dim caps As DDSCAPS2
caps.lCaps = DDSCAPS_BACKBUFFER
Set BackBuffer = Primary.GetAttachedSurface(caps)
BackBuffer.GetSurfaceDesc ddsd3
Similar stuff, only this time instead of PRIMARY we have used BACKBUFFER. Now, once this has been done, the setup of DirectDraw is fully complete. If we wanted to, we could start drawing stuff to the backbuffer with DrawText and DrawBox, but for most applications, you'll probably want to draw bitmaps onto the surface. Use this code to set up BitSurf:
ddsd2.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH
ddsd2.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
ddsd2.lWidth = ddsd3.lWidth
ddsd2.lHeight = ddsd3.lHeight
Set BitSurf = DD.CreateSurfaceFromFile("C:\mypic.bmp", ddsd2)
This means that BitSurf has been made into an OFFSCREENPLAIN surface, once which is not ever seen, but holds an image of some sort. The parts with ddsd2 and ddsd3 are just making the bitmap the same size as the screen. Now, finally, everything has been setup. We can now start to show stuff. At this point it might be a good idea to have bInit = True.
Before I go on, you have to understand how DirectDraw fullscreen works. Basically, we draw something onto the backbuffer, and then 'flip' it..... this means that the BackBuffer becomes the Primary and the Primary becomes the backbuffer. Thus, we are drawing to one surface while the other surface is onscreen. Flipping happens very fast, and is the framerate of your application (here it should be around 85+). Because we need to be constantly flipping, everything has to be done in a continuous loop. That is why I set up bRunning, so that we can see whats going on....
Now add the following code, a new sub: (you could have put all that stuff before into an Initialise sub or something)
Sub DrawPic()
If bInit = False Then Exit Sub
Dim rBack As RECT
rBack.Bottom = ddsd3.lHeight
rBack.Right = ddsd3.lWidth
Call BackBuffer.BltFast(0, 0, BitSurf, rBack, DDBLTFAST_WAIT)
Primary.Flip Nothing, DDFLIP_WAIT
End Sub
This is very easy to follow. A rectangle (RECT) is setup to the size of the screen (ddsd3) as a source and then the contents of BitSurf are pasted to it on the BackBuffer using the BltFast call. Simple. Then, the flip occurs, and what we have done so far appears on screen. Neat, huh?
All we need now is a loop somewhere (outside this sub) something like this:
Do While bRunning
DrawPic
DoEvents
Loop
DoEvents very important there. Now, how do we make bRunning false? By putting some code in the Form_KeyDown, Form_KeyPress, or Form_Click subs of Form1, like so:
Private Sub Form_Click()
bRunning = False
End Sub
The end is in sight, if you have got this far then you're doing well....... now all we need to do is clear up after ourselves when we have finished. We do this with the following code:
Call DD.RestoreDisplayMode
Call DD.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL)
Set Primary = Nothing
Set BackBuffer = Nothing
Set BitSurf = Nothing
Set DD = Nothing
This gives control of DirectDraw and the screen space back to Windows. As with DirectMusic, you might also want to close down DirectX if you are finished with it.
Congratulations. If you've got this far, you will have created a simple DirectDraw application. I know what you're thinking - 'If this is SIMPLE, what is compex going to be like?' - Well rest assured, its only really the setting up of DD that is so tricky. After that, its plain sailing.
Right, the next tutorial will be advanced DirectDraw, or did I say it would be DirectDraw windowed? ah, never mind.......
Good luck images/smilies/wink.gif
For this tutorial I will be using DirectX 7. DirectX 8 does not have support for DirectDraw, instead you have to do everything through Direct3D. Hopefully by DX9 it will have returned. Hopefully.......
Firstly, Im going to assume you've read the first tutorial. If you haven't, click here (http://www.visualbasicforum.com/showthread.php?s=&threadid=11945). You will need to reference DirectX in just the same way. Apart from that, things will be very different.....
First, we need some objects to work with:
Option Explicit
Dim DX As New DirectX7
Dim DD As DirectDraw7
Dim Primary As DirectDrawSurface7
Dim BackBuffer As DirectDrawSurface7
Dim BitSurf As DirectDrawSurface7
Dim ddsd1 As DDSURFACEDESC2
Dim ddsd2 As DDSURFACEDESC2
Dim ddsd3 As DDSURFACEDESC2
WOA! Loads of new objects there..... here's an explanation:
DirectDraw7 - The main DirectDraw object
DirectDrawSurface7 - This is a 'surface' , an area of main memory or video memory where we can take images from, or send them to. The Primary will be the main surface which we see. The BackBuffer is a hidden surface which we draw to, and the BitSurf is where we hold a loaded bitmap.
DDSURFACEDESC2 - tricky one to remember. This type stores information about a surface. We have dimmed one for each of our surfaces.
Right, now thats out the way, we can get on with some general dimming:
Dim bInit As Boolean
Dim bRunning As Boolean
Just 2 simple booleans to check various things along the way... now we need to code DirectDraw to DO something:
Set DD = DX.DirectDrawCreate("")
Form1.Show
Following so far? The above code has set DirectDraw, and "" means with the default driver, usually the best one images/icons/wink.gif. Form1.Show merely shows the form which we are drawing to.
Call DD.SetCooperativeLevel(Form1.hWnd, DDSCL_FULLSCREEN Or DDSCL_ALLOWMODEX Or DDSCL_EXCLUSIVE)
Call DD.SetDisplayMode(640, 480, 16, 0, DDSDM_DEFAULT)
Wow, tricky code there. These two lines setup DirectDraw to draw onto Form1. EXCULSIVE means that our app has complete control over DirectDraw, so other windows stuff is kept out. FULLSCREEN means we will be using DirectDraw in fullscreen mode (windowed mode will be covered in my next tutorial). The second line sets the display to 640x480x16. You can set anything you like, such as 1152x864x32, which I use a lot, since its my normal desktop resolution. Anyway, moving on......
Now we need to set up our surfaces which we dimmed before. First is the Primary:
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)
This has initialised the surface we called Primary to be the displayed surface, and has set it up to have one attatched BackBuffer. You might use two if you were doing triplebuffering, or Zbuffering, but those are more advanced topics. Now, we set up the BackBuffer surface:
Dim caps As DDSCAPS2
caps.lCaps = DDSCAPS_BACKBUFFER
Set BackBuffer = Primary.GetAttachedSurface(caps)
BackBuffer.GetSurfaceDesc ddsd3
Similar stuff, only this time instead of PRIMARY we have used BACKBUFFER. Now, once this has been done, the setup of DirectDraw is fully complete. If we wanted to, we could start drawing stuff to the backbuffer with DrawText and DrawBox, but for most applications, you'll probably want to draw bitmaps onto the surface. Use this code to set up BitSurf:
ddsd2.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH
ddsd2.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
ddsd2.lWidth = ddsd3.lWidth
ddsd2.lHeight = ddsd3.lHeight
Set BitSurf = DD.CreateSurfaceFromFile("C:\mypic.bmp", ddsd2)
This means that BitSurf has been made into an OFFSCREENPLAIN surface, once which is not ever seen, but holds an image of some sort. The parts with ddsd2 and ddsd3 are just making the bitmap the same size as the screen. Now, finally, everything has been setup. We can now start to show stuff. At this point it might be a good idea to have bInit = True.
Before I go on, you have to understand how DirectDraw fullscreen works. Basically, we draw something onto the backbuffer, and then 'flip' it..... this means that the BackBuffer becomes the Primary and the Primary becomes the backbuffer. Thus, we are drawing to one surface while the other surface is onscreen. Flipping happens very fast, and is the framerate of your application (here it should be around 85+). Because we need to be constantly flipping, everything has to be done in a continuous loop. That is why I set up bRunning, so that we can see whats going on....
Now add the following code, a new sub: (you could have put all that stuff before into an Initialise sub or something)
Sub DrawPic()
If bInit = False Then Exit Sub
Dim rBack As RECT
rBack.Bottom = ddsd3.lHeight
rBack.Right = ddsd3.lWidth
Call BackBuffer.BltFast(0, 0, BitSurf, rBack, DDBLTFAST_WAIT)
Primary.Flip Nothing, DDFLIP_WAIT
End Sub
This is very easy to follow. A rectangle (RECT) is setup to the size of the screen (ddsd3) as a source and then the contents of BitSurf are pasted to it on the BackBuffer using the BltFast call. Simple. Then, the flip occurs, and what we have done so far appears on screen. Neat, huh?
All we need now is a loop somewhere (outside this sub) something like this:
Do While bRunning
DrawPic
DoEvents
Loop
DoEvents very important there. Now, how do we make bRunning false? By putting some code in the Form_KeyDown, Form_KeyPress, or Form_Click subs of Form1, like so:
Private Sub Form_Click()
bRunning = False
End Sub
The end is in sight, if you have got this far then you're doing well....... now all we need to do is clear up after ourselves when we have finished. We do this with the following code:
Call DD.RestoreDisplayMode
Call DD.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL)
Set Primary = Nothing
Set BackBuffer = Nothing
Set BitSurf = Nothing
Set DD = Nothing
This gives control of DirectDraw and the screen space back to Windows. As with DirectMusic, you might also want to close down DirectX if you are finished with it.
Congratulations. If you've got this far, you will have created a simple DirectDraw application. I know what you're thinking - 'If this is SIMPLE, what is compex going to be like?' - Well rest assured, its only really the setting up of DD that is so tricky. After that, its plain sailing.
Right, the next tutorial will be advanced DirectDraw, or did I say it would be DirectDraw windowed? ah, never mind.......
Good luck images/smilies/wink.gif