|
Posted on 2008-05-26 19:25 cacar 阅读(2032) 评论(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 42 typedef unsigned short USHORT; 43 typedef unsigned short WORD; 44 typedef unsigned char UCHAR; 45 typedef unsigned char BYTE; 46 47 // container structure for bitmaps .BMP file 48 // 用来保存位图的结构体 49 typedef 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 结构体,包含了要在背景上绘制的“外星人”的各帧以及位置、速度等 60 typedef 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 72 int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height); 73 74 int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename); 75 76 int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap); 77 78 int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color); 79 80 int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap, LPDIRECTDRAWSURFACE7 lpdds, int cx,int cy); 81 82 LPDIRECTDRAWSURFACE7 DDraw_Create_Surface(int width, int height, int mem_flags, int color_key); 83 84 int DDraw_Draw_Surface(LPDIRECTDRAWSURFACE7 source, int x, int y, 85 int width, int height, LPDIRECTDRAWSURFACE7 dest, 86 int transparent); 87 88 LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds, 89 int num_rects, 90 LPRECT clip_list); 91 92 int 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 105 HWND main_window_handle = NULL; // globally track main window 106 int window_closed = 0; // tracks if window is closed 107 HINSTANCE hinstance_app = NULL; // globally track hinstance 108 109 // directdraw stuff 110 111 LPDIRECTDRAW7 lpdd = NULL; // dd4 object 112 LPDIRECTDRAWSURFACE7 lpddsprimary = NULL; // dd primary surface 113 LPDIRECTDRAWSURFACE7 lpddsback = NULL; // dd back surface 114 LPDIRECTDRAWPALETTE lpddpal = NULL; // a pointer to the created dd palette 115 LPDIRECTDRAWCLIPPER lpddclipper = NULL; // dd clipper 116 PALETTEENTRY palette[256]; // color palette 117 PALETTEENTRY save_palette[256]; // used to save palettes 118 DDSURFACEDESC2 ddsd; // a direct draw surface description struct 119 DDBLTFX ddbltfx; // used to fill 120 DDSCAPS2 ddscaps; // a direct draw surface capabilities struct 121 HRESULT ddrval; // result back from dd calls 122 DWORD start_clock_count = 0; // used for timing 123 124 BITMAP_FILE bitmap; // holds the bitmap 125 126 ALIEN_OBJ aliens[3]; // 3 aliens, one on each level 127 128 LPDIRECTDRAWSURFACE7 lpddsbackground = NULL;// this will hold the background image 129 130 char buffer[80]; // general printing buffer 131 132 int gwidth = -1; 133 int gheight = -1; 134 135 // FUNCTIONS //////////////////////////////////////////////// 136 // 载入位图文件到结构体 137 int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename) 138  { 139 // this function opens a bitmap file and loads the data into bitmap 140 141 int file_handle, // the file handle 142 index; // looping index 143 144 UCHAR *temp_buffer = NULL; // used to convert 24 bit images to 16 bit 145 OFSTRUCT file_data; // the file data information 146 147 // open the file if it exists 148 if ((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 155 if (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 172 if (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 198 if (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 219 else 220 { 221 // serious problem 222 return(0); 223 224 } // end else 225 226 #if 0 227 // write the file info out 228 printf("\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 242 Flip_Bitmap(bitmap->buffer, 243 bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8), 244 bitmap->bitmapinfoheader.biHeight); 245 246 // return success 247 return(1); 248 249 } // end Load_Bitmap_File 250 251 /**//////////////////////////////////////////////////////////// 252 // 卸载位图文件,释放内存 253 int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap) 254  { 255 // this function releases all memory associated with "bitmap" 256 if (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 267 return(1); 268 269 } // end Unload_Bitmap_File 270 271 /**//////////////////////////////////////////////////////////// 272 //将位图文件上下颠倒~ 273 int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height) 274  { 275 // this function is used to flip bottom-up .BMP images 276 277 UCHAR *buffer; // used to perform the image processing 278 int index; // looping index 279 280 // allocate the temporary buffer 281 if (!(buffer = (UCHAR *)malloc(bytes_per_line*height))) 282 return(0); 283 284 // copy image to work area 285 memcpy(buffer,image,bytes_per_line*height); 286 287 // flip vertically 288 for (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 293 free(buffer); 294 295 // return success 296 return(1); 297 298 } // end Flip_Bitmap 299 300 /**//////////////////////////////////////////////////////////////// 301 //为表面关联裁剪器 302 LPDIRECTDRAWCLIPPER 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 310 int index; // looping var 311 LPDIRECTDRAWCLIPPER lpddclipper; // pointer to the newly created dd clipper 312 LPRGNDATA 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: 生成裁剪器 317 if (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申请空间 325 region_data = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+num_rects*sizeof(RECT)); 326 327 // now copy the rects into region data 328 // 拷贝指定的RECTs到ClipperList,即 RGNDATA 结构体的 Buffer中 329 memcpy(region_data->Buffer, clip_list, sizeof(RECT)*num_rects); 330 331 // set up fields of header 332 region_data->rdh.dwSize = sizeof(RGNDATAHEADER); 333 region_data->rdh.iType = RDH_RECTANGLES; 334 region_data->rdh.nCount = num_rects; 335 region_data->rdh.nRgnSize = num_rects*sizeof(RECT); 336 337 region_data->rdh.rcBound.left = 64000; 338 region_data->rdh.rcBound.top = 64000; 339 region_data->rdh.rcBound.right = -64000; 340 region_data->rdh.rcBound.bottom = -64000; 341 342 // find bounds of all clipping regions 343 // 填充 RGNDATAs 344 for (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: 将裁剪序列发送给裁剪器 364 if (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: 将裁减器同表面关联 373 if (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 382 free(region_data); 383 return(lpddclipper); 384 385 } // end DDraw_Attach_Clipper 386 387 /**//////////////////////////////////////////////////////////// 388 // 用指定颜色填充表面 389 int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color) 390  { 391 DDBLTFX ddbltfx; // this contains the DDBLTFX structure 392 393 // clear out the structure and set the size field 394 DDRAW_INIT_STRUCT(ddbltfx); 395 396 // set the dwfillcolor field to the desired color 397 ddbltfx.dwFillColor = color; 398 399 // ready to blt to surface 400 lpdds->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 407 return(1); 408 } // end DDraw_Fill_Surface 409 410 /**//////////////////////////////////////////////////////////////// 411 // 在目标表面特定位置绘制源表面 412 413 int 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 422 RECT dest_rect, // the destination rectangle 423 source_rect; // the source rectangle 424 425 // fill in the destination rect 426 dest_rect.left = x; 427 dest_rect.top = y; 428 dest_rect.right = x+width-1; 429 dest_rect.bottom = y+height-1; 430 431 // fill in the source rect 432 source_rect.left = 0; 433 source_rect.top = 0; 434 source_rect.right = width-1; 435 source_rect.bottom = height-1; 436 437 // test transparency flag 438 439 if (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 449 else 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 461 return(1); 462 463 } // end DDraw_Draw_Surface 464 465 /**//////////////////////////////////////////////////////////////// 466 // 将结构体中的位图写入表面 467 // cx, cy 是要拷贝位图内容的起始 行列号 468 int 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 474 UCHAR *source_ptr, // working pointers 475 *dest_ptr; 476 477 DDSURFACEDESC2 ddsd; // direct draw surface description 478 479 // get the addr to destination surface memory 480 481 // set size of the structure 482 ddsd.dwSize = sizeof(ddsd); 483 484 // lock the display surface 485 lpdds->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 // 中的位置 494 cx = cx*(ddsd.dwWidth+1) + 1; 495 cy = cy*(ddsd.dwHeight+1) + 1; 496 // 这两行没用 497 gwidth = ddsd.dwWidth; 498 gheight = ddsd.dwHeight; 499 500 // extract bitmap data 501 // 找到欲绘制内容在位图中的起始地址 502 source_ptr = bitmap->buffer + cy*bitmap->bitmapinfoheader.biWidth+cx; 503 504 // assign a pointer to the memory surface for manipulation 505 // 获得表面指针 506 dest_ptr = (UCHAR *)ddsd.lpSurface; 507 508 // iterate thru each scanline and copy bitmap 509 // 从位图结构体按行拷贝至表面 510 for (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 521 lpdds->Unlock(NULL); 522 523 // return success 524 return(1); 525 526 } // end Scan_Image_Bitmap 527 528 /**//////////////////////////////////////////////////////////////// 529 // 创建表面 530 LPDIRECTDRAWSURFACE7 DDraw_Create_Surface(int width, int height, int mem_flags, int color_key = 0) 531  { 532 // this function creates an offscreen plain surface 533 534 DDSURFACEDESC2 ddsd; // working description 535 LPDIRECTDRAWSURFACE7 lpdds; // temporary surface 536 537 // set to access caps, width, and height 538 memset(&ddsd,0,sizeof(ddsd)); 539 ddsd.dwSize = sizeof(ddsd); 540 // 创建 离屏表面,必须将dwFlags设置为这样 541 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; 542 543 // set dimensions of the new bitmap surface 544 ddsd.dwWidth = width; 545 ddsd.dwHeight = height; 546 547 // set surface to offscreen plain 548 // 指明是离屏表面 549 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | mem_flags; 550 551 // create the surface 552 if (FAILED(lpdd->CreateSurface(&ddsd,&lpdds,NULL))) 553 return(NULL); 554 555 // test if user wants a color key 556 if (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 569 return(lpdds); 570 } // end DDraw_Create_Surface 571 572 573 /**//////////////////////////////////////////////////////////////// 574 575 LRESULT CALLBACK WindowProc(HWND hwnd, 576 UINT msg, 577 WPARAM wparam, 578 LPARAM lparam) 579  { 580 // this is the main message handler of the system 581 PAINTSTRUCT ps; // used in WM_PAINT 582 HDC hdc; // handle to a device context 583 char buffer[80]; // used to print strings 584 585 // what is the message 586 switch(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 622 return (DefWindowProc(hwnd, msg, wparam, lparam)); 623 624 } // end WinProc 625 626 /**//////////////////////////////////////////////////////////// 627 // 在特定位置输出文字 628 int 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 633 HDC xdc; // the working dc 634 635 // get the dc from surface 636 if (FAILED(lpdds->GetDC(&xdc))) 637 return(0); 638 639 // set the colors for the text up 640 SetTextColor(xdc,color); 641 642 // set background mode to transparent so black isn't copied 643 SetBkMode(xdc, TRANSPARENT); 644 645 // draw the text a 646 TextOut(xdc,x,y,text,strlen(text)); 647 648 // release the dc 649 lpdds->ReleaseDC(xdc); 650 651 // return success 652 return(1); 653 } // end Draw_Text_GDI 654 655 /**//////////////////////////////////////////////////////////////// 656 657 int 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 663 static int animation_seq[4] = {0,1,0,2}; 664 665 int index; // general looping variable 666 667 // make sure this isn't executed again 668 if (window_closed) 669 return(0); 670 671 // for now test if user is hitting ESC and send WM_CLOSE 672 if (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 679 DDraw_Draw_Surface(lpddsbackground,0,0, SCREEN_WIDTH,SCREEN_HEIGHT, lpddsback,0); 680 681 // move objects around 682 // 移动 Aliens 图像 683 for (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 708 for (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 720 while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT))); 721 722 // wait a sec 723 Sleep(30); 724 725 // return success or failure or your own return code here 726 return(1); 727 728 } // end Game_Main 729 730 /**///////////////////////////////////////////////////////////// 731 732 int 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 739 if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL))) 740 return(0); 741 // set cooperation to full screen 742 if (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 748 if (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 754 DDRAW_INIT_STRUCT(ddsd); 755 756 // enable valid fields 757 // 双缓存 758 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; 759 760 // set the backbuffer count field to 1, use 2 for triple buffering 761 ddsd.dwBackBufferCount = 1; 762 763 // request a complex, flippable 764 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; 765 766 // create the primary surface 767 // 创建主表面 768 if (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 774 ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; 775 776 // get the attached back buffer surface 777 if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback))) 778 return(0); 779 780 // build up the palette data array 781 for (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 793 palette[0].peRed = 0; 794 palette[0].peGreen = 0; 795 palette[0].peBlue = 0; 796 palette[0].peFlags = PC_NOCOLLAPSE; 797 798 palette[255].peRed = 255; 799 palette[255].peGreen = 255; 800 palette[255].peBlue = 255; 801 palette[255].peFlags = PC_NOCOLLAPSE; 802 803 // create the palette object 804 if (FAILED(lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | 805 DDPCAPS_INITIALIZE, 806 palette,&lpddpal, NULL))) 807 return(0); 808 809 // finally attach the palette to the primary surface 810 // 把调色板给主表面 811 if (FAILED(lpddsprimary->SetPalette(lpddpal))) 812 return(0); 813 814 // set clipper up on back buffer since that's where well clip 815 // 为后备表面创建并关联裁剪器 816 RECT screen_rect= {0,0,SCREEN_WIDTH-1,SCREEN_HEIGHT-1}; 817 lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect); 818 819 // load the 8-bit image 820 // 载入背景位图 821 if (!Load_Bitmap_File(&bitmap,"alley8.bmp")) 822 return(0); 823 824 // load it's palette into directdraw 825 // 将位图的调色板载入 DirectDraw 826 if (FAILED(lpddpal->SetEntries(0,0,MAX_COLORS_PALETTE,bitmap.palette))) 827 return(0); 828 829 // clean the surfaces 830 // 用纯色填充 主表面 和 后备表面 ,防止有以前的内容残留 831 DDraw_Fill_Surface(lpddsprimary,0); 832 DDraw_Fill_Surface(lpddsback,0); 833 834 // create the buffer to hold the background 835 // 为背景图像创建表面 836 lpddsbackground = DDraw_Create_Surface(640,480,0,-1); 837 838 // copy the background bitmap image to the background surface 839 // 将背景位图载入背景表面 840 // lock the surface 841 lpddsbackground->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL); 842 843 // get video pointer to primary surfce 844 UCHAR *image_buffer = (UCHAR *)ddsd.lpSurface; 845 846 // test if memory is linear 847 if (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 852 else 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 873 if (FAILED(lpddsbackground->Unlock(NULL))) 874 return(0); 875 876 // unload the bitmap file, we no longer need it 877 Unload_Bitmap_File(&bitmap); 878 879 // seed random number generator 880 // 产生随机数,用来设置 Alien 的速度 速度在2~6之间 881 srand(GetTickCount()); 882 883 // initialize all the aliens 884 885 // alien on level 1 of complex 886 887 aliens[0].x = rand()%SCREEN_WIDTH; 888 aliens[0].y = 116 - 72; 889 aliens[0].velocity = 2+rand()%4; 890 aliens[0].current_frame = 0; 891 aliens[0].counter = 0; 892 893 // alien on level 2 of complex 894 895 aliens[1].x = rand()%SCREEN_WIDTH; 896 aliens[1].y = 246 - 72; 897 aliens[1].velocity = 2+rand()%4; 898 aliens[1].current_frame = 0; 899 aliens[1].counter = 0; 900 901 // alien on level 3 of complex 902 903 aliens[2].x = rand()%SCREEN_WIDTH; 904 aliens[2].y = 382 - 72; 905 aliens[2].velocity = 2+rand()%4; 906 aliens[2].current_frame = 0; 907 aliens[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 914 if (!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帧构成 921 for (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 935 Unload_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中 942 for (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 946 return(1); 947 948 } // end Game_Init 949 950 /**////////////////////////////////////////////////////////////// 951 952 int 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 961 if (lpddpal) 962 { 963 lpddpal->Release(); 964 lpddpal = NULL; 965 } // end if 966 967 // now the primary surface 968 if (lpddsprimary) 969 { 970 lpddsprimary->Release(); 971 lpddsprimary = NULL; 972 } // end if 973 974 // now blow away the IDirectDraw4 interface 975 if (lpdd) 976 { 977 lpdd->Release(); 978 lpdd = NULL; 979 } // end if 980 981 // return success or failure or your own return code here 982 return(1); 983 984 } // end Game_Shutdown 985 986 // WINMAIN //////////////////////////////////////////////// 987 988 int WINAPI WinMain( HINSTANCE hinstance, 989 HINSTANCE hprevinstance, 990 LPSTR lpcmdline, 991 int ncmdshow) 992  { 993 994 WNDCLASSEX winclass; // this will hold the class we create 995 HWND hwnd; // generic window handle 996 MSG msg; // generic message 997 HDC hdc; // graphics device context 998 999 // first fill in the window class stucture 1000 winclass.cbSize = sizeof(WNDCLASSEX); 1001 winclass.style = CS_DBLCLKS | CS_OWNDC | 1002 CS_HREDRAW | CS_VREDRAW; 1003 winclass.lpfnWndProc = WindowProc; 1004 winclass.cbClsExtra = 0; 1005 winclass.cbWndExtra = 0; 1006 winclass.hInstance = hinstance; 1007 winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); 1008 winclass.hCursor = LoadCursor(NULL, IDC_ARROW); 1009 winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 1010 winclass.lpszMenuName = NULL; 1011 winclass.lpszClassName = WINDOW_CLASS_NAME; 1012 winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 1013 1014 // save hinstance in global 1015 hinstance_app = hinstance; 1016 1017 // register the window class 1018 if (!RegisterClassEx(&winclass)) 1019 return(0); 1020 1021 // create the window 1022 if (!(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 1032 return(0); 1033 1034 // save main window handle 1035 main_window_handle = hwnd; 1036 1037 // initialize game here 1038 Game_Init(); 1039 1040 // enter main event loop 1041 while(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 1063 Game_Shutdown(); 1064 1065 // return to Windows like this 1066 return(msg.wParam); 1067 1068 } // end WinMain 1069 1070 /**////////////////////////////////////////////////////////////1071 1072
Feedback
# re: 高级DirectDraw和位图图形(3) 回复 更多评论
2011-03-02 12:01 by
给我收益非浅,感谢不尽!
|