www.pudn.com > Snake.rar > main.cpp


#include 
#include  
 
#include"snaker.h" 
#include"table.h" 
 
//游戏状态定义 
#define GAME_STATE_WAIT     0  //游戏等待状态 
#define GAME_STATE_RUN      1  //游戏运行状态 
#define GAME_STATE_END      2  //游戏结束状态 
 
//界面相关物件尺寸定义 
#define WALL_WIDTH             80  //外墙从左部到游戏区的宽度 
#define WALL_HEIGHT            80  //外墙从顶部到游戏区的高度 
 
#define BMP_SCORE_BOARD_WIDTH  256 //分数位图板的宽度 
#define BMP_SCORE_BOARD_HEIGHT 55  //分数位图板的高度 
 
#define BMP_WALL_WIDTH         16  //墙位图的宽度 
#define BMP_WALL_HEIGHT        16  //墙位图的高度 
 
LRESULT CALLBACK WndProc(HWND hWnd,UINT message, 
						 WPARAM wParam,LPARAM lParam); 
void DrawGame(void); 
void ShellDraw( HDC  hdc ); 
void GameAreaDraw(HDC hdc); 
 
void OnTimer(UINT uTIMER_ID); 
void StartGame( void ); 
void EndGame( void ); 
 
//创建一个桌子 
CTable table; 
 
int tableBlockWidth = 0;  //桌子的格子的宽度 
int tableBlockHeight = 0; //桌子的格子的高度 
int iScores = 0;          //游戏的得分 
 
UINT uGameState = GAME_STATE_WAIT; //当前游戏状态 
 
HDC windowDC = NULL;      //windows屏幕设备 
HDC bufferDC = NULL;      //缓冲设备环境 
HDC picDC = NULL;         //snake图像内存设备 
HDC endDC = NULL;		 //游戏终结图像内存设备 
HDC scoreDC = NULL;      //分数板内存设备 
 
HWND hAppWnd = NULL;     //本application窗口句柄 
 
 
HBITMAP picBMP = NULL;      //snake图像位图句柄 
HBITMAP bufferBMP = NULL;   //缓冲位图句柄 
HBITMAP endBMP = NULL;      //游戏终结图像内存句柄 
HBITMAP hbmpWall = NULL;    //墙位图句柄 
HBITMAP hbmpScore = NULL;   //分数板位图句柄 
 
HBRUSH hbrushWall = NULL;      //墙画刷 
 
//定时器标识 
UINT uSnakeMoveTimer;  //蛇的移动 
UINT uFoodAddTimer;    //水果的产生 
 
//框架的位置数据定义 
//GDI RECT 而不是 MFC CRect 
RECT g_ClientRect; 
RECT g_GameValueRect; 
int g_iClientWidth; 
int g_iClientHeight; 
 
