LPDIRECTDRAW7 lpdd = NULL; // dd object
LPDIRECTDRAWSURFACE7 lpddsprimary = NULL; // dd primary surface
DDSURFACEDESC2 ddsd; // a direct draw surface description struct
// create IDirectDraw interface 7.0 object and test for error
if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
return(0);
// set cooperation to full screen
if (FAILED(lpdd->SetCooperativeLevel(main_window_handle,
DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX |
DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
return(0);
// set display mode to 640x480x16
if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0)))
return(0);
// clear ddsd and set size
memset(&ddsd,0,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
// enable valid fields
ddsd.dwFlags = DDSD_CAPS;
// request primary surface
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
// create the primary surface
if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
return(0);
这就写完了。现在你可以看到一个黑屏(如果住缓冲留有数据的话,也可能你会看到一些乱七八糟的东西)。
无论如何,为了往屏幕上写数据,你必须:
1、锁住主表面-----调用Lock()函数
2、建立16位RGB字----这可以通过使用定义的宏之一(_RGB16BIT555(r,g,b) 、_RGB16BIT565(r,g,b)),或者你自己来生成它
3、写像素----这意味着采用一个USHORT指针定位主缓冲,将像素写入VRAM缓冲
4、解锁主表面-----调用UnLock()函数。
下面给出16位像素绘制函数代码:
void Polt_Pixel116(int x, int y ,int red , int green , int blue , LPDIRECTDRAWSURFACE7 lpdds)
{
DDSURFACE2 ddsd;/////dd surface description
USHORT pixel = _RGB16BIT565(red,green,blue); /////build up color WORD
///now lock video buffer
DDRAW_INIT_STRUCT(ddsd);///---->#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }
lpdds->Lock(NULL,&ddsd,DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR ,NULL);
///write the pixel
////alias(别名、化名) the surface memory pointer to a USHORT ptr 就是声明一个指针指向主表面(当色深8位是指针类型位UCHAR* ,16位时为USHORT*,32.....)
USHORT *video_buffer = ddsd.lpSurface;
///write the data
video_buffer[x + y*(ddsd.lPitch>>1)] = pixel;
///unlock the surface
lpdds->UnLock(NULL);
}//////end of Polt_Pixel16
优化后的程序版本:
inline void Plot_Pixel_Fast16(int x, int y,
int red, int green, int blue,
USHORT *video_buffer, int lpitch)
{
// this function plots a pixel in 16-bit color mode
// assuming that the caller already locked the surface
// and is sending a pointer and byte pitch to it
// first build up color WORD
USHORT pixel = _RGB16BIT565(red,green,blue);
// write the data
video_buffer[x + y*(lpitch>>1)] = pixel;
} // end Plot_Pixel_Fast16
改写上述优化后的版本程序(更快的版本):
int lpitch16 = (lpitch>>1);
inline void Plot_Pixel_Faster16(int x, int y,
int red, int green, int blue,
USHORT *video_buffer, int lpitch16)
{
// this function plots a pixel in 16-bit color mode
// assuming that the caller already locked the surface
// and is sending a pointer and byte pitch to it
// first build up color WORD
USHORT pixel = _RGB16BIT565(red,green,blue);//////上面说的第二步,创造一个RGB字
// write the data
video_buffer[x + y*lpitch16] = pixel;
} // end Plot_Pixel_Faster16
使用16位绘制像素函数的例子:
int Game_Main(void *parms = NULL, int num_parms = 0)
{
// this is the main loop of the game, do all your processing
// here
// for now test if user is hitting ESC and send WM_CLOSE
if (KEYDOWN(VK_ESCAPE))
SendMessage(main_window_handle,WM_CLOSE,0,0);
// plot 1000 random pixels to the primary surface and return
// clear ddsd and set size, never assume it's clean
DDRAW_INIT_STRUCT(ddsd);
// lock the primary surface
if (FAILED(lpddsprimary->Lock(NULL, &ddsd,
DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
NULL)))
return(0);
// now ddsd.lPitch is valid and so is ddsd.lpSurface
// make a couple aliases to make code cleaner, so we don't
// have to cast
int lpitch16 = (int)(ddsd.lPitch >> 1);
USHORT *video_buffer = (USHORT *)ddsd.lpSurface;
// plot 1000 random pixels with random colors on the
// primary surface, they will be instantly visible
for (int index=0; index < 1000; index++)
{
// select random position and color for 640x480x16
int red = rand()%256;
int green = rand()%256;
int blue = rand()%256;
int x = rand()%640;
int y = rand()%480;
// plot the pixel
Plot_Pixel_Faster16(x,y,red,green,blue,video_buffer,lpitch16);
} // end for index
// now unlock the primary surface
if (FAILED(lpddsprimary->Unlock(NULL)))
return(0);
// return success or failure or your own return code here
return(1);
} // end Game_Main