游戏编程总结(一) 是男人就撑过20秒

 
最近一直在研究游戏编程方面的东西。
受到大牛们的点播,于是去网上下了一本书《windows游戏编程大师技巧(第二版)》  当然了,是电子版的。
 
刚开始看的时候觉得很无趣,而且难度非常大。
因为老是想一口吃成大胖子,所以好高骛远,学了一段时间,什么都没学到。
后来认真的把书上的文字叙述看了下,并且找到了本书的所有源代码。于是学习的进度就大大提高了。
这本书真的很好,书中叙述非常幽默,不像国内出版的书籍,一板一眼,很严肃。
而且本书作者的水平很高超,能够凭空创造游戏。。。。(膜拜)
 
现在这本书读了大概1/3左右。按照前面所教的内容,胡乱编制了一个非常弱B的游戏。(漏洞千奇百怪)
特此总结一下。
 
首先,代码调用了DirectX SDK 9.0版本的库函数。
所以直接运行源代码,在普通的VC上是没有办法编译的。
/*编译出来的exe文件可以任何机器上运行*/
安装DirectX SDK也是一个麻烦事。(非常麻烦,稍不注意就会错)
 
整个游戏的编程过程是:
先创建一个窗口,窗口类型为WS_POPUP,并且把屏幕的分辨率调小(320*240)色彩深度更改为8位
 
然后在窗口上面随机产生50个笑脸,笑脸的位置随机,初始速度随机(为了保证游戏性,把速度为0的笑脸去掉了)
 
然后创建一个蓝色的原点,这个原点会根据我们的键盘按下消息更改位置。
 
不断的对整个窗口做碰撞检测,如果发生碰撞,就弹出对话框,输出"G A M E   O V E R~~~~"
 
游戏虽然很简单,但是用到的东西比较多。需要总结、记忆
 

游戏效果:

图片

 

图中,蓝色点为操控的点。其他的笑脸全部在运动。(布朗运动?)

目标就是不断的躲避,不碰到那些笑脸

 

如果碰到的话:

图片

 

点击确定后,程序睡眠三秒,随后退出程序。

 
 
//下面的定义了游戏常用函数,和游戏的参数(如分辨率,色深,速度等等)

#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,
                          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};

由于在创建调色板的时候,把1颜色调成了黄色,0是黑色

显示图片的函数:(由于图片出现的位置有可能位于超过屏幕的地方)

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=video_buffer+mempitch;
  bitmap=bitmap+width;
 }
}

另外碰撞检测是直接运算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、最先开始本来调用系统时间来计算程序运行时间,可是计算结果老是不对。

猜你喜欢

转载自blog.csdn.net/xieshimao/article/details/7296168