int WINAPI WinMain(HINSTANCE hCurrentInst,HINSTANCE hPrevInstance, 
				   PSTR lpszCmdLine,int nCmdShow) 
{	 
	WNDCLASS wndClass; 
	HWND hWnd; 
	MSG msg; 
	UINT width,height; 
	 
	 
	//定义窗口 
	wndClass.style=CS_HREDRAW | CS_VREDRAW; 
	wndClass.lpfnWndProc=WndProc; 
	wndClass.cbClsExtra=0; 
	wndClass.cbWndExtra=0; 
	wndClass.hInstance=hCurrentInst; 
	wndClass.hIcon=LoadIcon(NULL,MAKEINTRESOURCE(IDI_MAIN)); 
	wndClass.hCursor=LoadCursor(NULL,IDC_ARROW); 
	wndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); 
	wndClass.lpszMenuName=NULL; 
	wndClass.lpszClassName="Snake_CLASS"; 
	//注册窗口 
	RegisterClass(&wndClass); 
	 
	 
	//取整个屏幕的尺寸	 
	width=GetSystemMetrics(SM_CXSCREEN); 
	height=	GetSystemMetrics(SM_CYSCREEN); 
	//创建窗口 
	hWnd=CreateWindow( 
		"Snake_CLASS", 
		"skyblue snake", 
		WS_POPUP, 
		0,0, 
		width,height, 
		NULL,NULL, 
		hCurrentInst, 
		NULL); 
 
	hAppWnd = hWnd; 
 
	//显示窗口 
	ShowWindow(hWnd,nCmdShow); 
	UpdateWindow(hWnd); 
	 
    //获取窗体大小 
	GetClientRect(hAppWnd, &g_ClientRect); 
	g_iClientWidth = g_ClientRect.right-g_ClientRect.left; 
	g_iClientHeight = g_ClientRect.bottom-g_ClientRect.top; 
 
	//将游戏区域分成纵,横均为20块的小方块 
	//并计算每块区域的大小 
	tableBlockWidth = (g_iClientWidth-2*WALL_WIDTH)/20; 
	tableBlockHeight = (g_iClientHeight-2*WALL_HEIGHT)/20; 
	 
	//获取当前主窗口设备与windowDC关联 
	windowDC=GetDC(NULL); 
	//创建与windowDC兼容的内存设备环境 
	bufferDC=CreateCompatibleDC(windowDC); 
	picDC=CreateCompatibleDC(windowDC); 
	endDC=CreateCompatibleDC(windowDC);	 
	scoreDC=CreateCompatibleDC(windowDC);	 
 
	//位图的初始化或载入位图	 
	bufferBMP=CreateCompatibleBitmap(windowDC,g_iClientWidth,g_iClientHeight); 
	picBMP=(HBITMAP)LoadImage(NULL,"snake.bmp",IMAGE_BITMAP,160,80,LR_LOADFROMFILE); 
	hbmpWall=(HBITMAP)LoadImage(NULL,"brick.bmp",IMAGE_BITMAP,16,16,LR_LOADFROMFILE); 
	endBMP = (HBITMAP)LoadImage(NULL,"end.bmp",IMAGE_BITMAP,369,300,LR_LOADFROMFILE); 
	hbmpScore=(HBITMAP)LoadImage(NULL,"scoreboard.bmp",IMAGE_BITMAP,265,55,LR_LOADFROMFILE); 
	 
	//声明位图与设备环境的关联 
	SelectObject(bufferDC,bufferBMP); 
	SelectObject(picDC,picBMP); 
	SelectObject(endDC,endBMP); 
	SelectObject(scoreDC,hbmpScore); 
 
	//建立画刷与其名相对应的图像的关联, 
	//以备用刷子将墙刷出来,用PatBlt()实现 
	hbrushWall = CreatePatternBrush(hbmpWall); 
	 
	StartGame(); 
	 
	 
	while(GetMessage(&msg,NULL,0,0)) 
	{		 
		TranslateMessage(&msg); 
		DispatchMessage(&msg); 
	} 
	return msg.wParam; 
} 
 
LRESULT CALLBACK WndProc(HWND hWnd,UINT message, 
						 WPARAM wParam,LPARAM lParam) 
{ 
	 
	switch(message) 
	{ 
	case WM_TIMER : 
		OnTimer((UINT)wParam);		 
		break;		 
 
	case WM_KEYDOWN: 
		switch(wParam) 
		{ 
		case VK_ESCAPE: 
			exit(0); 
			break; 
		case VK_UP: 
			table.ChangeSnakeDirect(S_UP); 
			break; 
		case VK_DOWN: 
			table.ChangeSnakeDirect(S_DOWN); 
			break; 
		case VK_LEFT: 
			table.ChangeSnakeDirect(S_LEFT); 
			break; 
		case VK_RIGHT: 
			table.ChangeSnakeDirect(S_RIGHT); 
			break; 
		case VK_SPACE: 
			if(	uGameState == GAME_STATE_END ) 
		{ 
			StartGame(); 
			break; 
		} 
 
		} 
		return 0; 
		case WM_SETCURSOR: 
			SetCursor(NULL); 
			return 0; 
		case WM_DESTROY: 
			ReleaseDC(hWnd,picDC); 
			ReleaseDC(hWnd,bufferDC); 
			ReleaseDC(hWnd,windowDC); 
			PostQuitMessage(0); 
			return 0;			 
	} 
	return DefWindowProc(hWnd,message,wParam,lParam); 
} 
 
void DrawGame(void) 
{ 
	//绘制外壳区域到缓冲 
	ShellDraw(bufferDC); 
 
	//绘制游戏区域到缓冲 
	GameAreaDraw(bufferDC); 
 
	//将整个画面从缓冲DC拷贝出屏幕 
	BitBlt(windowDC,0,0,g_iClientWidth,g_iClientHeight,bufferDC,0,0,SRCCOPY); 
} 
 
 
 
