#include <windows.h>
#include <time.h>
#pragma comment(lib,"msimg32.lib")
#define SNAKESIZE 36
#define CELLROW 20
#define CELLCOL 25
HINSTANCE G_hInst=NULL;
HDC G_BitMapBKDC=NULL;
HDC G_BitMapSnakeDC=NULL;
HDC G_BitMapFoodDC=NULL;
RECT ClientRect;
long BKWidth=0;
long BKHeight=0;
enum Direction
{
LEFT,
UP,
RIGHT,
DOWN
};
enum Direction SnakeDir=RIGHT;
POINT SnakePoint = {108,108};
POINT FoodPoint;
POINT SnakeBody[500];
int SnakeBodySize=0;
LRESULT CALLBACK WndProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
HDC LoadBitMapToDC(HINSTANCE hInst,char * fileName);
HDC LoadBitMapToDC(HINSTANCE hInst,char * fileName,long &width,long &height);
void DrawSnake(HDC hDc);
void CreateFood();
void CreateFood()
{
::srand(time(NULL));
FoodPoint.x = ::rand()%CELLCOL * SNAKESIZE;
FoodPoint.y = ::rand()%CELLROW * SNAKESIZE;
}
HDC LoadBitMapToDC(HINSTANCE hInst,char * fileName)
{
HBITMAP hBitMap = (HBITMAP)::LoadImage(hInst,fileName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
HDC hDc = ::CreateCompatibleDC(NULL);
::SelectObject(hDc,hBitMap);
::DeleteObject(hBitMap);
return hDc;
}
HDC LoadBitMapToDC(HINSTANCE hInst,char * fileName,long &width,long &height)
{
HBITMAP hBitMap = (HBITMAP)::LoadImage(hInst,fileName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE | LR_CREATEDIBSECTION);
DIBSECTION dib;
::GetObject(hBitMap,sizeof(dib),&dib);
BITMAPINFOHEADER bm = dib.dsBmih;
width = bm.biWidth;
height = bm.biHeight;
HDC hDc = ::CreateCompatibleDC(NULL);
::SelectObject(hDc,hBitMap);
::DeleteObject(hBitMap);
return hDc;
}
HDC CreateMemoryDC(HDC ClientDC,RECT rect)
{
HDC hMDC = ::CreateCompatibleDC(ClientDC);
HBITMAP hBitMap = ::CreateCompatibleBitmap(ClientDC,
rect.right-rect.left,
rect.bottom-rect.top);
::SelectObject(hMDC,hBitMap);
FillRect(hMDC,&rect,NULL);
::DeleteObject(hBitMap);
return hMDC;
}
void DrawSnake(HDC hDc)
{
//::BitBlt(hDc,0,0,640,480,
// G_BitMapBKDC,0,0,SRCCOPY);
HDC hMDC = CreateMemoryDC(hDc,ClientRect);
::StretchBlt(hMDC,0,0,
ClientRect.right-ClientRect.left,
ClientRect.bottom-ClientRect.top,
G_BitMapBKDC,0,0,BKWidth,BKHeight,SRCCOPY);
//BitBlt(hDc,200,200,36,36,
// G_BitMapSnakeDC,0,0,SRCCOPY);
int color = ::GetPixel(G_BitMapSnakeDC,0,0);
::TransparentBlt(hMDC,SnakePoint.x,SnakePoint.y,SNAKESIZE,SNAKESIZE,
G_BitMapSnakeDC,0,0,SNAKESIZE,SNAKESIZE,color);
for(int i=0;i<SnakeBodySize;i++)
::TransparentBlt(hMDC,SnakeBody[i].x,SnakeBody[i].y,SNAKESIZE,SNAKESIZE,
G_BitMapSnakeDC,0,0,SNAKESIZE,SNAKESIZE,color);
color = ::GetPixel(G_BitMapFoodDC,0,0);
::TransparentBlt(hMDC,FoodPoint.x,FoodPoint.y,SNAKESIZE,SNAKESIZE,
G_BitMapFoodDC,0,0,SNAKESIZE,SNAKESIZE,color);
::BitBlt(hDc,0,0,
ClientRect.right-ClientRect.left,
ClientRect.bottom-ClientRect.top,
hMDC,0,0,SRCCOPY);
}
void SnakeMove(HWND hwnd)
{
switch(SnakeDir)
{
case LEFT:
SnakePoint.x-=SNAKESIZE;
break;
case UP:
SnakePoint.y-=SNAKESIZE;
break;
case RIGHT:
SnakePoint.x+=SNAKESIZE;
break;
case DOWN:
SnakePoint.y+=SNAKESIZE;
break;
}
int EndX = SnakeBody[SnakeBodySize].x;
int EndY = SnakeBody[SnakeBodySize].y;
for(int i=SnakeBodySize;i>0;i--)
{
SnakeBody[i].x=SnakeBody[i-1].x;
SnakeBody[i].y=SnakeBody[i-1].y;
}
SnakeBody[i].x=SnakePoint.x;
SnakeBody[i].y=SnakePoint.y;
if(SnakePoint.x == FoodPoint.x
&& SnakePoint.y == FoodPoint.y)
{
CreateFood();
::KillTimer(hwnd,2);
::SetTimer(hwnd,2,5000,NULL);
SnakeBody[SnakeBodySize].x=EndX;
SnakeBody[SnakeBodySize].y=EndY;
SnakeBodySize++;
}
}
LRESULT CALLBACK WndProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
switch(uMsg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDc = ::BeginPaint(hwnd,&ps);
DrawSnake(hDc);
::EndPaint(hwnd,&ps);
break;
}
case WM_SIZE:
{
::GetClientRect(hwnd,&ClientRect);
break;
}
case WM_KEYDOWN:
{
switch(wParam)
{
case VK_LEFT:
SnakeDir = LEFT;
break;
case VK_UP:
SnakeDir = UP;
break;
case VK_RIGHT:
SnakeDir = RIGHT;
break;
case VK_DOWN:
SnakeDir = DOWN;
break;
}
break;
}
case WM_TIMER:
{
switch(wParam)
{
case 1:
{
SnakeMove(hwnd);
HDC hDc = GetDC(hwnd);
DrawSnake(hDc);
ReleaseDC(hwnd,hDc);
break;
}
case 2:
{
CreateFood();
break;
}
}
break;
}
case WM_CREATE:
{
::SetTimer(hwnd,1,200,NULL);
::SetTimer(hwnd,2,5000,NULL);
::GetClientRect(hwnd,&ClientRect);
CreateFood();
G_BitMapBKDC =::LoadBitMapToDC(G_hInst,"map//back.bmp",BKWidth,BKHeight);
G_BitMapSnakeDC = LoadBitMapToDC(G_hInst,"map//tank11.bmp");
G_BitMapFoodDC = LoadBitMapToDC(G_hInst,"map//tank21.bmp");
break;
}
case WM_DESTROY:
::DeleteDC(G_BitMapBKDC);
G_BitMapBKDC=NULL;
::DeleteDC(G_BitMapSnakeDC);
G_BitMapSnakeDC=NULL;
::DeleteDC(G_BitMapFoodDC);
G_BitMapFoodDC=NULL;
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return false;
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
G_hInst = hInstance;
//1、设置窗体属性
WNDCLASSEX wcex;
// 结构体的大小
wcex.cbSize = sizeof(WNDCLASSEX);
// 窗体类的样式
wcex.style = CS_HREDRAW | CS_VREDRAW;
// *窗体回调函数
wcex.lpfnWndProc = (WNDPROC)WndProc;
// 窗体类额外字节数,通常为0
wcex.cbClsExtra = 0;
// 窗体实例额外字节数,通常为0
wcex.cbWndExtra = 0;
// *应用程序实例句柄
wcex.hInstance = hInstance;
wcex.hIcon = NULL; // 窗体大图标
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); // 窗体鼠标光标样式
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // 窗体背景色
wcex.lpszMenuName = NULL; // 窗体主菜单
// *窗体类名称
wcex.lpszClassName = "Snake";
wcex.hIconSm = NULL; // 窗体小图标
//2、注册窗体
RegisterClassEx(&wcex);
//3、创建窗体
HWND hWnd = CreateWindow(
"Snake", // *窗体类名称
"贪食蛇未完成版", // 窗体标题名
WS_OVERLAPPEDWINDOW, // 窗体外观样式
CW_USEDEFAULT, // 窗体在屏幕上的水平位置
0, // 窗体在屏幕上的垂直位置
900, // 窗口的宽度
720, // 窗口的高度
NULL, // 父窗体句柄
NULL, // 窗口菜单句柄
hInstance, // *创建窗体的应用程序实例句柄
NULL); // 创建窗体时的额外信息,通常为NULL
if (NULL == hWnd)
{
return FALSE;
}
//4、显示窗体
ShowWindow(hWnd, nShowCmd);
//5、 更新窗体
UpdateWindow(hWnd);
//6、主消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) // 从消息队列中获取消息
{
TranslateMessage(&msg); // 转换消息
DispatchMessage(&msg); // 分发消息给回调函数
}
return msg.wParam;
}