这一节主要进行BOB引擎的使用,加个 bitmap类,派生出一个bob类
#include "common.h"
#pragma once
class ddraw_bitmap
{
public:
ddraw_bitmap( );
~ddraw_bitmap(void);
public:
int Flip_Bitmap( UCHAR * image, int bytes_per_line, int height );
int Load_Bitmap_File( BITMAP_FILE_PTR bitmap, char * filename );
int Scan_Image_Bitmap( BITMAP_FILE_PTR bitmap, LPDIRECTDRAWSURFACE7 lpdds, int cx, int cy );
void setPixelFormat( int pixelformat );
int Unload_Bitmap_File( BITMAP_FILE_PTR bitmap );
private:
int m_pixelformat;
};
相应的函数实现都已经进行过了。
加个结构体
typedef struct BITMAP_IMAGE_TYP
{
int state; // state of bitmap
int attr; // attributes of bitmap
int x,y; // position of bitmap
int width, height; // size of bitmap
int num_bytes; // total bytes of bitmap
int bpp; // bits per pixel
UCHAR *buffer; // pixels of bitmap
} BITMAP_IMAGE, *BITMAP_IMAGE_PTR;
加个BOB结构体
typedef struct BOB_TYP
{
int state;
int anim_state;
int attr;
float x,y;
float xv, yv;
int width, height;
int width_fill;
int bpp;
int counter_1;
int counter_2;
int max_count_1;
int max_count_2;
int varsI[16];
float varsF[16];
int curr_frame;
int num_frames;
int curr_animation;
int anim_counter;
int anim_index;
int anim_count_max;
int * animations[MAX_BOB_ANIMATIONS];
LPDIRECTDRAWSURFACE7 images[MAX_BOB_FRAMES];
} BOB, * BOB_PTR;
BOB的一些状态如下:
#define BOB_STATE_DEAD 0
#define BOB_STATE_ALIVE 1
#define BOB_STATE_DYING 2
#define BOB_STATE_ANIM_DONE 1
#define MAX_BOB_FRAMES 64
#define MAX_BOB_ANIMATIONS 16
#define BOB_ATTR_SINGLE_FRAME 1
#define BOB_ATTR_MULTI_FRAME 2
#define BOB_ATTR_MULTI_ANIM 4
#define BOB_ATTR_ANIM_ONE_SHOT 8
#define BOB_ATTR_VISIBLE 16
#define BOB_ATTR_BOUNCE 32
#define BOB_ATTR_WRAPAROUND 64
#define BOB_ATTR_LOADED 128
#define BOB_ATTR_CLONE 256
抽象出一个位图类
class ddraw_bitmap
{
public:
ddraw_bitmap( );
~ddraw_bitmap(void);
public:
int Create_Bitmap( BITMAP_IMAGE_PTR image, int x, int y, int width, int height, int bpp = 8);
int Destroy_Bitmap(BITMAP_IMAGE_PTR image);
int Draw_Bitmap(BITMAP_IMAGE_PTR source_bitmap,UCHAR *dest_buffer, int lpitch, int transparent);
int Flip_Bitmap( UCHAR * image, int bytes_per_line, int height );
int Load_Bitmap_File( BITMAP_FILE_PTR bitmap, char * filename );
int Load_Image_Bitmap( BITMAP_IMAGE_PTR image, BITMAP_FILE_PTR bitmap, int cx, int cy, int mode );
int Scan_Image_Bitmap( BITMAP_FILE_PTR bitmap, LPDIRECTDRAWSURFACE7 lpdds, int cx, int cy );
void setPixelFormat( int pixelformat );
int Unload_Bitmap_File( BITMAP_FILE_PTR bitmap );
private:
int m_pixelformat;
};
各成员函数以前都写过了,就不再赘述了,
再派生出一个BOB类。
class DDraw_BOB : public ddraw_bitmap
{
public:
DDraw_BOB(void);
~DDraw_BOB(void);
public:
int Animate_BOB( BOB_PTR bob );
int Create_BOB( LPDIRECTDRAW7 lpdd,BOB_PTR bob, int x, int y, int width, int height, int num_frames, int attr, int mem_flags = 0, USHORT color_key_value = 0, int bpp = 8);
int Draw_BOB( BOB_PTR bob, LPDIRECTDRAWSURFACE7 dest );
int Load_Animation_BOB( BOB_PTR bob, int anim_index, int num_frames, int * sequence );
int Load_Frame_BOB( BOB_PTR bob, // bob to load with data
BITMAP_FILE_PTR bitmap, // bitmap to scan image data from
int frame, // frame to load
int cx,int cy, // cell or absolute pos. to scan image from
int mode); // if 0 then cx,cy is cell position, else
// cx,cy are absolute coords
int Set_Animation_BOB(BOB_PTR bob, int anim_index);
int Set_Anim_Speed_BOB( BOB_PTR bob, int speed );
int Set_Pos_BOB( BOB_PTR bob, int x, int y );
int Set_Vel_BOB( BOB_PTR bob, int xv, int yv );
};
函数实现过程
#include "BOB.h"
DDraw_BOB::DDraw_BOB(void)
{
}
DDraw_BOB::~DDraw_BOB(void)
{
}
int DDraw_BOB::Create_BOB( LPDIRECTDRAW7 lpdd,BOB_PTR bob, int x, int y, int width, int height, int num_frames, int attr, int mem_flags, USHORT color_key_value, int bpp )
{
DDSURFACEDESC2 ddsd;
int index;
bob->state = BOB_STATE_ALIVE;
bob->attr = attr;
bob->anim_state = 0;
bob->counter_1 = 0;
bob->counter_2 = 0;
bob->max_count_1 = 0;
bob->curr_frame = 0;
bob->num_frames = num_frames;
bob->bpp = bpp;
bob->curr_animation = 0;
bob->anim_counter = 0;
bob->anim_index = 0;
bob->anim_count_max = 0;
bob->x = x;
bob->y = y;
bob->xv = 0;
bob->yv = 0;
bob->width = width;
bob->height = height;
for( int index = 0; index < MAX_BOB_FRAMES; index ++ )
bob->images[index] = NULL;
for( int index = 0; index < MAX_BOB_ANIMATIONS; index ++ )
bob->animations[index] = NULL;
for( int index = 0; index < bob->num_frames; index ++ )
{
memset( & ddsd, 0, sizeof( ddsd ) );
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.dwWidth = bob->width + bob->width_fill;
ddsd.dwHeight = bob->height;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | mem_flags;
if( FAILED( lpdd->CreateSurface( & ddsd, & ( bob->images[index] ), NULL ) ) )
return ( 0 );
DDCOLORKEY color_key;
color_key.dwColorSpaceLowValue = color_key_value;
color_key.dwColorSpaceHighValue = color_key_value;
( bob->images[index] )->SetColorKey( DDCKEY_SRCBLT, & color_key );
}
return ( 1 );
}
int DDraw_BOB::Load_Frame_BOB(BOB_PTR bob, // bob to load with data
BITMAP_FILE_PTR bitmap, // bitmap to scan image data from
int frame, // frame to load
int cx,int cy, // cell or absolute pos. to scan image from
int mode) // if 0 then cx,cy is cell position, else
// cx,cy are absolute coords
{
// this function extracts a bitmap out of a bitmap file
DDSURFACEDESC2 ddsd; // direct draw surface description
// is this a valid bob
if (!bob)
return(0);
UCHAR *source_ptr, // working pointers
*dest_ptr;
// test the mode of extraction, cell based or absolute
if (mode==BITMAP_EXTRACT_MODE_CELL)
{
// re-compute x,y
cx = cx*(bob->width+1) + 1;
cy = cy*(bob->height+1) + 1;
} // end if
// extract bitmap data
source_ptr = bitmap->buffer + cy*bitmap->bitmapinfoheader.biWidth+cx;
// get the addr to destination surface memory
// set size of the structure
ddsd.dwSize = sizeof(ddsd);
// lock the display surface
(bob->images[frame])->Lock(NULL,
&ddsd,
DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
NULL);
// assign a pointer to the memory surface for manipulation
dest_ptr = (UCHAR *)ddsd.lpSurface;
// iterate thru each scanline and copy bitmap
for (int index_y=0; index_y<bob->height; index_y++)
{
// copy next line of data to destination
memcpy(dest_ptr, source_ptr,bob->width);
// advance pointers
dest_ptr += (ddsd.lPitch); // (bob->width+bob->width_fill);
source_ptr += bitmap->bitmapinfoheader.biWidth;
} // end for index_y
// unlock the surface
(bob->images[frame])->Unlock(NULL);
// set state to loaded
bob->attr |= BOB_ATTR_LOADED;
// return success
return(1);
} // end Load_Frame_BOB
int DDraw_BOB::Load_Animation_BOB( BOB_PTR bob, int anim_index, int num_frames, int * sequence )
{
int index_an = 0;
if( !bob )
return ( 0 );
if( ! ( bob->animations[anim_index] = ( int * ) malloc( ( num_frames + 1 ) * sizeof( int ) ) ) )
return ( 0 );
for( index_an = 0; index_an < num_frames; index_an++ )
bob->animations[anim_index][index_an] = sequence[index_an];
bob->animations[anim_index][index_an] = -1;
return ( 1 );
}
int DDraw_BOB::Set_Animation_BOB(BOB_PTR bob, int anim_index)
{
// this function sets the animation to play
// is this a valid bob
if (!bob)
return(0);
// set the animation index
bob->curr_animation = anim_index;
// reset animation
bob->anim_index = 0;
// return success
return(1);
} // end Set_Animation_BOB
int DDraw_BOB::Set_Anim_Speed_BOB( BOB_PTR bob, int speed )
{
if( ! bob )
return ( 0 );
bob->anim_count_max = speed;
return ( 1 );
}
int DDraw_BOB::Set_Vel_BOB( BOB_PTR bob, int xv, int yv )
{
if( !bob )
return ( 0 );
bob->xv = xv;
bob->yv = yv;
return ( 1 );
}
int DDraw_BOB::Set_Pos_BOB( BOB_PTR bob, int x, int y )
{
if( !bob )
return ( 0 );
bob->x = x;
bob->y = y;
return ( 1 );
}
int DDraw_BOB::Animate_BOB( BOB_PTR bob )
{
if( ! bob )
return ( 0 );
if( bob->attr & BOB_ATTR_SINGLE_FRAME )
{
bob->curr_frame = 0;
return ( 1 );
}
else
if( bob->attr & BOB_ATTR_MULTI_FRAME )
{
if( ++ bob->anim_counter >= bob->anim_count_max )
{
bob->anim_counter = 0;
if( ++ bob->curr_frame >= bob->num_frames )
bob->curr_frame = 0;
}
}
else
if( bob->attr & BOB_ATTR_MULTI_ANIM )
{
if( ++ bob->anim_counter >= bob->anim_count_max )
{
bob->anim_counter = 0;
bob->anim_index ++;
bob->curr_frame = bob->animations[bob->curr_animation][bob->anim_index];
if( bob->curr_frame == -1 )
{
if( bob->attr & BOB_ATTR_ANIM_ONE_SHOT )
{
bob->anim_state = BOB_STATE_ANIM_DONE;
bob->anim_index--;
bob->curr_frame = bob->animations[bob->curr_animation][bob->anim_index];
}
else
{
bob->anim_index = 0;
bob->curr_frame = bob->animations[bob->curr_animation][bob->anim_index];
}
}
}
}
return ( 1 );
}
int DDraw_BOB::Draw_BOB( BOB_PTR bob, LPDIRECTDRAWSURFACE7 dest )
{
RECT dest_rect, source_rect;
if( ! bob )
return ( 0 );
if( ! ( bob->attr & BOB_ATTR_VISIBLE ) )
return ( 1 );
dest_rect.left = bob->x;
dest_rect.top = bob->y;
dest_rect.right = bob->x + bob->width;
dest_rect.bottom = bob->y + bob->height;
source_rect.left = 0;
source_rect.top = 0;
source_rect.right = bob->width;
source_rect.bottom = bob->height;
if( FAILED( dest->Blt( & dest_rect, bob->images[bob->curr_frame],
& source_rect, ( DDBLT_WAIT | DDBLT_KEYSRC ), NULL ) ) )
return ( 0 );
return ( 1 );
}
char filename[80];
POLYGON2D object;
DDraw_BOB bob;
BOB skelaton;
tool mytool;
char buffer[80];
BITMAP_FILE bitmap8bit;
BITMAP_IMAGE landscape[3];
int curr_page = 0;
int skelaton_anims[8][4] = { { 0, 1, 0, 2 },
{ 0+4, 1+4, 0+4, 2+4},
{0+8,1+8,0+8,2+8},
{0+12,1+12,0+12,2+12},
{0+16,1+16,0+16,2+16},
{0+20,1+20,0+20,2+20},
{0+24,1+24,0+24,2+24},
{0+28,1+28,0+28,2+28},
};
int Game_Init(void *parms = NULL, int num_parms = 0)
{
// this is called once after the initial window is created and
// before the main event loop is entered, do all your initialization
// here
srand( GetTickCount());
//初始化DDRAW
ddraw->DDraw_Init( main_window_handle, SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP );
for( int index = 0; index < 1; index ++ )
{
sprintf( filename, "LANDSCAPE%d.bmp", index+1 );
bob.Load_Bitmap_File( & bitmap8bit, filename );
bob.Create_Bitmap( & landscape[index], 0, 0, 640, 480 );
bob.Load_Image_Bitmap( & landscape[index], & bitmap8bit, 0, 0, BITMAP_EXTRACT_MODE_ABS );
bob.Unload_Bitmap_File( & bitmap8bit );
}
ddraw->Set_Palette( bitmap8bit.palette );
if( ! bob.Create_BOB( ddraw->getlpdd(), & skelaton, 0, 0, 72, 74, 32, BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_ANIM, DDSCAPS_SYSTEMMEMORY ) )
return ( 0 );
for( int direction = 0; direction < 8; direction ++ )
{
sprintf( filename, "QUENSP%d.bmp", direction );
bob.Load_Bitmap_File( & bitmap8bit, filename );
bob.Load_Frame_BOB( & skelaton, & bitmap8bit, 0 + direction * 4, 0, 0, BITMAP_EXTRACT_MODE_CELL );
bob.Load_Frame_BOB( & skelaton, & bitmap8bit, 1 + direction * 4, 1, 0, BITMAP_EXTRACT_MODE_CELL );
bob.Load_Frame_BOB( & skelaton, & bitmap8bit, 2 + direction * 4, 2, 0, BITMAP_EXTRACT_MODE_CELL );
bob.Load_Frame_BOB( & skelaton, & bitmap8bit, 3 + direction * 4, 0, 1, BITMAP_EXTRACT_MODE_CELL );
bob.Unload_Bitmap_File( & bitmap8bit );
bob.Load_Animation_BOB( & skelaton, direction, 4, skelaton_anims[direction] );
}
bob.Set_Animation_BOB( & skelaton, 0 );
bob.Set_Anim_Speed_BOB( & skelaton, 4 );
bob.Set_Vel_BOB( & skelaton, 0, 0 );
bob.Set_Pos_BOB( & skelaton, 16, 256 );
ShowCursor( FALSE );
// return success or failure or your own return code here
return(1);
}
int Game_Main(void *parms = NULL, int num_parms = 0)
{
int index;
int dx, dy;
static int player_moving = 0;
static PALETTEENTRY glow = { 0, 0, 0, PC_NOCOLLAPSE };
// make sure this isn't executed again
// for now test if user is hitting ESC and send WM_CLOSE
if (KEYDOWN(VK_ESCAPE))
{
PostMessage(main_window_handle,WM_DESTROY,0,0);
} // end if
mytool.Start_Clock();
ddraw->DDraw_Fill_Surface( ddraw->getbackSurface(), 0 );
ddraw->DDraw_Lock_Back_Surface();
bob.Draw_Bitmap( &landscape[curr_page], ddraw->getbackbuffer(), ddraw->getbacklpitch(), 0 );
ddraw->DDraw_Unlock_Back_Surface();
player_moving = 0;
if( KEYDOWN( VK_RIGHT ) )
{
skelaton.x += 2;
dx = 2;
dy = 0;
player_moving = 1;
if( skelaton.curr_animation != SKELATON_EAST )
bob.Set_Animation_BOB( & skelaton, SKELATON_EAST );
}
else
if( KEYDOWN( VK_LEFT ) )
{
skelaton.x -= 2;
dx = -2;
dy = 0;
player_moving = 1;
if( skelaton.curr_animation != SKELATON_WEST )
bob.Set_Animation_BOB( & skelaton, SKELATON_WEST );
}
skelaton.y += 1;
if( player_moving )
{
bob.Animate_BOB( & skelaton );
}
ddraw->DDraw_Lock_Back_Surface();
while( mytool.Color_Scan( SCREEN_WIDTH, SCREEN_HEIGHT,skelaton.x + 16, skelaton.y + 24, skelaton.x + skelaton.width - 32, skelaton.y + skelaton.height - 12,
FLOOR_COLOR, FLOOR_COLOR, ddraw->getbackbuffer(), ddraw->getbacklpitch() ) )
{
skelaton.y -= 1;
}
ddraw->DDraw_Unlock_Back_Surface();
bob.Draw_BOB( & skelaton, ddraw->getbackSurface() );
static int glow_count = 0;
if( ++ glow_count > 5 )
{
ddraw->Rotate_Colors( 152, 159 );
glow_count = 0 ;
}
glow.peGreen = rand() % 256;
ddraw->Set_Palette_Entry( FLOOR_COLOR, & glow );
if( skelaton.x > SCREEN_WIDTH - ( skelaton.width >> 1 ) )
{
skelaton.x -= dx;
if( curr_page < 2 )
{
curr_page++;
skelaton.x = - ( skelaton.width >> 1 );
}
}
else
if( skelaton.x < - ( skelaton.width >> 1 ) )
{
skelaton.x = - ( skelaton.width >> 1 );
if( curr_page > 0 )
{
curr_page--;
skelaton.x = SCREEN_WIDTH - ( skelaton.width >> 1 );
}
}
ddraw->DDraw_Flip();
//while( FAILED( ddraw->DDraw_Flip() ) );
mytool.Wait_Clock( 30 );
// do nothing -- look at pretty picture
// return success or failure or your own return code here
return(1);
} // end Game_Main
再看下T3dlib这里,销毁BOB
int DDraw_BOB::Destroy_BOB( BOB_PTR bob )
{
int index;
if( !bob )
return ( 0 );
if( bob->attr && BOB_ATTR_CLONE )
{
for( int index = 0; index < MAX_BOB_FRAMES; index++ )
if( bob->images[index] )
bob->images[index] = NULL;
for( int index = 0; index < MAX_BOB_ANIMATIONS; index ++ )
{
if( bob->animations[index] )
bob->animations[index] = NULL;
}
}
else
{
for( int index = 0; index < MAX_BOB_FRAMES; index++ )
if( bob->images[index] )
bob->images[index]->Release();
for( int index = 0; index < MAX_BOB_ANIMATIONS; index ++ )
{
if( bob->animations[index] )
free( bob->animations[index] );
}
}
return ( 1 );
}
16位绘制BOB,
int DDraw_BOB::Draw_BOB16( BOB_PTR bob, LPDIRECTDRAWSURFACE7 dest );发现没啥区别
放缩的,
int DDraw_BOB::Draw_Scaled_BOB( BOB_PTR bob, int swidth, int sheight, LPDIRECTDRAWSURFACE7 dest )
就是把原来的宽度和高度改了,
以前是
dest_rect.right = bob->x + bob->width;
dest_rect.bottom = bob->y + bob->height;
现在是
dest_rect.right = bob->x + swidth;
dest_rect.bottom = bob->y + sheight;
16位
int DDraw_BOB::Draw_Scaled_BOB16( BOB_PTR bob, int swidth, int sheight, LPDIRECTDRAWSURFACE7 dest )
没有区别
16位加载
int DDraw_BOB::Load_Frame_BOB16(BOB_PTR bob, // bob to load with data
BITMAP_FILE_PTR bitmap, // bitmap to scan image data from
int frame, // frame to load
int cx,int cy, // cell or absolute pos. to scan image from
int mode)
再分配空间时有区别
// copy next line of data to destination
memcpy(dest_ptr, source_ptr,bob->width * 2 );
// advance pointers
dest_ptr += (ddsd.lPitch >> 1); // (bob->width+bob->width_fill);
下面还有16位的颜色扫描碰撞检测
int tool::Color_Scan16( int screenwidth, int screenheight, int x1, int y1, int x2, int y2, USHORT scan_start, USHORT scan_end, UCHAR * scan_buffer, int scan_lpitch )
区别在于位数转换
USHORT * scan_buffer2 = ( USHORT * ) scan_buffer;
scan_lpitch = ( scan_lpitch >> 1 );
16位装载位图
int Load_Image_Bitmap16( BITMAP_IMAGE_PTR image, BITMAP_FILE_PTR bitmap, int cx, int cy, int mode );
区别在于
USHORT * source_ptr, * dest_ptr;
source_ptr =( USHORT * ) bitmap->buffer + cy * bitmap->bitmapinfoheader.biWidth + cx;
dest_ptr = ( USHORT * ) image->buffer;
int bytes_per_line = image->width * 2;
for( int index_y = 0; index_y < image->height; index_y ++ )
{
memcpy( dest_ptr, source_ptr, bytes_per_line );
。。。
还是16位和8位之间分配空间的区别。
16位绘制位图
int ddraw_bitmap::Draw_Bitmap16(BITMAP_IMAGE_PTR source_bitmap,UCHAR *dest_buffer, int lpitch, int transparent)
{
// this function draws the bitmap onto the destination memory surface
// if transparent is 1 then color 0 (8bit) or 0.0.0 (16bit) will be transparent
// note this function does NOT clip, so be carefull!!!
// test if this bitmap is loaded
if (!(source_bitmap->attr & BITMAP_ATTR_LOADED))
return(0);
USHORT *dest_addr, // starting address of bitmap in destination
*source_addr; // starting adddress of bitmap data in source
USHORT pixel; // used to hold pixel value
int index_loop, // looping vars
pixel_x,
lpitch_2 = lpitch >> 1;
// compute starting destination address
dest_addr = ( ( USHORT * )dest_buffer ) + source_bitmap->y*lpitch_2 + source_bitmap->x;
// compute the starting source address
source_addr = ( USHORT * )source_bitmap->buffer;
// is this bitmap transparent
if (transparent)
{
// copy each line of bitmap into destination with transparency
for (index_loop=0; index_loop<source_bitmap->height; index_loop++)
{
// copy the memory
for (pixel_x=0; pixel_x<source_bitmap->width; pixel_x++)
{
if ((pixel = source_addr[pixel_x])!=0)
dest_addr[pixel_x] = pixel;
} // end if
// advance all the pointers
dest_addr += lpitch2;
source_addr += source_bitmap->width;
} // end for index
} // end if
else
{
// non-transparent version
// copy each line of bitmap into destination
int source_bytes_per_line = source_bitmap->width * 2;
for (index_loop=0; index_loop < source_bitmap->height; index_loop++)
{
// copy the memory
memcpy(dest_addr, source_addr, source_bytes_per_line);
// advance all the pointers
dest_addr += lpitch2;
source_addr += source_bitmap->width;
} // end for index
} // end else
// return success
return(1);
} // end Draw_Bitmap