void OnTimer(UINT uTIMER_ID) 
{ 
	if ( uTIMER_ID == uSnakeMoveTimer ) 
	{ 
		//移动蛇 
		table.SnakeMove(); 
		 
		//检测是否碰到身体(环绕),结束游戏 
		if(table.GetSnake()->IsHeadTouchBody(table.GetSnake()->GetPos()[0].x,table.GetSnake()->GetPos()[0].y)) 
		{ 
			EndGame(); 
		} 
		 
		//根据蛇头所在的区域作出相应的处理 
		switch(table.GetData(table.GetSnake()->GetPos()[0].x,table.GetSnake()->GetPos()[0].y)) 
		{ 
		case TB_STATE_FOOD: 
			table.ClearFood(table.GetSnake()->GetPos()[0].x,table.GetSnake()->GetPos()[0].y); 
			table.AddBlock((rand())%tableBlockWidth,(rand())%tableBlockHeight); 
			table.GetSnake()->AddBody(); 
			++iScores; 
			break; 
		case TB_STATE_BLOCK: 
		case TB_STATE_SBLOCK: 
			//检测是否碰到障碍物,结束游戏 
			EndGame(); 
			break; 
		} 
		 
		//显示 
		DrawGame(); 
	} 
	else if ( uTIMER_ID == uFoodAddTimer ) 
	{//定时加食物 
		table.AddFood((rand())%tableBlockWidth,(rand())%tableBlockHeight); 
	} 
} 
 
void StartGame() 
{ 
	iScores=0; 
 
	//桌面的初始化 
	table.InitialTable(tableBlockWidth,tableBlockHeight); 
	table.GetSnake()->ChangeDirect(S_RIGHT); 
	table.GetSnake()->SetHeadPos(tableBlockWidth/2,tableBlockHeight/2); 
 
	//预先随机产生几个食物 
	srand( (unsigned)time(NULL) ); 
	for(int iFoodNum=0;  iFoodNum<4; iFoodNum++) 
	{ 
		table.AddFood((rand())%tableBlockWidth,(rand())%tableBlockHeight); 
	} 
	//不部下种子也可以直接用rand(), 
	//但是每次游戏开始都是产生完全一样的伪随即序列 
 
	//打开定时器 
	uSnakeMoveTimer = SetTimer(hAppWnd,500,100,NULL); 
	uFoodAddTimer = SetTimer(hAppWnd,600,7000,NULL); 
 
		uGameState = GAME_STATE_RUN; 
} 
 
void EndGame( void ) 
{ 
	//关闭定时器 
	KillTimer(hAppWnd,uSnakeMoveTimer); 
	KillTimer(hAppWnd,uFoodAddTimer); 
	uGameState = GAME_STATE_END; 
} 
 
void ShellDraw( HDC  hdc ) 
{	 
//	HDC hMemDc; 
//	BOOL ret = TRUE; 
//	HDC hMemoryDC; 
//	HBITMAP hbmp; 
	//分数提示显示文字 
	char szText[30] = "Score: "; 
	char szNum[20]; 
 
	int iNowScore = iScores*100; 
	itoa(iNowScore,szNum,10); 
	strcat(szText, szNum); 
	 
	RECT rt, rect; 
	GetClientRect(hAppWnd, &rt); 
	//墙的绘制 
	SelectObject(hdc,hbrushWall); 
	PatBlt(hdc,rt.left,rt.top,rt.right,rt.bottom,PATCOPY); 
	//内部游戏区的白色底平面 
	rect.left = rt.left+WALL_WIDTH; 
	rect.top = rt.top + WALL_HEIGHT; 
	rect.right = rt.right - WALL_WIDTH; 
	rect.bottom = rt.bottom - WALL_HEIGHT;		 
	FillRect(hdc, &rect, (HBRUSH) (COLOR_WINDOW+1)); 
	 
	//分数提示板的绘制		 
/*	hMemoryDC =	CreateCompatibleDC(NULL);	 
	hbmp = CreateCompatibleBitmap(hdc,265,55);		 
	SelectObject(hMemoryDC,hbrushScore);	 
	SelectObject(hMemoryDC,hbmp);	 
	PatBlt(hMemoryDC,0,0,256,55,PATCOPY);	 
	BitBlt(hdc,GetSystemMetrics(SM_CXSCREEN)/3, 
		   10,256,55,hMemoryDC,0,0,SRCCOPY); 
*/ 
	BitBlt(hdc,GetSystemMetrics(SM_CXSCREEN)/3, 
		   10,256,55,scoreDC,0,0,SRCCOPY); 
	 
//分数的打印绘制 
	SetBkMode(hdc, TRANSPARENT); 	 
	TextOut(hdc, GetSystemMetrics(SM_CXSCREEN)/3+50, 30,szText,strlen(szText) ); 
} 
 
