JavaScript EditorFree JavaScript Editor     Ajax Editor 



Main Page
  Previous Section Next Section

The BOB (Blitter Object) Engine

Although with a bit of programming you can get the BITMAP_IMAGE type to do what you want, it's lacking in a serious way—it doesn't use DirectDraw surfaces, so there's no support for acceleration. Therefore, I've created a new type called a Blitter Object (BOB) that's very similar to a sprite. For those of you who've been in a game programming cave, a sprite is nothing more than an object you can move around the screen that usually doesn't disturb the background. In this case that isn't true, so I called my animation object a BOB rather than a sprite—so there!

You haven't seen any of the BOB engine source code so far in this book, but you have seen everything that went into making it. I don't have enough space to list the source code, but it's in the file T3DLIB1.CPP along with everything else. What I'm going to do is show you each function that makes up the engine, and you're free to use the code, print it out and burn it, or whatever. I just wanted to give you a good example of using DirectDraw surfaces and full acceleration before you moved on to the remaining non-graphical components of DirectX.

Let's talk briefly about what a BOB is. First, take a look at the data structure for a BOB, which is back in the section "Data Types and Structures," and then come back here…Ready?

A BOB is basically a graphical object represented by one or more DirectDraw surfaces (up to 64). You can move a BOB, draw a BOB, and animate a BOB. BOBs are clipped by the current DirectDraw clipper, so they're clipped as well as accelerated—which is a good thing! Figure 8.55 shows a BOB and its relationship to its animation frames.

Figure 8.55. The BOB (blitter object) animation system.

graphics/08fig55.gif

Also, the BOB engine supports animation sequences, so you can load in a set of frames and an animation sequence and the sequence will play by feeding from the frames. This is a very cool feature. Also, all the BOB functions return TRUE if successful and FALSE otherwise. And of course BOBs support both 8 and 16-bit modes. Since BOBs are DirectDraw objects more or less, only a few functions need 16-bit versions (mostly in the loading and drawing calls) since most of the BOB is abstracted enough that it doesn't matter, but where it does there are of course two functions: one for 8-bit and one for 16-bit modes. The 16-bit functions are the exact same as the 8-bit with "16" concatenated on the function name. But, I will take you through this as we go.

So let's take a look at them all…

Function Prototype:

int Create_BOB(BOB_PTR bob, // ptr to bob to create
   int x, int y,          // initial position of bob
   int width, int height, // size of bob
   int num_frames, // total number of frames for bob
   int attr,       // attributes of bob
   int mem_flags, // surface memory flags, 0 is VRAM
   USHORT color_key_value=0, // color key value, index for
                             // 8-bit modes or RGB value for
                             // 16-bit modes
  int bpp=8);   // color depth of the requested bob

Purpose:

Create_BOB() creates a single BOB object and sets it up for either a 8 or 16-bit display. The function sets up all the internal variables in addition to creating a separate DirectDraw surface for each frame. Most of the parameters are self-explanatory; the only value that needs a little explanation is the attribute variable attr. Take a look at Table 8.4 to see a better description of each of the attributes you can logically OR together and send in this field.

Table 8.4. Valid BOB Attributes
Value Description
BOB_ATTR_SINGLE_FRAME Creates BOB with a single frame.
BOB_ATTR_MULTI_FRAME Creates BOB with multiple frames, but the animation of the BOB will be a linear sequence through the frames 0..n.
BOB_ATTR_MULTI_ANIM Creates a multiple-frame BOB that supports animation sequences.
BOB_ATTR_ANIM_ONE_SHOT If this is set, an animation sequence will play only once and then stop. At that point the internal variable anim_state will be set. To play the animation again, reset this variable.
BOB_ATTR_BOUNCE This flag tells the BOB to bounce off the screen boundaries like a ball. This only works if you use Move_BOB().
BOB_ATTR_WRAPAROUND This flag tells the BOB to wrap around to the other side of the screen as it moves. This only works if you use Move_BOB().

