Our Direct Draw LibraryAlright, we are now ready to start coding our Direct Draw library routines. So, the logical starting place would be figuring out what kinds of routines we will need for the game. Obviously we want an initialization and shutdown routine, and we are going to need a function to lock and unlock surfaces. Also, it would be nice to have a function to draw text, and, since the game is going to run in 16 bpp mode, we will want a function that can figure out the pixel format for us. It would also be a good idea to have a function that creates surfaces, loads a bitmap into a surface, and a function to flip our buffers for us. That should cover it ... so lets get started. The first routine that we will look at is the initialization routine. This is the most logical place to start, especially since the routine has just about every type of call we will be using in Direct Draw. Here is the code: The above code is fairly complex so let's see what each individual section does. The first step is we create a default Direct Draw object. This is nothing more than a simple call with a couple of parameters. NOTE: since it is NOT based on an already created object, the function is not virtual. Therefore, we can call it like a normal function using invoke. Also, notice how we check for an error right afterwards. This is very important in DirectX. In the case of an error, we merely give a message, and then jump to the error return at the bottom of the procedure. The second step is we query for a DirectDraw4 object. We will almost always want the newest version of the objects, and querying after you have the base object is the way to get them. If this succeeds we then set the cooperative level and the display mode for our game. Nothing major ... but don't forget to check for errors. Our next step is to create a primary surface for the object that we have. If that succeeds we create the back buffer. The structure that we use in this call, and other DirectX calls, needs to be cleared before using it. This is done in a macro, DDINITSTRUCT, that I have included in the DDraw.inc file. The final thing we do is make a call to our routine that determines the pixel format for our surfaces. All of these pieces fit together into initializing our system for use. The next routine we will look at is the pixel format obtainer. This is a fairly advanced routine so I wanted to make sure that we cover it. Here is the code: First, we initialize our description structure and make a call to get the surface description from Direct Draw. We place the masks that are returned in global variables, since we will want to use them in all kinds of places. A mask is a value that you can use to set or clear certain bits in a variable/register. In our case, we use them to mask off the unnecessary bits so that we can access the red, green, or blue bits of our pixel individually. The next three sections of code are used to determine the number of bits in each color component. For example, if we had set the mode to 24 bpp, then there would be 8-bits in every component. The way we determine the number of bits it needs to be moved is by shifting each mask to the right by 1 and AND'ing it with the number one. This allows us to effectively count all the bits we need to shift by in order to move our component into its proper position. This works because the mask is going to contain a 1 where the bits are valid. So, by AND'ing it with the 1 we are able to see if the bit was turned on or not, since the number one will leave only the first bit set and turn all others off. Finally, we set a variable that tells us whether or not the video mode is 5-5-5 or 5-6-5. This is extremely important since 16 bpp mode can be either, and we do not want our pictures to have a green or purple tint on one machine, and look fine on another one! The last function that I want to cover in our Direct Draw library is the text drawing function. This uses GDI and so I figured I should at least give it a small explanation. The code ... Following this code is relatively simple. First, we get the Device Context for our surface. In Windows, drawing is typically done through these DC's ( Device Contexts ), thus ... if you want to use any GDI function in Direct Draw the first thing you have to do is get the DC for your surface. Then, we set the background mode and text color using basic Windows GDI calls. Now, we are ready to draw our text ... again we just make a call to the Windows function TextOut(). There are many others, this is just the one that I chose to use. Finally, we release the DC for our surface. The rest of the Direct Draw routines follow the same basic format and use the same types of calls, so they shouldn't be too hard to figure out. The basic idea behind all of the routines is the same: encapsulate the functionality we need into some services that still allow us to be flexible. Now, we need to write the code to handle our bitmaps that go into these surfaces. |
|