void GameAreaDraw(HDC hdc) 
{ 
	int i,j; 
	int x,y, x_pos,y_pos; 
	BitmapState  state; 
	char strMark[20]; 
 
	//绘制水果与 毒果 
	for(i=0;iGetPos()[0].x; 
		y=table.GetSnake()->GetPos()[0].y; 
		x_pos = x*20+WALL_WIDTH; 
		y_pos = y*20+WALL_HEIGHT;		 
		state=table.GetSnake()->GetStateArray()[0]; 
 
		switch(state) 
		{ 
		case M_UP_UP: 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,80,20,SRCPAINT); 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,0,20,SRCAND); 
			break; 
		case M_DOWN_DOWN: 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,140,20,SRCPAINT); 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,60,20,SRCAND); 
			break; 
		case M_LEFT_LEFT: 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,100,20,SRCPAINT); 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,20,20,SRCAND); 
			break; 
		case M_RIGHT_RIGHT: 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,120,20,SRCPAINT); 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,40,20,SRCAND); 
			break; 
		} 
 
		//根据各个蛇身节点的状态绘制蛇身的形状 
		for(i=1;iGetLength()-1;i++) 
		{ 
			x=table.GetSnake()->GetPos()[i].x; 
			y=table.GetSnake()->GetPos()[i].y; 
			x_pos = x*20+WALL_WIDTH; 
			y_pos = y*20+WALL_HEIGHT;	 
			state=table.GetSnake()->GetStateArray()[i]; 
			switch(state) 
			{ 
			case M_UP_UP: 
			case M_DOWN_DOWN: 
				BitBlt(hdc,x_pos,y_pos,20,20,picDC,80,40,SRCPAINT); 
				BitBlt(hdc,x_pos,y_pos,20,20,picDC,0,40,SRCAND); 
				break; 
			case M_LEFT_LEFT: 
			case M_RIGHT_RIGHT: 
				BitBlt(hdc,x_pos,y_pos,20,20,picDC,100,40,SRCPAINT); 
				BitBlt(hdc,x_pos,y_pos,20,20,picDC,20,40,SRCAND); 
				break; 
			case M_RIGHT_DOWN: 
			case M_UP_LEFT: 
				BitBlt(hdc,x_pos,y_pos,20,20,picDC,100,60,SRCPAINT); 
				BitBlt(hdc,x_pos,y_pos,20,20,picDC,20,60,SRCAND); 
				break; 
			case M_LEFT_DOWN: 
			case M_UP_RIGHT: 
				BitBlt(hdc,x_pos,y_pos,20,20,picDC,80,60,SRCPAINT); 
				BitBlt(hdc,x_pos,y_pos,20,20,picDC,0,60,SRCAND); 
				break; 
			case M_RIGHT_UP: 
			case M_DOWN_LEFT: 
				BitBlt(hdc,x_pos,y_pos,20,20,picDC,140,40,SRCPAINT); 
				BitBlt(hdc,x_pos,y_pos,20,20,picDC,60,40,SRCAND); 
				break; 
			case M_LEFT_UP: 
			case M_DOWN_RIGHT: 
				BitBlt(hdc,x_pos,y_pos,20,20,picDC,120,40,SRCPAINT); 
				BitBlt(hdc,x_pos,y_pos,20,20,picDC,40,40,SRCAND); 
				break; 
				 
			} 
		} 
 
		//绘制蛇尾巴 
		x=table.GetSnake()->GetPos()[table.GetSnake()->GetLength()-1].x; 
		y=table.GetSnake()->GetPos()[table.GetSnake()->GetLength()-1].y; 
		x_pos = x*20+WALL_WIDTH; 
		y_pos = y*20+WALL_HEIGHT;	 
		state=table.GetSnake()->GetStateArray()[table.GetSnake()->GetLength()-1];		 
		switch(state) 
		{ 
		case M_UP_UP: 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,120,60,SRCPAINT); 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,40,60,SRCAND); 
			break; 
		case M_DOWN_DOWN: 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,120,0,SRCPAINT); 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,40,0,SRCAND); 
			break; 
		case M_LEFT_LEFT: 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,140,60,SRCPAINT); 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,60,60,SRCAND); 
			break; 
		case M_RIGHT_RIGHT: 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,140,0,SRCPAINT); 
			BitBlt(hdc,x_pos,y_pos,20,20,picDC,60,0,SRCAND); 
			break; 
		} 
		 
		if(uGameState == GAME_STATE_END) 
		{//绘制游戏结束图像 
			int x_pos = g_iClientWidth/3; 
			int y_pos = g_iClientHeight/4; 
 
			BitBlt(hdc, x_pos, y_pos, 369, 300, endDC, 0, 0, SRCCOPY);			 
		} 
}