|
Posted on 2008-05-26 19:25 cacar 阅读(2010) 评论(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
给我收益非浅,感谢不尽!
|