posts - 2, comments - 1, trackbacks - 0, articles - 4
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

高级DirectDraw和位图图形(3)

Posted on 2008-05-26 19:25 cacar 阅读(1948) 评论(1)  编辑 收藏 引用 所属分类: DirectX
    例子如下:
   1// DEMO7_13.CPP 8-bit blitting demo
   2
   3// INCLUDES ///////////////////////////////////////////////
   4
   5#define WIN32_LEAN_AND_MEAN  // just say no to MFC
   6
   7#define INITGUID
   8
   9#include <windows.h>   // include important windows stuff
  10#include <windowsx.h> 
  11#include <mmsystem.h>
  12#include <iostream.h> // include important C/C++ stuff
  13#include <conio.h>
  14#include <stdlib.h>
  15#include <malloc.h>
  16#include <memory.h>
  17#include <string.h>
  18#include <stdarg.h>
  19#include <stdio.h> 
  20#include <math.h>
  21#include <io.h>
  22#include <fcntl.h>
  23
  24#include <ddraw.h> // include directdraw
  25
  26// DEFINES ////////////////////////////////////////////////
  27
  28// defines for windows 
  29#define WINDOW_CLASS_NAME "WINCLASS1"
  30
  31// default screen size
  32#define SCREEN_WIDTH    640  // size of screen
  33#define SCREEN_HEIGHT   480
  34#define SCREEN_BPP      8    // bits per pixel
  35
  36#define BITMAP_ID            0x4D42 // universal id for a bitmap
  37#define MAX_COLORS_PALETTE   256
  38
  39// TYPES //////////////////////////////////////////////////////
  40
  41// basic unsigned types
  42typedef unsigned short USHORT;
  43typedef unsigned short WORD;
  44typedef unsigned char  UCHAR;
  45typedef unsigned char  BYTE;
  46
  47// container structure for bitmaps .BMP file
  48// 用来保存位图的结构体
  49typedef struct BITMAP_FILE_TAG
  50        {
  51        BITMAPFILEHEADER bitmapfileheader;  // this contains the bitmapfile header
  52        BITMAPINFOHEADER bitmapinfoheader;  // this is all the info including the palette
  53        PALETTEENTRY     palette[256];      // we will store the palette here
  54        UCHAR            *buffer;           // this is a pointer to the data
  55
  56        }
 BITMAP_FILE, *BITMAP_FILE_PTR;
  57
  58// this will hold our little alien
  59// Alien 结构体,包含了要在背景上绘制的“外星人”的各帧以及位置、速度等
  60typedef struct ALIEN_OBJ_TYP
  61        {
  62        LPDIRECTDRAWSURFACE7 frames[3]; // 3 frames of animation for complete walk cycle
  63        int x,y;                        // position of alien
  64        int velocity;                   // x-velocity
  65        int current_frame;              // current frame of animation
  66        int counter;                    // used to time animation
  67 
  68        }
 ALIEN_OBJ, *ALIEN_OBJ_PTR;
  69
  70// PROTOTYPES  //////////////////////////////////////////////
  71
  72int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height);
  73
  74int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename);
  75
  76int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap);
  77
  78int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color);
  79
  80int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap, LPDIRECTDRAWSURFACE7 lpdds, int cx,int cy);
  81
  82LPDIRECTDRAWSURFACE7 DDraw_Create_Surface(int width, int height, int mem_flags, int color_key);
  83
  84int DDraw_Draw_Surface(LPDIRECTDRAWSURFACE7 source, int x, int y, 
  85                      int width, int height, LPDIRECTDRAWSURFACE7 dest, 
  86                      int transparent);    
  87
  88LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds,
  89                                         int num_rects,
  90                                         LPRECT clip_list);
  91
  92int Draw_Text_GDI(char *text, int x,int y,COLORREF color, LPDIRECTDRAWSURFACE7 lpdds);
  93
  94// MACROS /////////////////////////////////////////////////
  95
  96// tests if a key is up or down
  97#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
  98#define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
  99
 100// initializes a direct draw struct
 101#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }
 102
 103// GLOBALS ////////////////////////////////////////////////
 104
 105HWND      main_window_handle = NULL; // globally track main window
 106int       window_closed      = 0;    // tracks if window is closed
 107HINSTANCE hinstance_app      = NULL; // globally track hinstance
 108
 109// directdraw stuff
 110
 111LPDIRECTDRAW7         lpdd         = NULL;   // dd4 object
 112LPDIRECTDRAWSURFACE7  lpddsprimary = NULL;   // dd primary surface
 113LPDIRECTDRAWSURFACE7  lpddsback    = NULL;   // dd back surface
 114LPDIRECTDRAWPALETTE   lpddpal      = NULL;   // a pointer to the created dd palette
 115LPDIRECTDRAWCLIPPER   lpddclipper  = NULL;   // dd clipper
 116PALETTEENTRY          palette[256];          // color palette
 117PALETTEENTRY          save_palette[256];     // used to save palettes
 118DDSURFACEDESC2        ddsd;                  // a direct draw surface description struct
 119DDBLTFX               ddbltfx;               // used to fill
 120DDSCAPS2              ddscaps;               // a direct draw surface capabilities struct
 121HRESULT               ddrval;                // result back from dd calls
 122DWORD                 start_clock_count = 0// used for timing
 123
 124BITMAP_FILE           bitmap;                // holds the bitmap
 125
 126ALIEN_OBJ             aliens[3];             // 3 aliens, one on each level
 127
 128LPDIRECTDRAWSURFACE7  lpddsbackground = NULL;// this will hold the background image
 129
 130char buffer[80];                             // general printing buffer
 131
 132int gwidth  = -1;
 133int gheight = -1;
 134
 135// FUNCTIONS ////////////////////////////////////////////////
 136// 载入位图文件到结构体
 137int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
 138{
 139// this function opens a bitmap file and loads the data into bitmap
 140
 141int file_handle,  // the file handle
 142    index;        // looping index
 143
 144UCHAR   *temp_buffer = NULL; // used to convert 24 bit images to 16 bit
 145OFSTRUCT file_data;          // the file data information
 146
 147// open the file if it exists
 148if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)
 149   return(0);
 150
 151// now load the bitmap file header
 152_lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));
 153
 154// test if this is a bitmap file
 155if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
 156   {
 157   // close the file
 158   _lclose(file_handle);
 159
 160   // return error
 161   return(0);
 162   }
 // end if
 163
 164// now we know this is a bitmap, so read in all the sections
 165
 166// first the bitmap infoheader
 167
 168// now load the bitmap file header
 169_lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));
 170
 171// now load the color palette if there is one
 172if (bitmap->bitmapinfoheader.biBitCount == 8)
 173   {
 174   _lread(file_handle, &bitmap->palette,MAX_COLORS_PALETTE*sizeof(PALETTEENTRY));
 175
 176   // now set all the flags in the palette correctly and fix the reversed 
 177   // BGR RGBQUAD data format
 178   for (index=0; index < MAX_COLORS_PALETTE; index++)
 179       {
 180       // reverse the red and green fields
 181       int temp_color                = bitmap->palette[index].peRed;
 182       bitmap->palette[index].peRed  = bitmap->palette[index].peBlue;
 183       bitmap->palette[index].peBlue = temp_color;
 184       
 185       // always set the flags word to this
 186       bitmap->palette[index].peFlags = PC_NOCOLLAPSE;
 187       }
 // end for index
 188
 189    }
 // end if
 190
 191// finally the image data itself
 192_lseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);
 193
 194// now read in the image, if the image is 8 or 16 bit then simply read it
 195// but if its 24 bit then read it into a temporary area and then convert
 196// it to a 16 bit image
 197
 198if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16 || 
 199    bitmap->bitmapinfoheader.biBitCount==24)
 200   {
 201   // delete the last image if there was one
 202   if (bitmap->buffer)
 203       free(bitmap->buffer);
 204
 205   // allocate the memory for the image
 206   if (!(bitmap->buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))
 207      {
 208      // close the file
 209      _lclose(file_handle);
 210
 211      // return error
 212      return(0);
 213      }
 // end if
 214
 215   // now read it in
 216   _lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);
 217
 218   }
 // end if
 219else
 220   {
 221   // serious problem
 222   return(0);
 223
 224   }
 // end else
 225
 226#if 0
 227// write the file info out 
 228printf("\nfilename:%s \nsize=%d \nwidth=%d \nheight=%d \nbitsperpixel=%d \ncolors=%d \nimpcolors=%d",
 229        filename,
 230        bitmap->bitmapinfoheader.biSizeImage,
 231        bitmap->bitmapinfoheader.biWidth,
 232        bitmap->bitmapinfoheader.biHeight,
 233        bitmap->bitmapinfoheader.biBitCount,
 234        bitmap->bitmapinfoheader.biClrUsed,
 235        bitmap->bitmapinfoheader.biClrImportant);
 236#endif
 237
 238// close the file
 239_lclose(file_handle);
 240
 241// flip the bitmap
 242Flip_Bitmap(bitmap->buffer, 
 243            bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8), 
 244            bitmap->bitmapinfoheader.biHeight);
 245
 246// return success
 247return(1);
 248
 249}
 // end Load_Bitmap_File
 250
 251///////////////////////////////////////////////////////////
 252// 卸载位图文件,释放内存
 253int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
 254{
 255// this function releases all memory associated with "bitmap"
 256if (bitmap->buffer)
 257   {
 258   // release memory
 259   free(bitmap->buffer);
 260
 261   // reset pointer
 262   bitmap->buffer = NULL;
 263
 264   }
 // end if
 265
 266// return success
 267return(1);
 268
 269}
 // end Unload_Bitmap_File
 270
 271///////////////////////////////////////////////////////////
 272//将位图文件上下颠倒~
 273int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)
 274{
 275// this function is used to flip bottom-up .BMP images
 276
 277UCHAR *buffer; // used to perform the image processing
 278int index;     // looping index
 279
 280// allocate the temporary buffer
 281if (!(buffer = (UCHAR *)malloc(bytes_per_line*height)))
 282   return(0);
 283
 284// copy image to work area
 285memcpy(buffer,image,bytes_per_line*height);
 286
 287// flip vertically
 288for (index=0; index < height; index++)
 289    memcpy(&image[((height-1- index)*bytes_per_line],
 290           &buffer[index*bytes_per_line], bytes_per_line);
 291
 292// release the memory
 293free(buffer);
 294
 295// return success
 296return(1);
 297
 298}
 // end Flip_Bitmap
 299
 300///////////////////////////////////////////////////////////////
 301//为表面关联裁剪器
 302LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds,
 303                                         int num_rects,
 304                                         LPRECT clip_list)
 305
 306{
 307// this function creates a clipper from the sent clip list and attaches
 308// it to the sent surface
 309
 310int index;                         // looping var
 311LPDIRECTDRAWCLIPPER lpddclipper;   // pointer to the newly created dd clipper
 312LPRGNDATA region_data;             // pointer to the region data that contains
 313                                   // the header and clip list
 314
 315// first create the direct draw clipper
 316// step 1: 生成裁剪器
 317if (FAILED(lpdd->CreateClipper(0,&lpddclipper,NULL)))
 318   return(NULL);
 319
 320// now create the clip list from the sent data
 321
 322//    step 2: 创建裁剪序列
 323// first allocate memory for region data
 324// 为ClipperList申请空间
 325region_data = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+num_rects*sizeof(RECT));
 326
 327// now copy the rects into region data
 328// 拷贝指定的RECTs到ClipperList,即 RGNDATA 结构体的 Buffer中
 329memcpy(region_data->Buffer, clip_list, sizeof(RECT)*num_rects);
 330
 331// set up fields of header
 332region_data->rdh.dwSize          = sizeof(RGNDATAHEADER);
 333region_data->rdh.iType           = RDH_RECTANGLES;
 334region_data->rdh.nCount          = num_rects;
 335region_data->rdh.nRgnSize        = num_rects*sizeof(RECT);
 336
 337region_data->rdh.rcBound.left    =  64000;
 338region_data->rdh.rcBound.top     =  64000;
 339region_data->rdh.rcBound.right   = -64000;
 340region_data->rdh.rcBound.bottom  = -64000;
 341
 342// find bounds of all clipping regions
 343// 填充 RGNDATAs
 344for (index=0; index<num_rects; index++)
 345    {
 346    // test if the next rectangle unioned with the current bound is larger
 347    if (clip_list[index].left < region_data->rdh.rcBound.left)
 348       region_data->rdh.rcBound.left = clip_list[index].left;
 349
 350    if (clip_list[index].right > region_data->rdh.rcBound.right)
 351       region_data->rdh.rcBound.right = clip_list[index].right;
 352
 353    if (clip_list[index].top < region_data->rdh.rcBound.top)
 354       region_data->rdh.rcBound.top = clip_list[index].top;
 355
 356    if (clip_list[index].bottom > region_data->rdh.rcBound.bottom)
 357       region_data->rdh.rcBound.bottom = clip_list[index].bottom;
 358
 359    }
 // end for index
 360
 361// now we have computed the bounding rectangle region and set up the data
 362// now let's set the clipping list
 363// step 3: 将裁剪序列发送给裁剪器
 364if (FAILED(lpddclipper->SetClipList(region_data, 0)))
 365   {
 366   // release memory and return error
 367   free(region_data);
 368   return(NULL);
 369   }
 // end if
 370
 371// now attach the clipper to the surface
 372// step 4: 将裁减器同表面关联
 373if (FAILED(lpdds->SetClipper(lpddclipper)))
 374   {
 375   // release memory and return error
 376   free(region_data);
 377   return(NULL);
 378   }
 // end if
 379
 380    // FINISHED!!!
 381// all is well, so release memory and send back the pointer to the new clipper
 382free(region_data);
 383return(lpddclipper);
 384
 385}
 // end DDraw_Attach_Clipper
 386
 387///////////////////////////////////////////////////////////   
 388// 用指定颜色填充表面
 389int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color)
 390{
 391DDBLTFX ddbltfx; // this contains the DDBLTFX structure
 392
 393// clear out the structure and set the size field 
 394DDRAW_INIT_STRUCT(ddbltfx);
 395
 396// set the dwfillcolor field to the desired color
 397ddbltfx.dwFillColor = color; 
 398
 399// ready to blt to surface
 400lpdds->Blt(NULL,       // ptr to dest rectangle
 401           NULL,       // ptr to source surface, NA            
 402           NULL,       // ptr to source rectangle, NA
 403           DDBLT_COLORFILL | DDBLT_WAIT,   // fill and wait                   
 404           &ddbltfx);  // ptr to DDBLTFX structure
 405
 406// return success
 407return(1);
 408}
 // end DDraw_Fill_Surface
 409
 410///////////////////////////////////////////////////////////////
 411// 在目标表面特定位置绘制源表面
 412
 413int DDraw_Draw_Surface(LPDIRECTDRAWSURFACE7 source, // source surface to draw
 414                      int x, int y,                 // position to draw at
 415                      int width, int height,        // size of source surface
 416                      LPDIRECTDRAWSURFACE7 dest,    // surface to draw the surface on
 417                      int transparent = 1)          // transparency flag
 418{
 419// draw a bob at the x,y defined in the BOB
 420// on the destination surface defined in dest
 421
 422RECT dest_rect,   // the destination rectangle
 423     source_rect; // the source rectangle                             
 424
 425// fill in the destination rect
 426dest_rect.left   = x;
 427dest_rect.top    = y;
 428dest_rect.right  = x+width-1;
 429dest_rect.bottom = y+height-1;
 430
 431// fill in the source rect
 432source_rect.left    = 0;
 433source_rect.top     = 0;
 434source_rect.right   = width-1;
 435source_rect.bottom  = height-1;
 436
 437// test transparency flag
 438
 439if (transparent)
 440   {
 441   // enable color key blit
 442   // blt to destination surface
 443   if (FAILED(dest->Blt(&dest_rect, source,
 444                     &source_rect,(DDBLT_WAIT | DDBLT_KEYSRC),    // 色彩键设置
 445                     NULL)))
 446           return(0);
 447
 448   }
 // end if
 449else
 450   {
 451   // perform blit without color key
 452   // blt to destination surface
 453   if (FAILED(dest->Blt(&dest_rect, source,
 454                     &source_rect,(DDBLT_WAIT),
 455                     NULL)))
 456           return(0);
 457
 458   }
 // end if
 459
 460// return success
 461return(1);
 462
 463}
 // end DDraw_Draw_Surface
 464
 465///////////////////////////////////////////////////////////////
 466// 将结构体中的位图写入表面
 467// cx, cy 是要拷贝位图内容的起始 行列号
 468int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap,     // bitmap file to scan image data from
 469                      LPDIRECTDRAWSURFACE7 lpdds, // surface to hold data
 470                      int cx, int cy)             // cell to scan image from
 471{
 472// this function extracts a bitmap out of a bitmap file
 473
 474UCHAR *source_ptr,   // working pointers
 475      *dest_ptr;
 476
 477DDSURFACEDESC2 ddsd;  //  direct draw surface description 
 478
 479// get the addr to destination surface memory
 480
 481// set size of the structure
 482ddsd.dwSize = sizeof(ddsd);
 483
 484// lock the display surface
 485lpdds->Lock(NULL,
 486            &ddsd,
 487            DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
 488            NULL);
 489
 490// compute position to start scanning bits from
 491// ddsd.dwWidth , ddsd.dwHeight 是帧子图像的宽度和高度,参数中的
 492// cx,cy指明了第cx行,cy列的子图像,在此将其转换为该帧子图像在原图像
 493// 中的位置
 494cx = cx*(ddsd.dwWidth+1+ 1;
 495cy = cy*(ddsd.dwHeight+1+ 1;
 496// 这两行没用
 497gwidth  = ddsd.dwWidth;
 498gheight = ddsd.dwHeight;
 499
 500// extract bitmap data
 501// 找到欲绘制内容在位图中的起始地址
 502source_ptr = bitmap->buffer + cy*bitmap->bitmapinfoheader.biWidth+cx;
 503
 504// assign a pointer to the memory surface for manipulation
 505// 获得表面指针
 506dest_ptr = (UCHAR *)ddsd.lpSurface;
 507
 508// iterate thru each scanline and copy bitmap
 509// 从位图结构体按行拷贝至表面
 510for (int index_y=0; index_y < ddsd.dwHeight; index_y++)
 511    {
 512    // copy next line of data to destination
 513    memcpy(dest_ptr, source_ptr, ddsd.dwWidth);
 514
 515    // advance pointers
 516    dest_ptr   += (ddsd.lPitch); // (ddsd.dwWidth);
 517    source_ptr += bitmap->bitmapinfoheader.biWidth;
 518    }
 // end for index_y
 519
 520// unlock the surface 
 521lpdds->Unlock(NULL);
 522
 523// return success
 524return(1);
 525
 526}
 // end Scan_Image_Bitmap
 527
 528///////////////////////////////////////////////////////////////
 529// 创建表面
 530LPDIRECTDRAWSURFACE7 DDraw_Create_Surface(int width, int height, int mem_flags, int color_key = 0)
 531{
 532// this function creates an offscreen plain surface
 533
 534DDSURFACEDESC2 ddsd;         // working description
 535LPDIRECTDRAWSURFACE7 lpdds;  // temporary surface
 536    
 537// set to access caps, width, and height
 538memset(&ddsd,0,sizeof(ddsd));
 539ddsd.dwSize  = sizeof(ddsd);
 540// 创建 离屏表面,必须将dwFlags设置为这样
 541ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
 542
 543// set dimensions of the new bitmap surface
 544ddsd.dwWidth  =  width;
 545ddsd.dwHeight =  height;
 546
 547// set surface to offscreen plain
 548// 指明是离屏表面
 549ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | mem_flags;
 550
 551// create the surface
 552if (FAILED(lpdd->CreateSurface(&ddsd,&lpdds,NULL)))
 553   return(NULL);
 554
 555// test if user wants a color key
 556if (color_key >= 0)
 557   {
 558   // set color key to color 0
 559   DDCOLORKEY color_key; // used to set color key
 560   color_key.dwColorSpaceLowValue  = 0;
 561   color_key.dwColorSpaceHighValue = 0;
 562
 563   // now set the color key for source blitting
 564   // 设置色彩键
 565   lpdds->SetColorKey(DDCKEY_SRCBLT, &color_key);
 566   }
 // end if
 567
 568// return surface
 569return(lpdds);
 570}
 // end DDraw_Create_Surface
 571
 572
 573///////////////////////////////////////////////////////////////
 574
 575LRESULT CALLBACK WindowProc(HWND hwnd, 
 576                            UINT msg, 
 577                            WPARAM wparam, 
 578                            LPARAM lparam)
 579{
 580// this is the main message handler of the system
 581PAINTSTRUCT        ps;        // used in WM_PAINT
 582HDC                hdc;    // handle to a device context
 583char buffer[80];        // used to print strings
 584
 585// what is the message 
 586switch(msg)
 587    {    
 588    case WM_CREATE: 
 589        {
 590        // do initialization stuff here
 591        // return success
 592        return(0);
 593        }
 break;
 594   
 595    case WM_PAINT: 
 596        {
 597        // simply validate the window 
 598           hdc = BeginPaint(hwnd,&ps);     
 599        
 600        // end painting
 601        EndPaint(hwnd,&ps);
 602
 603        // return success
 604        return(0);
 605           }
 break;
 606
 607    case WM_DESTROY: 
 608        {
 609
 610        // kill the application, this sends a WM_QUIT message 
 611        PostQuitMessage(0);
 612
 613        // return success
 614        return(0);
 615        }
 break;
 616
 617    default:break;
 618
 619    }
 // end switch
 620
 621// process any messages that we didn't take care of 
 622return (DefWindowProc(hwnd, msg, wparam, lparam));
 623
 624}
 // end WinProc
 625
 626///////////////////////////////////////////////////////////
 627// 在特定位置输出文字
 628int Draw_Text_GDI(char *text, int x,int y,COLORREF color, LPDIRECTDRAWSURFACE7 lpdds)
 629{
 630// this function draws the sent text on the sent surface 
 631// using color index as the color in the palette
 632
 633HDC xdc; // the working dc
 634
 635// get the dc from surface
 636if (FAILED(lpdds->GetDC(&xdc)))
 637   return(0);
 638
 639// set the colors for the text up
 640SetTextColor(xdc,color);
 641
 642// set background mode to transparent so black isn't copied
 643SetBkMode(xdc, TRANSPARENT);
 644
 645// draw the text a
 646TextOut(xdc,x,y,text,strlen(text));
 647
 648// release the dc
 649lpdds->ReleaseDC(xdc);
 650
 651// return success
 652return(1);
 653}
 // end Draw_Text_GDI
 654
 655///////////////////////////////////////////////////////////////
 656
 657int Game_Main(void *parms = NULL, int num_parms = 0)
 658{
 659// this is the main loop of the game, do all your processing
 660// here
 661
 662// lookup for proper walking sequence
 663static int animation_seq[4= {0,1,0,2};
 664
 665int index; // general looping variable
 666
 667// make sure this isn't executed again
 668if (window_closed)
 669   return(0);
 670
 671// for now test if user is hitting ESC and send WM_CLOSE
 672if (KEYDOWN(VK_ESCAPE))
 673   {
 674   PostMessage(main_window_handle,WM_CLOSE,0,0);
 675   window_closed = 1;
 676   }
 // end if
 677
 678// copy background to back buffer
 679DDraw_Draw_Surface(lpddsbackground,0,0, SCREEN_WIDTH,SCREEN_HEIGHT, lpddsback,0);    
 680
 681// move objects around
 682// 移动 Aliens 图像
 683for (index=0; index < 3; index++)
 684    {
 685    // move each object to the right at its given velocity
 686    aliens[index].x++// =aliens[index].velocity;
 687
 688    // test if off screen edge, and wrap around
 689    if (aliens[index].x > SCREEN_WIDTH)
 690       aliens[index].x = - 80;
 691
 692    // animate bot
 693    if (++aliens[index].counter >= (8 - aliens[index].velocity))
 694        {
 695        // reset counter
 696        aliens[index].counter = 0;
 697
 698        // advance to next frame
 699        if (++aliens[index].current_frame > 3)
 700           aliens[index].current_frame = 0;
 701  
 702        }
 // end if
 703
 704    }
 // end for index
 705
 706
 707// draw all the bots
 708for (index=0; index < 3; index++)
 709    {
 710    // draw objects
 711    DDraw_Draw_Surface(aliens[index].frames[animation_seq[aliens[index].current_frame]], 
 712                       aliens[index].x, aliens[index].y,
 713                       72,80,
 714                       lpddsback);
 715
 716    }
 // end for index
 717
 718
 719// flip pages
 720while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT)));
 721
 722// wait a sec
 723Sleep(30);
 724
 725// return success or failure or your own return code here
 726return(1);
 727
 728}
 // end Game_Main
 729
 730////////////////////////////////////////////////////////////
 731
 732int Game_Init(void *parms = NULL, int num_parms = 0)
 733{
 734// this is called once after the initial window is created and
 735// before the main event loop is entered, do all your initialization
 736// here
 737
 738// create IDirectDraw interface 7.0 object and test for error
 739if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
 740   return(0);
 741// set cooperation to full screen
 742if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, 
 743                                      DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | 
 744                                      DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
 745   return(0);
 746
 747// set display mode to 640x480x8
 748if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0)))
 749   return(0);
 750
 751// we need a complex surface system with a primary and backbuffer
 752
 753// clear ddsd and set size
 754DDRAW_INIT_STRUCT(ddsd); 
 755
 756// enable valid fields
 757// 双缓存
 758ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
 759
 760// set the backbuffer count field to 1, use 2 for triple buffering
 761ddsd.dwBackBufferCount = 1;
 762
 763// request a complex, flippable
 764ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
 765
 766// create the primary surface
 767// 创建主表面
 768if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
 769   return(0);
 770
 771// now query for attached surface from the primary surface
 772// 从主表面获得 缓冲表面
 773// this line is needed by the call
 774ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
 775
 776// get the attached back buffer surface
 777if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)))
 778  return(0);
 779
 780// build up the palette data array
 781for (int color=1; color < 255; color++)
 782    {
 783    // fill with random RGB values
 784    palette[color].peRed   = rand()%256;
 785    palette[color].peGreen = rand()%256;
 786    palette[color].peBlue  = rand()%256;
 787
 788    // set flags field to PC_NOCOLLAPSE
 789    palette[color].peFlags = PC_NOCOLLAPSE;
 790    }
 // end for color
 791
 792// now fill in entry 0 and 255 with black and white
 793palette[0].peRed     = 0;
 794palette[0].peGreen   = 0;
 795palette[0].peBlue    = 0;
 796palette[0].peFlags   = PC_NOCOLLAPSE;
 797
 798palette[255].peRed   = 255;
 799palette[255].peGreen = 255;
 800palette[255].peBlue  = 255;
 801palette[255].peFlags = PC_NOCOLLAPSE;
 802
 803// create the palette object
 804if (FAILED(lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | 
 805                                DDPCAPS_INITIALIZE, 
 806                                palette,&lpddpal, NULL)))
 807return(0);
 808
 809// finally attach the palette to the primary surface
 810// 把调色板给主表面
 811if (FAILED(lpddsprimary->SetPalette(lpddpal)))
 812   return(0);
 813
 814// set clipper up on back buffer since that's where well clip
 815// 为后备表面创建并关联裁剪器
 816RECT screen_rect= {0,0,SCREEN_WIDTH-1,SCREEN_HEIGHT-1};
 817lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect);
 818
 819// load the 8-bit image
 820// 载入背景位图
 821if (!Load_Bitmap_File(&bitmap,"alley8.bmp"))
 822   return(0);
 823
 824// load it's palette into directdraw
 825// 将位图的调色板载入 DirectDraw
 826if (FAILED(lpddpal->SetEntries(0,0,MAX_COLORS_PALETTE,bitmap.palette)))
 827   return(0);
 828
 829// clean the surfaces
 830// 用纯色填充 主表面 和 后备表面 ,防止有以前的内容残留
 831DDraw_Fill_Surface(lpddsprimary,0);
 832DDraw_Fill_Surface(lpddsback,0);
 833
 834// create the buffer to hold the background
 835// 为背景图像创建表面
 836lpddsbackground = DDraw_Create_Surface(640,480,0,-1);
 837
 838// copy the background bitmap image to the background surface 
 839// 将背景位图载入背景表面
 840// lock the surface
 841lpddsbackground->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);
 842
 843// get video pointer to primary surfce
 844UCHAR *image_buffer = (UCHAR *)ddsd.lpSurface;       
 845
 846// test if memory is linear
 847if (ddsd.lPitch == SCREEN_WIDTH)
 848   {
 849   // copy memory from double buffer to primary buffer
 850   memcpy((void *)image_buffer, (void *)bitmap.buffer, SCREEN_WIDTH*SCREEN_HEIGHT);
 851   }
 // end if
 852else
 853   // non-linear
 854
 855   // make copy of source and destination addresses
 856   UCHAR *dest_ptr = image_buffer;
 857   UCHAR *src_ptr  = bitmap.buffer;
 858
 859   // memory is non-linear, copy line by line
 860   for (int y=0; y < SCREEN_HEIGHT; y++)
 861       {
 862       // copy line
 863       memcpy((void *)dest_ptr, (void *)src_ptr, SCREEN_WIDTH);
 864
 865       // advance pointers to next line
 866       dest_ptr+=ddsd.lPitch;
 867       src_ptr +=SCREEN_WIDTH;
 868       }
 // end for
 869
 870   }
 // end else
 871
 872// now unlock the primary surface
 873if (FAILED(lpddsbackground->Unlock(NULL)))
 874   return(0);
 875
 876// unload the bitmap file, we no longer need it
 877Unload_Bitmap_File(&bitmap);
 878
 879// seed random number generator
 880// 产生随机数,用来设置 Alien 的速度 速度在2~6之间
 881srand(GetTickCount());
 882
 883// initialize all the aliens
 884
 885// alien on level 1 of complex
 886
 887aliens[0].x              = rand()%SCREEN_WIDTH;
 888aliens[0].y              = 116 - 72;                  
 889aliens[0].velocity       = 2+rand()%4;
 890aliens[0].current_frame  = 0;             
 891aliens[0].counter        = 0;       
 892
 893// alien on level 2 of complex
 894
 895aliens[1].x              = rand()%SCREEN_WIDTH;
 896aliens[1].y              = 246 - 72;                  
 897aliens[1].velocity       = 2+rand()%4;
 898aliens[1].current_frame  = 0;             
 899aliens[1].counter        = 0;  
 900
 901// alien on level 3 of complex
 902
 903aliens[2].x              = rand()%SCREEN_WIDTH;
 904aliens[2].y              = 382 - 72;                  
 905aliens[2].velocity       = 2+rand()%4;
 906aliens[2].current_frame  = 0;             
 907aliens[2].counter        = 0;  
 908
 909// now load the bitmap containing the alien imagery
 910// then scan the images out into the surfaces of alien[0]
 911// and copy then into the other two, be careful of reference counts!
 912// 读入 Alien 的图像
 913// load the 8-bit image
 914if (!Load_Bitmap_File(&bitmap,"dedsp0.bmp"))
 915   return(0);
 916
 917// create each surface and load bits
 918// 为 Alien 的每一帧创建表面,并将对应帧的图像载入表面
 919// 在此 Scan_Image_Bitmap中,第3,第4个参数分别指明了帧图像(机器人动画中一帧的子图像)在 Alien 图像中的 行、列号
 920// 每个机器人的动作由3帧构成
 921for (int index = 0; index < 3; index++)
 922    {
 923    // create surface to hold image
 924    // 每一个帧子图像的大小为 72*80
 925    aliens[0].frames[index] = DDraw_Create_Surface(72,80,0);
 926
 927    // now load bits
 928    Scan_Image_Bitmap(&bitmap,                 // bitmap file to scan image data from
 929                      aliens[0].frames[index], // surface to hold data
 930                      index, 0);               // cell to scan image from    
 931
 932    }
 // end for index
 933
 934// unload the bitmap file, we no longer need it
 935Unload_Bitmap_File(&bitmap);
 936
 937// now for the tricky part. There is no need to create more surfaces with the same
 938// data, so I'm going to copy the surface pointers member for member to each alien
 939// however, be careful, since the reference counts do NOT go up, you still only need
 940// to release() each surface once!
 941// 上面只创建一次表面,拷贝到其他两个 Aliens中
 942for (index = 0; index < 3; index++)
 943    aliens[1].frames[index] = aliens[2].frames[index] = aliens[0].frames[index];
 944
 945// return success or failure or your own return code here
 946return(1);
 947
 948}
 // end Game_Init
 949
 950/////////////////////////////////////////////////////////////
 951
 952int Game_Shutdown(void *parms = NULL, int num_parms = 0)
 953{
 954// this is called after the game is exited and the main event
 955// loop while is exited, do all you cleanup and shutdown here
 956
 957// kill all the surfaces
 958
 959
 960// first the palette
 961if (lpddpal)
 962   {
 963   lpddpal->Release();
 964   lpddpal = NULL;
 965   }
 // end if
 966
 967// now the primary surface
 968if (lpddsprimary)
 969   {
 970   lpddsprimary->Release();
 971   lpddsprimary = NULL;
 972   }
 // end if
 973
 974// now blow away the IDirectDraw4 interface
 975if (lpdd)
 976   {
 977   lpdd->Release();
 978   lpdd = NULL;
 979   }
 // end if
 980
 981// return success or failure or your own return code here
 982return(1);
 983
 984}
 // end Game_Shutdown
 985
 986// WINMAIN ////////////////////////////////////////////////
 987
 988int WINAPI WinMain(    HINSTANCE hinstance,
 989                    HINSTANCE hprevinstance,
 990                    LPSTR lpcmdline,
 991                    int ncmdshow)
 992{
 993
 994WNDCLASSEX winclass; // this will hold the class we create
 995HWND       hwnd;     // generic window handle
 996MSG           msg;         // generic message
 997HDC        hdc;      // graphics device context
 998
 999// first fill in the window class stucture
1000winclass.cbSize         = sizeof(WNDCLASSEX);
1001winclass.style            = CS_DBLCLKS | CS_OWNDC | 
1002                          CS_HREDRAW | CS_VREDRAW;
1003winclass.lpfnWndProc    = WindowProc;
1004winclass.cbClsExtra        = 0;
1005winclass.cbWndExtra        = 0;
1006winclass.hInstance        = hinstance;
1007winclass.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
1008winclass.hCursor        = LoadCursor(NULL, IDC_ARROW); 
1009winclass.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
1010winclass.lpszMenuName    = NULL;
1011winclass.lpszClassName    = WINDOW_CLASS_NAME;
1012winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);
1013
1014// save hinstance in global
1015hinstance_app = hinstance;
1016
1017// register the window class
1018if (!RegisterClassEx(&winclass))
1019    return(0);
1020
1021// create the window
1022if (!(hwnd = CreateWindowEx(NULL,                  // extended style
1023                            WINDOW_CLASS_NAME,     // class
1024                            "DirectDraw 8-Bit Blitting Demo"// title
1025                            WS_POPUP | WS_VISIBLE,
1026                             0,0,      // initial x,y
1027                            SCREEN_WIDTH,SCREEN_HEIGHT,  // initial width, height
1028                            NULL,      // handle to parent 
1029                            NULL,      // handle to menu
1030                            hinstance,// instance of this application
1031                            NULL)))    // extra creation parms
1032return(0);
1033
1034// save main window handle
1035main_window_handle = hwnd;
1036
1037// initialize game here
1038Game_Init();
1039
1040// enter main event loop
1041while(TRUE)
1042    {
1043    // test if there is a message in queue, if so get it
1044    if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
1045       
1046       // test if this is a quit
1047       if (msg.message == WM_QUIT)
1048           break;
1049    
1050       // translate any accelerator keys
1051       TranslateMessage(&msg);
1052
1053       // send the message to the window proc
1054       DispatchMessage(&msg);
1055       }
 // end if
1056    
1057       // main game processing goes here
1058       Game_Main();
1059       
1060    }
 // end while
1061
1062// closedown game here
1063Game_Shutdown();
1064
1065// return to Windows like this
1066return(msg.wParam);
1067
1068}
 // end WinMain
1069
1070///////////////////////////////////////////////////////////
1071
1072

Feedback

# re: 高级DirectDraw和位图图形(3)  回复  更多评论   

2011-03-02 12:01 by wangquan
给我收益非浅,感谢不尽!

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理