Examples:

Here are some examples of creating BOBs. First, a single-frame 8-bit BOB at (50,100) with a size of 96x64:

BOB car; // a car bob

// create the bob
if (!Create_BOB(&car, 50,100,
                96,64,1,BOB_ATTR_SINGLE_FRAME,0))
   { /* error */ }
// note that last two parameters were left out since they
// have default values of 0 for the color key and 8 for bpp

And here's a multiple-frame 16-bit BOB with eight frames and a size of 32x32:

BOB ship; // a space ship bob

// create the bob
if (!Create_BOB(&ship, 0,0,
                32,32,8,BOB_ATTR_MULTI_FRAME,0,0,16))
   { /* error */ }

Finally, a multiple-frame 8-bit BOB that supports animation sequences:

BOB greeny; // a little green man bob

// create the bob
if (!Create_BOB(&greeny, 0,0,
    32,32,32,BOB_ATTR_MULTI_ANIM,0,0,0))
   { /* error */ }

WARNING

It is extremely important that you create BOBs with the correct bit depth or bits per pixel, if you don't then you will probably crash the machine. Remember, the function defaults to 8-bit.


Function Prototype:

int Destroy_BOB(BOB_PTR bob); // ptr to bob to destroy

Purpose:

Destroy_BOB() destroys a previously created BOB. You would do this when you are done with the BOB and want to release the memory it used back to Windows. This function destroys either 8-bit or 16-bit BOBs with the same call.

Example:

// destroy the BOB above, you would do this
Destroy_BOB(&greeny);

Function Prototype:

int Draw_BOB(BOB_PTR bob,  // ptr of bob to draw
  LPDIRECTDRAWSURFACE7 dest); // dest surface to draw on

// 16-bit version
int Draw_BOB16(BOB_PTR bob,  // ptr of bob to draw
  LPDIRECTDRAWSURFACE7 dest); // dest surface to draw on

Purpose:

Draw_BOB*() is a very powerful function. It draws the sent BOB on the DirectDraw surface that you send it. The BOB is drawn in its current position and current frame, as defined by its animation parameters. Use the standard Draw_BOB() function for 8-bit modes and the 16-bit version Draw_BOB16() for 16-bit modes.

WARNING

For this function to work, the destination surface must not be locked.


Example:

// this is how you would position an 8-bit multiframe BOB at
// (50,50) and draw the first frame of it on the back
// surface:
BOB ship; // a space ship bob

// create the bob
if (!Create_BOB(&ship, 0,0,
                32,32,8,BOB_ATTR_MULTI_FRAME,0))

// load the bob images in..well get to this in a bit
// set the position and frame of bob
ship.x = 50;
ship.y = 50;
ship.curr_frame = 0; // this contains the frame to draw

// draw bob
Draw_BOB(&ship, lpddsback);

// same example with a 16-bit BOB
// this is how you would position an 8-bit multiframe BOB at
// (50,50) and draw the first frame of it on the back
// surface:
BOB ship; // a space ship bob

// create the bob
if (!Create_BOB(&ship, 0,0,
                32,32,8,BOB_ATTR_MULTI_FRAME,0,0,16))

// load the bob images in..well get to this in a bit
// set the position and frame of bob
ship.x = 50;
ship.y = 50;
ship.curr_frame = 0; // this contains the frame to draw

// draw bob
Draw_BOB16(&ship, lpddsback);

Function Prototype:

int Draw_Scaled_BOB(BOB_PTR bob, // ptr of bob to draw
  int swidth, int sheight, // new width and height of bob
  LPDIRECTDRAWSURFACE7 dest); // dest surface to draw on

// 16-bit version
int Draw_Scaled_BOB16(BOB_PTR bob, // ptr of bob to draw
  int swidth, int sheight, // new width and height of bob
  LPDIRECTDRAWSURFACE7 dest); // dest surface to draw on

Purpose:

