#define KEYDOWN(key) ((GetAsyncKeyState(key) & 0x8000) ? 1 : 0)
#define KEYUP(key) ((GetAsyncKeyState(key) & 0x8000) ? 0 : 1)
#define DD_INIT_STRUCT(ddstruct){memset(&ddstruct,0,sizeof(ddstruct));ddstruct.dwSize=sizeof(ddstruct);}
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define SCREEN_BPP 8
#define SPEED_X 3
#define SPEED_Y 3
#define ANINUM 50
关键是笑脸比较难画,我用的是书上的方法(最简单的一种)
用数组,表示了一个64像素的图片:
UCHAR happy_bitmap[64] = {0,0,0,0,0,0,0,0,由于在创建调色板的时候,把1颜色调成了黄色,0是黑色
显示图片的函数:(由于图片出现的位置有可能位于超过屏幕的地方)
void Blt_Clip(int x,int y,int width,int height,UCHAR *bitmap,UCHAR *video_buffer,int mempitch)
另外碰撞检测是直接运算50次,分别计算每一个距离是否会低于3.0
//接下来是所有代码:
//需要添加一个链接库文件:ddraw.lib才行
#pragma comment(lib,"dxguid.lib") #include<stdio.h> #include<windows.h> #include<time.h> #include<stdlib.h> #include<ddraw.h> #include<math.h> #define KEYDOWN(key) ((GetAsyncKeyState(key) & 0x8000) ? 1 : 0) #define KEYUP(key) ((GetAsyncKeyState(key) & 0x8000) ? 0 : 1) #define DD_INIT_STRUCT(ddstruct){memset(&ddstruct,0,sizeof(ddstruct));ddstruct.dwSize=sizeof(ddstruct);} #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 240 #define SCREEN_BPP 8 #define SPEED_X 3 #define SPEED_Y 3 #define ANINUM 50 UCHAR *double_buffer = NULL; LPDIRECTDRAW7 lpdd=NULL; LPDIRECTDRAWSURFACE7 lpddsprimary=NULL; LPDIRECTDRAWSURFACE7 lpddsback=NULL; DDSURFACEDESC2 ddsd; LPDIRECTDRAWPALETTE lpddpal=NULL; PALETTEENTRY palette[256]; DWORD Start_time; DWORD Now_time; #define _RGB16BIT555(r,g,b) ((b&31)+((g&31)<<5)+((r&31)<<10)) #define _RGB16BIT565(r,g,b) ((b&31)+((g&63)<<5)+((r&31)<<11)) #define _RGB32BIT(a,r,g,b) ((b)+((g)<<8)+((r)<<16)+((a)<<24)) UCHAR happy_bitmap[64] = {0,0,0,0,0,0,0,0, 0,0,1,1,1,1,0,0, 0,1,0,1,1,0,1,0, 0,1,1,1,1,1,1,0, 0,1,0,1,1,0,1,0, 0,1,1,0,0,1,1,0, 0,0,1,1,1,1,0,0, 0,0,0,0,0,0,0,0}; UCHAR sad_bitmap[64] = {0,0,0,0,0,0,0,0, 0,0,1,1,1,1,0,0, 0,1,0,1,1,0,1,0, 0,1,1,1,1,1,1,0, 0,1,1,0,0,1,1,0, 0,1,0,1,1,0,1,0, 0,0,1,1,1,1,0,0, 0,0,0,0,0,0,0,0}; UCHAR my_plane[64] = {0,0,0,0,0,0,0,0, 0,0,2,2,2,2,0,0, 0,2,2,2,2,2,2,0, 0,2,2,2,2,2,2,0, 0,2,2,2,2,2,2,0, 0,2,2,2,2,2,2,0, 0,0,2,2,2,2,0,0, 0,0,0,0,0,0,0,0}; struct HappyFace { int posx; int posy; int cen_x; int cen_y; int xv; int yv; }; struct MyPlane { int x; int y; int cen_x; int cen_y; }; MyPlane plane; HappyFace happy_face[100]; void Plot_Pixel_Faster32(int x,int y,int a,int r,int g,int b,UINT *video_buffer,int lpitch32) { UINT color; color=_RGB32BIT(a,r,g,b); video_buffer[x+y*lpitch32]=color; } HWND hwd; HINSTANCE hIns; HDC hdc; LRESULT CALLBACK WinSunProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { HDC hdc; PAINTSTRUCT ps; switch(uMsg) { case WM_PAINT: hdc=BeginPaint(hwnd,&ps); EndPaint(hwnd,&ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: break; } return DefWindowProc(hwnd,uMsg,wParam,lParam); } void Blt_Clip(int x,int y,int width,int height,UCHAR *bitmap,UCHAR *video_buffer,int mempitch) { if((x>=SCREEN_WIDTH)||(y>=SCREEN_HEIGHT)||((x+width)<=0)||((y+height)<=0)) return; int x1=x; int y1=y; int x2=x+width-1; int y2=y+height-1; if(x1<0) x1=0; if(y1<0) y1=0; if(x2>SCREEN_WIDTH) x2=SCREEN_WIDTH; if(y2>SCREEN_HEIGHT) y2=SCREEN_HEIGHT; int x_off=x-x1; int y_off=y-y1; int dx=x2-x1+1; int dy=y2-y1+1; video_buffer=video_buffer+(x1+y1*mempitch); bitmap=bitmap+(x_off+y_off*width); int i,j; UCHAR pixel; for(j=0;j<dy;j++) { for(i=0;i<dx;i++) { pixel=bitmap[i]; video_buffer[i]=pixel; } video_buffer=video_buffer+mempitch; bitmap=bitmap+width; } } void Game_Init() { if(FAILED(DirectDrawCreateEx(NULL,(void**)&lpdd,IID_IDirectDraw7,NULL))) return; if(FAILED(lpdd->SetCooperativeLevel(hwd,DDSCL_FULLSCREEN|DDSCL_ALLOWMODEX|DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT))) return; if(FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,0,0))) return; DD_INIT_STRUCT(ddsd); ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT; ddsd.dwBackBufferCount=1; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|DDSCAPS_FLIP; if(FAILED(lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL))) return; ddsd.ddsCaps.dwCaps=DDSCAPS_BACKBUFFER; if(FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps,&lpddsback))) return; int i; srand(time(NULL)); for(i=1;i<=254;i++) { palette[i].peRed=rand()%256; palette[i].peGreen=rand()%256; palette[i].peBlue=rand()%256; palette[i].peFlags=PC_NOCOLLAPSE; } palette[0].peRed=0; palette[0].peGreen=0; palette[0].peBlue=0; palette[0].peFlags=PC_NOCOLLAPSE; palette[255].peRed=255; palette[255].peGreen=255; palette[255].peBlue=255; palette[255].peFlags=PC_NOCOLLAPSE; palette[1].peRed=255; palette[1].peGreen=255; palette[1].peBlue=0; palette[1].peFlags=PC_NOCOLLAPSE; palette[2].peRed=0; palette[2].peGreen=0; palette[2].peBlue=255; palette[2].peFlags=PC_NOCOLLAPSE; if(FAILED(lpdd->CreatePalette(DDPCAPS_8BIT|DDPCAPS_ALLOW256|DDPCAPS_INITIALIZE,palette,&lpddpal, NULL))) return; if(FAILED(lpddsprimary->SetPalette(lpddpal))) return; for(i=0;i<ANINUM;i++) { happy_face[i].posx=rand()%SCREEN_WIDTH; happy_face[i].posy=rand()%SCREEN_HEIGHT; happy_face[i].xv=-1+rand()%3; happy_face[i].yv=-1+rand()%3; happy_face[i].cen_x=happy_face[i].posx+4; happy_face[i].cen_y=happy_face[i].posy+4; } plane.x=SCREEN_WIDTH/2; plane.y=SCREEN_HEIGHT/2; plane.cen_x=SCREEN_WIDTH/2+4; plane.cen_y=SCREEN_HEIGHT/2+4; } double dis(int i) { return sqrt((plane.cen_x-happy_face[i].cen_x)*(plane.cen_x-happy_face[i].cen_x)*1.0+\ (plane.cen_y-happy_face[i].cen_y)*(plane.cen_y-happy_face[i].cen_y)*1.0); } void Game_Main() { if(KEYDOWN(VK_ESCAPE)) SendMessage(hwd,WM_CLOSE,0,0); DDBLTFX ddbltfx; DD_INIT_STRUCT(ddbltfx); ddbltfx.dwFillColor=0; if(FAILED(lpddsback->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT,&ddbltfx))) return; DD_INIT_STRUCT(ddsd); if(FAILED(lpddsback->Lock(NULL,&ddsd,DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,NULL))) return; int i; for(i=0;i<ANINUM;i++) Blt_Clip(happy_face[i].posx,happy_face[i].posy,8,8,happy_bitmap,(UCHAR*)ddsd.lpSurface,ddsd.lPitch); Blt_Clip(plane.x,plane.y,8,8,my_plane,(UCHAR*)ddsd.lpSurface,ddsd.lPitch); if(KEYDOWN(VK_UP)) { plane.y=plane.y-SPEED_Y; plane.cen_x=plane.x+4; plane.cen_y=plane.y+4; } if(KEYDOWN(VK_DOWN)) { plane.y=plane.y+SPEED_Y; plane.cen_x=plane.x+4; plane.cen_y=plane.y+4; } if(KEYDOWN(VK_LEFT)) { plane.x=plane.x-SPEED_X; plane.cen_x=plane.x+4; plane.cen_y=plane.y+4; } if(KEYDOWN(VK_RIGHT)) { plane.x=plane.x+SPEED_X; plane.cen_x=plane.x+4; plane.cen_y=plane.y+4; } for(i=0;i<ANINUM;i++) { double len; len=dis(i); if(len<3.0) { char xout[30]; sprintf(xout,"G A M E O V E R~~~\n"); MessageBox(hwd,xout,"bingshen",MB_OK); Sleep(3000); SendMessage(hwd,WM_CLOSE,0,0); } } for(i=0;i<ANINUM;i++) { happy_face[i].posx=happy_face[i].posx+happy_face[i].xv; happy_face[i].posy=happy_face[i].posy+happy_face[i].yv; happy_face[i].cen_x=happy_face[i].posx+4; happy_face[i].cen_y=happy_face[i].posy+4; if(happy_face[i].posx<-8) happy_face[i].posx=SCREEN_WIDTH; if(happy_face[i].posy<-8) happy_face[i].posy=SCREEN_HEIGHT; if(happy_face[i].posx>SCREEN_WIDTH) happy_face[i].posx=0; if(happy_face[i].posy>SCREEN_HEIGHT) happy_face[i].posy=0; } if (FAILED(lpddsback->Unlock(NULL))) return; while(FAILED(lpddsprimary->Flip(NULL,DDFLIP_WAIT))); } void Game_Shut() { if(lpddpal) { lpddpal->Release(); lpddpal=NULL; } if(lpddsprimary) { lpddsprimary->Release(); lpddsprimary=NULL; } if(lpdd) { lpdd->Release(); lpdd=NULL; } } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdline, int nShowCmd ) { WNDCLASS wndclass; wndclass.cbClsExtra=0; wndclass.cbWndExtra=0; wndclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); wndclass.hInstance=hInstance; wndclass.lpfnWndProc=WinSunProc; wndclass.lpszClassName="bingshen"; wndclass.lpszMenuName=NULL; wndclass.style=CS_HREDRAW|CS_VREDRAW; ShowCursor(FALSE); HWND hwnd; RegisterClass(&wndclass); hwnd=CreateWindow("bingshen","-------bingshen",WS_POPUP|WS_VISIBLE, 0,0,SCREEN_WIDTH,SCREEN_HEIGHT, NULL,NULL,hInstance,NULL); hwd=hwnd; hdc=GetDC(hwnd); hIns=hInstance; Game_Init(); MSG msg; while(true) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(msg.message==WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } Game_Main(); } Game_Shut(); ReleaseDC(hwnd,hdc); return msg.wParam; }
//调色板和前面的各种创建动态表面的过程很复杂,需要记忆。。
//漏洞(BUG):
1、弹出游戏结束的对话框,有时候会不出现。
2、最先开始本来调用系统时间来计算程序运行时间,可是计算结果老是不对。