windows编程大师技巧第二版学习笔记——开发环境的搭建
2015-10-12 08:59
417 查看
先说一下学习这本书的初衷,现在的游戏开发一般都会直接使用游戏引擎来渲染和组织一些功能,笔者以前只用过u3d做过一次cs场景类的程序(严格来说不是游戏。。。)但是作为被封装好的引擎,作为初学者不能更好的理解引擎内部的运行机制,所以我打算用很久的空余时间来学习这本书。不使用引擎,自己做渲染等,这是一个挑战,但相信对长远发展会有帮助。
大师的代码最好使用dx7sdk,因为这本书的许多程序需要调用d3dim.lib直接模式(或立即模式)导入库,他是D3D immediatel mode使用的LIB,而在dx8.0(包括8.0)的以上版本取消了这种区别,也就是取消了这个库,所以在vs2010中会提示缺少d3dim.lib库。
所以推荐使用版本
dx7sdk-7001
编译器这本书使用的是vc++6.0,但是现在都是vc有点老了,所以我使用了vs2010,话说我现在才知道微软以前的编译器叫vc,在6.0之后的版本就开始叫vs了。。
这次主要的目标就是在vs2010上搭建我们的开发环境。
开始:
首先安装dx7sdk-7001
选择好使用的路径,点击unzip就可以了,实际上dx7.0作为很古老的版本,我们使用的也仅仅是它的一些include,lib文件。
然后在vs2010中配置dx环境
打开vs2010新建一个空的win32项目
然后右键点击这个项目
选择属性
在配置属性里面
选择vc++目录,我们需要修改的是第二行的包含目录和库目录。
我这里把刚才安装的dx7.0放在了d盘,以此为例。
包含目录修改成:
$(IncludePath);D:\dx7sdk-700.1\include
注意一定要把$(IncludePath);(原路径)放在最前面,手动修改的时候是默认在后面的。如果放在前面会出现很严重的程序错误。至少vs2010是这么不智能的。。。
库目录修改成
$(LibraryPath);D:\dx7sdk-700.1\lib;D:\dx7sdk-700.1\lib\borland
这三个路径同样需要把$(LibraryPath);这个原路径放在最前面,稍微提及一下dx7.0的borland产品,在使用声音等处理的时候还是加上这个库,他在dx7.0中的lib文件中的一个子文件。
修改完之后点击应用即可。
做完这些并不可以,还需要修改连接器的lib
同样是选择工程的右键属性点击链接器,选择输入属性,然后我们会看到附加依赖值这一项
点击编辑一项之后
我们需要添加的项目是
ddraw.lib
dinput.lib
dinput8.lib
dsound.lib
d3dim.lib
dxguid.lib
winmm.lib
这几项,d3dim.lib是dx7.0特有的文件,所以推荐使用dx7.0不然在本书的大多程序会报错。
修改完这些之后,大功告成,开始我们的开发之旅把。
第一个跑起来的游戏就从打砖块开始把:(因为没有引擎所以使用了blackbox.h进行渲染)
大师的代码最好使用dx7sdk,因为这本书的许多程序需要调用d3dim.lib直接模式(或立即模式)导入库,他是D3D immediatel mode使用的LIB,而在dx8.0(包括8.0)的以上版本取消了这种区别,也就是取消了这个库,所以在vs2010中会提示缺少d3dim.lib库。
所以推荐使用版本
dx7sdk-7001
编译器这本书使用的是vc++6.0,但是现在都是vc有点老了,所以我使用了vs2010,话说我现在才知道微软以前的编译器叫vc,在6.0之后的版本就开始叫vs了。。
这次主要的目标就是在vs2010上搭建我们的开发环境。
开始:
首先安装dx7sdk-7001
选择好使用的路径,点击unzip就可以了,实际上dx7.0作为很古老的版本,我们使用的也仅仅是它的一些include,lib文件。
然后在vs2010中配置dx环境
打开vs2010新建一个空的win32项目
然后右键点击这个项目
选择属性
在配置属性里面
选择vc++目录,我们需要修改的是第二行的包含目录和库目录。
我这里把刚才安装的dx7.0放在了d盘,以此为例。
包含目录修改成:
$(IncludePath);D:\dx7sdk-700.1\include
注意一定要把$(IncludePath);(原路径)放在最前面,手动修改的时候是默认在后面的。如果放在前面会出现很严重的程序错误。至少vs2010是这么不智能的。。。
库目录修改成
$(LibraryPath);D:\dx7sdk-700.1\lib;D:\dx7sdk-700.1\lib\borland
这三个路径同样需要把$(LibraryPath);这个原路径放在最前面,稍微提及一下dx7.0的borland产品,在使用声音等处理的时候还是加上这个库,他在dx7.0中的lib文件中的一个子文件。
修改完之后点击应用即可。
做完这些并不可以,还需要修改连接器的lib
同样是选择工程的右键属性点击链接器,选择输入属性,然后我们会看到附加依赖值这一项
点击编辑一项之后
我们需要添加的项目是
ddraw.lib
dinput.lib
dinput8.lib
dsound.lib
d3dim.lib
dxguid.lib
winmm.lib
这几项,d3dim.lib是dx7.0特有的文件,所以推荐使用dx7.0不然在本书的大多程序会报错。
修改完这些之后,大功告成,开始我们的开发之旅把。
第一个跑起来的游戏就从打砖块开始把:(因为没有引擎所以使用了blackbox.h进行渲染)
// FREAKOUT.CPP - break game demo // INCLUDES /////////////////////////////////////////////////// #define WIN32_LEAN_AND_MEAN // include all macros #define INITGUID // include all GUIDs #include <windows.h> // include important windows stuff #include <windowsx.h> #include <mmsystem.h> #include <iostream> // include important C/C++ stuff #include <conio.h> #include <stdlib.h> #include <malloc.h> #include <memory.h> #include <string.h> #include <stdarg.h> #include <stdio.h> #include <math.h> #include <io.h> #include <fcntl.h> #include <ddraw.h> // directX includes #include "blackbox.h" // game library includes // DEFINES //////////////////////////////////////////////////// // defines for windows #define WINDOW_CLASS_NAME "WIN3DCLASS" // class name #define WINDOW_WIDTH 640 // size of window #define WINDOW_HEIGHT 480 // states for game loop #define GAME_STATE_INIT 0 #define GAME_STATE_START_LEVEL 1 #define GAME_STATE_RUN 2 #define GAME_STATE_SHUTDOWN 3 #define GAME_STATE_EXIT 4 // block defines #define NUM_BLOCK_ROWS 6 #define NUM_BLOCK_COLUMNS 8 #define BLOCK_WIDTH 64 #define BLOCK_HEIGHT 16 #define BLOCK_ORIGIN_X 8 #define BLOCK_ORIGIN_Y 8 #define BLOCK_X_GAP 80 #define BLOCK_Y_GAP 32 // paddle defines #define PADDLE_START_X (SCREEN_WIDTH/2 - 16) #define PADDLE_START_Y (SCREEN_HEIGHT - 32); #define PADDLE_WIDTH 32 #define PADDLE_HEIGHT 8 #define PADDLE_COLOR 191 // ball defines #define BALL_START_Y (SCREEN_HEIGHT/2) #define BALL_SIZE 4 // PROTOTYPES ///////////////////////////////////////////////// // game console int Game_Init(void *parms=NULL); int Game_Shutdown(void *parms=NULL); int Game_Main(void *parms=NULL); // GLOBALS //////////////////////////////////////////////////// HWND main_window_handle = NULL; // save the window handle HINSTANCE main_instance = NULL; // save the instance int game_state = GAME_STATE_INIT; // starting state int paddle_x = 0, paddle_y = 0; // tracks position of paddle int ball_x = 0, ball_y = 0; // tracks position of ball int ball_dx = 0, ball_dy = 0; // velocity of ball int score = 0; // the score int level = 1; // the current level int blocks_hit = 0; // tracks number of blocks hit // this contains the game grid data UCHAR blocks[NUM_BLOCK_ROWS][NUM_BLOCK_COLUMNS]; // FUNCTIONS ////////////////////////////////////////////////// LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // this is the main message handler of the system PAINTSTRUCT ps; // used in WM_PAINT HDC hdc; // handle to a device context // what is the message switch(msg) { case WM_CREATE: { // do initialization stuff here return(0); } break; case WM_PAINT: { // start painting hdc = BeginPaint(hwnd,&ps); // the window is now validated // end painting EndPaint(hwnd,&ps); return(0); } break; case WM_DESTROY: { // kill the application PostQuitMessage(0); return(0); } break; default:break; } // end switch // process any messages that we didn't take care of return (DefWindowProc(hwnd, msg, wparam, lparam)); } // end WinProc // WINMAIN //////////////////////////////////////////////////// int WINAPI WinMain( HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) { // this is the winmain function WNDCLASS winclass; // this will hold the class we create HWND hwnd; // generic window handle MSG msg; // generic message HDC hdc; // generic dc PAINTSTRUCT ps; // generic paintstruct // first fill in the window class stucture winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; winclass.lpfnWndProc = WindowProc; winclass.cbClsExtra = 0; winclass.cbWndExtra = 0; winclass.hInstance = hinstance; winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); winclass.hCursor = LoadCursor(NULL, IDC_ARROW); winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); winclass.lpszMenuName = NULL; winclass.lpszClassName = WINDOW_CLASS_NAME; // register the window class if (!RegisterClass(&winclass)) return(0); // create the window, note the use of WS_POPUP if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class "WIN3D Game Console", // title WS_POPUP | WS_VISIBLE, 0,0, // initial x,y GetSystemMetrics(SM_CXSCREEN), // intial width GetSystemMetrics(SM_CYSCREEN), // initial height NULL, // handle to parent NULL, // handle to menu hinstance,// instance NULL))) // creation parms return(0); // hide mouse ShowCursor(FALSE); // save the window handle and instance in a global main_window_handle = hwnd; main_instance = hinstance; // perform all game console specific initialization Game_Init(); // enter main event loop while(1) { if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { // test if this is a quit if (msg.message == WM_QUIT) break; // translate any accelerator keys TranslateMessage(&msg); // send the message to the window proc DispatchMessage(&msg); } // end if // main game processing goes here Game_Main(); } // end while // shutdown game and release all resources Game_Shutdown(); // show mouse ShowCursor(TRUE); // return to Windows like this return(msg.wParam); } // end WinMain // T3DX GAME PROGRAMMING CONSOLE FUNCTIONS //////////////////// int Game_Init(void *parms) { // this function is where you do all the initialization // for your game // return success return(1); } // end Game_Init /////////////////////////////////////////////////////////////// int Game_Shutdown(void *parms) { // this function is where you shutdown your game and // release all resources that you allocated // return success return(1); } // end Game_Shutdown /////////////////////////////////////////////////////////////// void Init_Blocks(void) { // initialize the block field for (int row=0; row < NUM_BLOCK_ROWS; row++) for (int col=0; col < NUM_BLOCK_COLUMNS; col++) blocks[row][col] = row*16+col*3+16; } // end Init_Blocks /////////////////////////////////////////////////////////////// void Draw_Blocks(void) { // this function draws all the blocks in row major form int x1 = BLOCK_ORIGIN_X, // used to track current position y1 = BLOCK_ORIGIN_Y; // draw all the blocks for (int row=0; row < NUM_BLOCK_ROWS; row++) { // reset column position x1 = BLOCK_ORIGIN_X; // draw this row of blocks for (int col=0; col < NUM_BLOCK_COLUMNS; col++) { // draw next block (if there is one) if (blocks[row][col]!=0) { // draw block Draw_Rectangle(x1-4,y1+4, x1+BLOCK_WIDTH-4,y1+BLOCK_HEIGHT+4,0); Draw_Rectangle(x1,y1,x1+BLOCK_WIDTH, y1+BLOCK_HEIGHT,blocks[row][col]); } // end if // advance column position x1+=BLOCK_X_GAP; } // end for col // advance to next row position y1+=BLOCK_Y_GAP; } // end for row } // end Draw_Blocks /////////////////////////////////////////////////////////////// void Process_Ball(void) { // this function tests if the ball has hit a block or the paddle // if so, the ball is bounced and the block is removed from // the playfield note: very cheesy collision algorithm :) // first test for ball block collisions // the algorithm basically tests the ball against each // block's bounding box this is inefficient, but easy to // implement, later we'll see a better way int x1 = BLOCK_ORIGIN_X, // current rendering position y1 = BLOCK_ORIGIN_Y; int ball_cx = ball_x+(BALL_SIZE/2), // computer center of ball ball_cy = ball_y+(BALL_SIZE/2); // test of the ball has hit the paddle if (ball_y > (SCREEN_HEIGHT/2) && ball_dy > 0) { // extract leading edge of ball int x = ball_x+(BALL_SIZE/2); int y = ball_y+(BALL_SIZE/2); // test for collision with paddle if ((x >= paddle_x && x <= paddle_x+PADDLE_WIDTH) && (y >= paddle_y && y <= paddle_y+PADDLE_HEIGHT)) { // reflect ball ball_dy=-ball_dy; // push ball out of paddle since it made contact ball_y+=ball_dy; // add a little english to ball based on motion of paddle if (KEY_DOWN(VK_RIGHT)) ball_dx-=(rand()%3); else if (KEY_DOWN(VK_LEFT)) ball_dx+=(rand()%3); else ball_dx+=(-1+rand()%3); // test if there are no blocks, if so send a message // to game loop to start another level if (blocks_hit >= (NUM_BLOCK_ROWS*NUM_BLOCK_COLUMNS)) { game_state = GAME_STATE_START_LEVEL; level++; } // end if // make a little noise MessageBeep(MB_OK); // return return; } // end if } // end if // now scan thru all the blocks and see of ball hit blocks for (int row=0; row < NUM_BLOCK_ROWS; row++) { // reset column position x1 = BLOCK_ORIGIN_X; // scan this row of blocks for (int col=0; col < NUM_BLOCK_COLUMNS; col++) { // if there is a block here then test it against ball if (blocks[row][col]!=0) { // test ball against bounding box of block if ((ball_cx > x1) && (ball_cx < x1+BLOCK_WIDTH) && (ball_cy > y1) && (ball_cy < y1+BLOCK_HEIGHT)) { // remove the block blocks[row][col] = 0; // increment global block counter, so we know // when to start another level up blocks_hit++; // bounce the ball ball_dy=-ball_dy; // add a little english ball_dx+=(-1+rand()%3); // make a little noise MessageBeep(MB_OK); // add some points score+=5*(level+(abs(ball_dx))); // that's it -- no more block return; } // end if } // end if // advance column position x1+=BLOCK_X_GAP; } // end for col // advance to next row position y1+=BLOCK_Y_GAP; } // end for row } // end Process_Ball /////////////////////////////////////////////////////////////// int Game_Main(void *parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! char buffer[80]; // used to print text // what state is the game in? if (game_state == GAME_STATE_INIT) { // initialize everything here graphics DD_Init(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP); // seed the random number generator // so game is different each play srand(Start_Clock()); // set the paddle position here to the middle bottom paddle_x = PADDLE_START_X; paddle_y = PADDLE_START_Y; // set ball position and velocity ball_x = 8+rand()%(SCREEN_WIDTH-16); ball_y = BALL_START_Y; ball_dx = -4 + rand()%(8+1); ball_dy = 6 + rand()%2; // transition to start level state game_state = GAME_STATE_START_LEVEL; } // end if //////////////////////////////////////////////////////////////// else if (game_state == GAME_STATE_START_LEVEL) { // get a new level ready to run // initialize the blocks Init_Blocks(); // reset block counter blocks_hit = 0; // transition to run state game_state = GAME_STATE_RUN; } // end if /////////////////////////////////////////////////////////////// else if (game_state == GAME_STATE_RUN) { // start the timing clock Start_Clock(); // clear drawing surface for the next frame of animation Draw_Rectangle(0,0,SCREEN_WIDTH-1, SCREEN_HEIGHT-1,200); // move the paddle if (KEY_DOWN(VK_RIGHT)) { // move paddle to right paddle_x+=8; // make sure paddle doesn't go off screen if (paddle_x > (SCREEN_WIDTH-PADDLE_WIDTH)) paddle_x = SCREEN_WIDTH-PADDLE_WIDTH; } // end if else if (KEY_DOWN(VK_LEFT)) { // move paddle to right paddle_x-=8; // make sure paddle doesn't go off screen if (paddle_x < 0) paddle_x = 0; } // end if // draw blocks Draw_Blocks(); // move the ball ball_x+=ball_dx; ball_y+=ball_dy; // keep ball on screen, if the ball hits the edge of // screen then bounce it by reflecting its velocity if (ball_x > (SCREEN_WIDTH - BALL_SIZE) || ball_x < 0) { // reflect x-axis velocity ball_dx=-ball_dx; // update position ball_x+=ball_dx; } // end if // now y-axis if (ball_y < 0) { // reflect y-axis velocity ball_dy=-ball_dy; // update position ball_y+=ball_dy; } // end if else // penalize player for missing the ball if (ball_y > (SCREEN_HEIGHT - BALL_SIZE)) { // reflect y-axis velocity ball_dy=-ball_dy; // update position ball_y+=ball_dy; // minus the score score-=100; } // end if // next watch out for ball velocity getting out of hand if (ball_dx > 8) ball_dx = 8; else if (ball_dx < -8) ball_dx = -8; // test if ball hit any blocks or the paddle Process_Ball(); // draw the paddle and shadow Draw_Rectangle(paddle_x-8, paddle_y+8, paddle_x+PADDLE_WIDTH-8, paddle_y+PADDLE_HEIGHT+8,0); Draw_Rectangle(paddle_x, paddle_y, paddle_x+PADDLE_WIDTH, paddle_y+PADDLE_HEIGHT,PADDLE_COLOR); // draw the ball Draw_Rectangle(ball_x-4, ball_y+4, ball_x+BALL_SIZE-4, ball_y+BALL_SIZE+4, 0); Draw_Rectangle(ball_x, ball_y, ball_x+BALL_SIZE, ball_y+BALL_SIZE, 255); // draw the info sprintf(buffer,"F R E A K O U T Score %d Level %d",score,level); Draw_Text_GDI(buffer, 8,SCREEN_HEIGHT-16, 127); // flip the surfaces DD_Flip(); // sync to 33ish fps Wait_Clock(30); // check of user is trying to exit if (KEY_DOWN(VK_ESCAPE)) { // send message to windows to exit PostMessage(main_window_handle, WM_DESTROY,0,0); // set exit state game_state = GAME_STATE_SHUTDOWN; } // end if } // end if /////////////////////////////////////////////////////////////// else if (game_state == GAME_STATE_SHUTDOWN) { // in this state shut everything down and release resources DD_Shutdown(); // switch to exit state game_state = GAME_STATE_EXIT; } // end if // return success return(1); } // end Game_Main ///////////////////////////////////////////////////////////////
// BLACKBOX.CPP - Game Engine // INCLUDES /////////////////////////////////////////////////// #define WIN32_LEAN_AND_MEAN // make sure all macros are included // 添加这句,告诉链接器链接这个lib文件 #include <windows.h> // include important windows stuff #include <windowsx.h> #include <mmsystem.h> #include <iostream> // include important C/C++ stuff #include <conio.h> #include <stdlib.h> #include <malloc.h> #include <memory.h> #include <string.h> #include <stdarg.h> #include <stdio.h> #include <math.h> #include <io.h> #include <fcntl.h> #include <ddraw.h> // directX includes #include "blackbox.h" // game library includes // DEFINES //////////////////////////////////////////////////// // TYPES ////////////////////////////////////////////////////// // PROTOTYPES ///////////////////////////////////////////////// // EXTERNALS ////////////////////////////////////////////////// extern HWND main_window_handle; // save the window handle extern HINSTANCE main_instance; // save the instance // GLOBALS //////////////////////////////////////////////////// LPDIRECTDRAW7 lpdd = NULL; // dd object LPDIRECTDRAWSURFACE7 lpddsprimary = NULL; // dd primary surface LPDIRECTDRAWSURFACE7 lpddsback = NULL; // dd back surface LPDIRECTDRAWPALETTE lpddpal = NULL; // a pointer to the created dd palette LPDIRECTDRAWCLIPPER lpddclipper = NULL; // dd clipper PALETTEENTRY palette[256]; // color palette PALETTEENTRY save_palette[256]; // used to save palettes DDSURFACEDESC2 ddsd; // a direct draw surface description struct DDBLTFX ddbltfx; // used to fill DDSCAPS2 ddscaps; // a direct draw surface capabilities struct HRESULT ddrval; // result back from dd calls DWORD start_clock_count = 0; // used for timing // these defined the general clipping rectangle int min_clip_x = 0, // clipping rectangle max_clip_x = SCREEN_WIDTH-1, min_clip_y = 0, max_clip_y = SCREEN_HEIGHT-1; // these are overwritten globally by DD_Init() int screen_width = SCREEN_WIDTH, // width of screen screen_height = SCREEN_HEIGHT, // height of screen screen_bpp = SCREEN_BPP; // bits per pixel // FUNCTIONS ////////////////////////////////////////////////// int DD_Init(int width, int height, int bpp) { // this function initializes directdraw int index; // looping variable // create object and test for error if (DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)!=DD_OK) return(0); // set cooperation level to windowed mode normal if (lpdd->SetCooperativeLevel(main_window_handle, DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)!=DD_OK) return(0); // set the display mode if (lpdd->SetDisplayMode(width,height,bpp,0,0)!=DD_OK) return(0); // set globals screen_height = height; screen_width = width; screen_bpp = bpp; // Create the primary surface memset(&ddsd,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; // we need to let dd know that we want a complex // flippable surface structure, set flags for that ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; // set the backbuffer count to 1 ddsd.dwBackBufferCount = 1; // create the primary surface lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL); // query for the backbuffer i.e the secondary surface ddscaps.dwCaps = DDSCAPS_BACKBUFFER; lpddsprimary->GetAttachedSurface(&ddscaps,&lpddsback); // create and attach palette // create palette data // clear all entries defensive programming memset(palette,0,256*sizeof(PALETTEENTRY)); // create a R,G,B,GR gradient palette for (index=0; index < 256; index++) { // set each entry if (index < 64) palette[index].peRed = index*4; else // shades of green if (index >= 64 && index < 128) palette[index].peGreen = (index-64)*4; else // shades of blue if (index >= 128 && index < 192) palette[index].peBlue = (index-128)*4; else // shades of grey if (index >= 192 && index < 256) palette[index].peRed = palette[index].peGreen = palette[index].peBlue = (index-192)*4; // set flags palette[index].peFlags = PC_NOCOLLAPSE; } // end for index // now create the palette object if (lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_INITIALIZE | DDPCAPS_ALLOW256, palette,&lpddpal,NULL)!=DD_OK) return(0); // attach the palette to the primary if (lpddsprimary->SetPalette(lpddpal)!=DD_OK) return(0); // clear out both primary and secondary surfaces DD_Fill_Surface(lpddsprimary,0); DD_Fill_Surface(lpddsback,0); // attach a clipper to the screen RECT screen_rect = {0,0,screen_width,screen_height}; lpddclipper = DD_Attach_Clipper(lpddsback,1,&screen_rect); // return success return(1); } // end DD_Init /////////////////////////////////////////////////////////////// int DD_Shutdown(void) { // this function release all the resources directdraw // allocated, mainly to com objects // release the clipper first if (lpddclipper) lpddclipper->Release(); // release the palette if (lpddpal) lpddpal->Release(); // release the secondary surface if (lpddsback) lpddsback->Release(); // release the primary surface if (lpddsprimary) lpddsprimary->Release(); // finally, the main dd object if (lpdd) lpdd->Release(); // return success return(1); } // end DD_Shutdown /////////////////////////////////////////////////////////////// LPDIRECTDRAWCLIPPER DD_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds, int num_rects, LPRECT clip_list) { // this function creates a clipper from the sent clip list and attaches // it to the sent surface int index; // looping var LPDIRECTDRAWCLIPPER lpddclipper; // pointer to the newly created dd clipper LPRGNDATA region_data; // pointer to the region data that contains // the header and clip list // first create the direct draw clipper if ((lpdd->CreateClipper(0,&lpddclipper,NULL))!=DD_OK) return(NULL); // now create the clip list from the sent data // first allocate memory for region data region_data = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+num_rects*sizeof(RECT)); // now copy the rects into region data memcpy(region_data->Buffer, clip_list, sizeof(RECT)*num_rects); // set up fields of header region_data->rdh.dwSize = sizeof(RGNDATAHEADER); region_data->rdh.iType = RDH_RECTANGLES; region_data->rdh.nCount = num_rects; region_data->rdh.nRgnSize = num_rects*sizeof(RECT); region_data->rdh.rcBound.left = 64000; region_data->rdh.rcBound.top = 64000; region_data->rdh.rcBound.right = -64000; region_data->rdh.rcBound.bottom = -64000; // find bounds of all clipping regions for (index=0; index<num_rects; index++) { // test if the next rectangle unioned with the current bound is larger if (clip_list[index].left < region_data->rdh.rcBound.left) region_data->rdh.rcBound.left = clip_list[index].left; if (clip_list[index].right > region_data->rdh.rcBound.right) region_data->rdh.rcBound.right = clip_list[index].right; if (clip_list[index].top < region_data->rdh.rcBound.top) region_data->rdh.rcBound.top = clip_list[index].top; if (clip_list[index].bottom > region_data->rdh.rcBound.bottom) region_data->rdh.rcBound.bottom = clip_list[index].bottom; } // end for index // now we have computed the bounding rectangle region and set up the data // now let's set the clipping list if ((lpddclipper->SetClipList(region_data, 0))!=DD_OK) { // release memory and return error free(region_data); return(NULL); } // end if // now attach the clipper to the surface if ((lpdds->SetClipper(lpddclipper))!=DD_OK) { // release memory and return error free(region_data); return(NULL); } // end if // all is well, so release memory and send back the pointer to the new clipper free(region_data); return(lpddclipper); } // end DD_Attach_Clipper /////////////////////////////////////////////////////////////// int DD_Flip(void) { // this function flip the primary surface with the secondary surface // flip pages while(lpddsprimary->Flip(NULL, DDFLIP_WAIT)!=DD_OK); // flip the surface // return success return(1); } // end DD_Flip /////////////////////////////////////////////////////////////// DWORD Start_Clock(void) { // this function starts the clock, that is, saves the current // count, use in conjunction with Wait_Clock() return(start_clock_count = Get_Clock()); } // end Start_Clock /////////////////////////////////////////////////////////////// DWORD Get_Clock(void) { // this function returns the current tick count // return time return(GetTickCount()); } // end Get_Clock /////////////////////////////////////////////////////////////// DWORD Wait_Clock(DWORD count) { // this function is used to wait for a specific number of clicks // since the call to Start_Clock while((Get_Clock() - start_clock_count) < count); return(Get_Clock()); } // end Wait_Clock /////////////////////////////////////////////////////////////// int DD_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color) { DDBLTFX ddbltfx; // this contains the DDBLTFX structure // clear out the structure and set the size field DD_INIT_STRUCT(ddbltfx); // set the dwfillcolor field to the desired color ddbltfx.dwFillColor = color; // ready to blt to surface lpdds->Blt(NULL, // ptr to dest rectangle NULL, // ptr to source surface, NA NULL, // ptr to source rectangle, NA DDBLT_COLORFILL | DDBLT_WAIT | DDBLT_ASYNC, // fill and wait &ddbltfx); // ptr to DDBLTFX structure // return success return(1); } // end DD_Fill_Surface /////////////////////////////////////////////////////////////// int Draw_Rectangle(int x1, int y1, int x2, int y2, int color, LPDIRECTDRAWSURFACE7 lpdds) { // this function uses directdraw to draw a filled rectangle DDBLTFX ddbltfx; // this contains the DDBLTFX structure RECT fill_area; // this contains the destination rectangle // clear out the structure and set the size field DD_INIT_STRUCT(ddbltfx); // set the dwfillcolor field to the desired color ddbltfx.dwFillColor = color; // fill in the destination rectangle data (your data) fill_area.top = y1; fill_area.left = x1; fill_area.bottom = y2+1; fill_area.right = x2+1; // ready to blt to surface, in this case blt to primary lpdds->Blt(&fill_area, // ptr to dest rectangle NULL, // ptr to source surface, NA NULL, // ptr to source rectangle, NA DDBLT_COLORFILL | DDBLT_WAIT | DDBLT_ASYNC, // fill and wait &ddbltfx); // ptr to DDBLTFX structure // return success return(1); } // end Draw_Rectangle /////////////////////////////////////////////////////////////// int Draw_Text_GDI(char *text, int x,int y,int color, LPDIRECTDRAWSURFACE7 lpdds) { // this function draws the sent text on the sent surface // using color index as the color in the palette HDC xdc; // the working dc // get the dc from surface if (lpdds->GetDC(&xdc)!=DD_OK) return(0); // set the colors for the text up SetTextColor(xdc,RGB(palette[color].peRed,palette[color].peGreen,palette[color].peBlue) ); // set background mode to transparent so black isn't copied SetBkMode(xdc, TRANSPARENT); // draw the text a TextOut(xdc,x,y,text,strlen(text)); // release the dc lpdds->ReleaseDC(xdc); // return success return(1); } // end Draw_Text_GDI ///////////////////////////////////////////////////////////////
// BLACKBOX.H - Header file for demo game engine library // watch for multiple inclusions #ifndef BLACKBOX #define BLACKBOX #include <ddraw.h> // directX includes #pragma comment(lib, "ddraw.lib") // 添加这句,告诉链接器链接这个lib文件 // DEFINES //////////////////////////////////////////////////// // default screen size #define SCREEN_WIDTH 640 // size of screen #define SCREEN_HEIGHT 480 #define SCREEN_BPP 8 // bits per pixel #define MAX_COLORS 256 // maximum colors // MACROS ///////////////////////////////////////////////////// // these read the keyboard asynchronously #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) #define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) // initializes a direct draw struct #define DD_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); } // TYPES ////////////////////////////////////////////////////// // basic unsigned types typedef unsigned short USHORT; typedef unsigned short WORD; typedef unsigned char UCHAR; typedef unsigned char BYTE; // EXTERNALS ////////////////////////////////////////////////// extern LPDIRECTDRAW7 lpdd; // dd object extern LPDIRECTDRAWSURFACE7 lpddsprimary; // dd primary surface extern LPDIRECTDRAWSURFACE7 lpddsback; // dd back surface extern LPDIRECTDRAWPALETTE lpddpal; // a pointer to the created dd palette extern LPDIRECTDRAWCLIPPER lpddclipper; // dd clipper extern PALETTEENTRY palette[256]; // color palette extern PALETTEENTRY save_palette[256]; // used to save palettes extern DDSURFACEDESC2 ddsd; // a direct draw surface description struct extern DDBLTFX ddbltfx; // used to fill extern DDSCAPS2 ddscaps; // a direct draw surface capabilities struct extern HRESULT ddrval; // result back from dd calls extern DWORD start_clock_count; // used for timing // these defined the general clipping rectangle extern int min_clip_x, // clipping rectangle max_clip_x, min_clip_y, max_clip_y; // these are overwritten globally by DD_Init() extern int screen_width, // width of screen screen_height, // height of screen screen_bpp; // bits per pixel // PROTOTYPES ///////////////////////////////////////////////// // DirectDraw functions int DD_Init(int width, int height, int bpp); int DD_Shutdown(void); LPDIRECTDRAWCLIPPER DD_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds, int num_rects, LPRECT clip_list); int DD_Flip(void); int DD_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color); // general utility functions DWORD Start_Clock(void); DWORD Get_Clock(void); DWORD Wait_Clock(DWORD count); // graphics functions int Draw_Rectangle(int x1, int y1, int x2, int y2, int color,LPDIRECTDRAWSURFACE7 lpdds=lpddsback); // gdi functions int Draw_Text_GDI(char *text, int x,int y,COLORREF color, LPDIRECTDRAWSURFACE7 lpdds=lpddsback); int Draw_Text_GDI(char *text, int x,int y,int color, LPDIRECTDRAWSURFACE7 lpdds=lpddsback); #endif
相关文章推荐
- java读取属性配置(properties)文件
- 文件的加密压缩与解压(java)
- Java插入修改删除数据库数据的基本方法
- Java基础:如何解决double和float精度不准的问题
- C++对象模型
- java如何保留指定精度
- 简单的Lua 连接操作mysql数据库的方法
- opencv每隔几秒在图片上显示一个点 (代码)
- 悬浮导航代码
- JSP编译为Java类
- 53 PHP文件处理(六)文件上传--总结---细说php
- Python&nbsp;cgi&nbsp;windows
- C++&nbsp;有符号&nbsp;无符号数
- Python set list dict tuple 区别
- PHP 之 FastCGI 与 mod_php 详解
- Effective&nbsp;C++笔记
- Python&nbsp;tuples&nbsp;list
- Python&nbsp;类型转化
- Google&nbsp;编程规范1.2
- C语言字符串操作