Draw_Scaled_BOB*() works exactly like Draw_BOB*(), except that you can send any width and height to draw the BOB with and the engine will scale the BOB up or down. This is very cool, and if you have acceleration, it's a great way to scale a BOB to make it look 3D! Of course, you must use the correct version for your particular bit depth.

Example:

// an example of drawing aship at 128x128 even though
// it was created as only 32x32 pixels
// 8-bit call
Draw_Scaled_BOB(&ship, 128,128,lpddsback);

Function Prototype:

int Load_Frame_BOB(
 BOB_PTR bob, // ptr of bob to load frame into
 BITMAP_FILE_PTR bitmap,// ptr of bitmap file to scan data
 int frame,   // frame number to place image into 0,1,2...
 int cx,int cy, // cell pos or abs pos to scan from
 int mode);     // scan mode, same as Load_Frame_Bitmap()

// 16-bit version
int Load_Frame_BOB16(
 BOB_PTR bob, // ptr of bob to load frame into
 BITMAP_FILE_PTR bitmap,// ptr of bitmap file to scan data
 int frame,   // frame number to place image into 0,1,2...
 int cx,int cy, // cell pos or abs pos to scan from
 int mode);     // scan mode, same as Load_Frame_Bitmap16()

Purpose:

The Load_Frame_BOB*() function works identically to the Load_Frame_Bitmap*() function, so refer to that for details. The only additional control parameter frame is the frame to load. If you create a BOB that has four frames, you'll load the frames in one by one. And of course use the right version for the bit depth you are working in.

Example:

// here's an example of loading 4 frames into an 8-bit BOB from a
// bitmap file in cell mode

BOB ship; // the bob
// loads frames 0,1,2,3 from cell position (0,0), (1,0),
// (2,0), (3,0)
// from bitmap8bit bitmap file, assume it has been loaded

for (int index=0; index<4; index++)
      Load_Frame_BOB(&ship,&bitmap8bit,
                       index, index,0,
                       BITMAP_EXTRACT_MODE_CELL );

// here's an example of loading 4 frames into an 16-bit BOB from a
// bitmap file in cell mode

BOB ship; // the bob
// loads frames 0,1,2,3 from cell position (0,0), (1,0),
// (2,0), (3,0)
// from bitmap8bit bitmap file, assume it has been loaded

for (int index=0; index<4; index++)
      Load_Frame_BOB16(&ship,&bitmap8bit,
                       index, index,0,
                       BITMAP_EXTRACT_MODE_CELL );

Function Prototype:

int Load_Animation_BOB(
   BOB_PTR bob,    // bob to load animation into
   int anim_index, // which animation to load 0..15
   int num_frames, // number of frames of animation
   int *sequence); // ptr to array holding sequence

Purpose:

Load_Animation() takes a little explaining. This function is used to load one of 16 arrays internal to the BOB that contain animation sequences. Each sequence contains an array of indices or frame numbers to display in sequence.

Example:

You might have a BOB that has eight frames, 0,1,…7, but you might have four animations defined as follows:

int anim_walk[]  = {0,1,2,1,0};
int anim_fire[]  = {5,6,0};
int anim_die[]   = {3,4};
int anim_sleep[] = {0,0,7,0,0};

Then, to load the animations into a 16-bit BOB, you would do the following:

// create a mutli animation bob
// create the bob
if (!Create_BOB(&alien, 0,0, 32,32,8,BOB_ATTR_MULTI_ANIM,0,0,16))
   { /* error */ }

// load the bob frames in... use 16 bit load function!
// load walk into animation 0
Load_Animation_BOB(&alien, 0,5,anim_walk);

// load fire into animation 1
Load_Animation_BOB(&alien, 1,3,anim_fire);

// load die into animation 2
Load_Animation_BOB(&alien, 2,2,anim_die);

// load sleep into animation 3
Load_Animation_BOB(&alien, 3,5,anim_sleep);

After loading the animations, you can set the active animation and play them with functions you'll see in a minute.

Function Prototype:

int Set_Pos_BOB(BOB_PTR bob, // ptr to bob to set position
             int x, int y);  // new position of bob

Purpose:

Set_Pos_BOB() is a simple way to set the position of the BOB. It does nothing more than assign the internal (x,y) variables, but it's nice to have a function.

Example:

// set the position of the alien BOB above
Set_Pos_BOB(&alien, player_x, player_y);

Function Prototype:

int Set_Vel_BOB(BOB_PTR bob, // ptr to bob to set velocity
         int xv, int yv); // new x,y velocity

Purpose:

Each BOB has an internal velocity contained in (xv,yv). Set_Vel_BOB() simply assigns these values the new values sent in the function. The velocity values in the BOB won't do anything unless you use the function Move_BOB() to move your BOBs. However, even if you don't, you can use (xv,yv) to track the velocity of the BOB yourself.

Example:

// make the BOB move in a straight horizontal line
Set_Vel_BOB(&alien, 10,0);

Function Prototype:

int Set_Anim_Speed_BOB(BOB_PTR bob, // ptr to bob
                 int speed); // speed of animation

Purpose:

Set_Anim_Speed() sets the internal animation rate for a BOB anim_count_max. The higher this number, the slower the animation. The lower the number (0 is the lowest), the faster the animation. However, this function only matters if you use the internal BOB animation function Animate_BOB(). And of course, you must have created a BOB that has multiple frames.

Example:

// set the rate to change frames every 30 frames
Set_Anim_Speed_BOB(&alien, 30);

Function Prototype:

int Set_Animation_BOB(
         BOB_PTR bob,  // ptr of bob to set animation
         int anim_index); // index of animation to set

Purpose:

Set_Animation_BOB() sets the current animation that will be played by the BOB. In the earlier example of Load_Animation_BOB(), you created four animations.

Example:

// make animation sequence number 2 active
Set_Animation_BOB(&alien, 2);

NOTE

This also resets the BOB animation to the first frame in the sequence.


Function Prototype:

int Animate_BOB(BOB_PTR bob); // ptr to bob to animate

Purpose:

Animate_BOB() animates a BOB for you. Normally, you would call this function once per frame to update the animation of the BOB.

Example:

// erase everything...
// move everything...
// animate everything
Animate_BOB(&alien);

Function Prototype:

int Move_BOB(BOB_PTR bob); // ptr of bob to move

Purpose:

Move_BOB() moves the BOB a delta of xv,yv, and then, depending on the attributes, it will either bounce the BOB off the walls, wrap it around, or do nothing. Similarly to the Animate_BOB() function, you would place this call once in the main loop right after (or before) Animate_BOB().

Example:

// animate bob
Animate_BOB(&alien);

// move it
Move_BOB(&alien);

Function Prototype:

int Hide_BOB(BOB_PTR bob); // ptr to bob to hide

Purpose:

Hide_BOB() simply sets the invisible flag on the BOB so Draw_BOB() won't display it.

Example:

// hide the bob
Hide_BOB(&alien);

Function Prototype:

int Show_BOB(BOB_PTR bob); // ptr to bob to show

Purpose:

Show_BOB() sets the visible flag on a BOB so it will be drawn (undoes a Hide_BOB() call). Here's an example of hiding and showing a BOB because you're displaying a GDI object or something and don't want the BOB to occlude it:

Example:

Hide_BOB(&alien);
// make calls to Draw_BOB and GDI etc.
Show_BOB(&alien);

Function Prototype:

int Collision_BOBS(BOB_PTR bob1,  // ptr to first bob
                   BOB_PTR bob2); // ptr to second bob

Purpose:

Collision_BOBS() detects if the bounding rectangles of two BOBs overlap. This can be used for collision detection in a game to see if a player BOB hits a missile BOB or whatever.

Example:

// check if a missile BOB hit a player BOB:
if (Collision_BOBS(&missile, &player))
   { /* make explosion sound */ }
      Previous Section Next Section
    



    JavaScript EditorAjax Editor     JavaScript Editor