main.cpp
上传用户:hbrsgg1
上传日期:2014-05-08
资源大小:2826k
文件大小:12k
源码类别:

其他智力游戏

开发平台:

C/C++

  1. #include<windows.h>
  2. #include <time.h>
  3. #include"snaker.h"
  4. #include"table.h"
  5. //游戏状态定义
  6. #define GAME_STATE_WAIT     0  //游戏等待状态
  7. #define GAME_STATE_RUN      1  //游戏运行状态
  8. #define GAME_STATE_END      2  //游戏结束状态
  9. //界面相关物件尺寸定义
  10. #define WALL_WIDTH             80  //外墙从左部到游戏区的宽度
  11. #define WALL_HEIGHT            80  //外墙从顶部到游戏区的高度
  12. #define BMP_SCORE_BOARD_WIDTH  256 //分数位图板的宽度
  13. #define BMP_SCORE_BOARD_HEIGHT 55  //分数位图板的高度
  14. #define BMP_WALL_WIDTH         16  //墙位图的宽度
  15. #define BMP_WALL_HEIGHT        16  //墙位图的高度
  16. LRESULT CALLBACK WndProc(HWND hWnd,UINT message,
  17.  WPARAM wParam,LPARAM lParam);
  18. void DrawGame(void);
  19. void ShellDraw( HDC  hdc );
  20. void GameAreaDraw(HDC hdc);
  21. void OnTimer(UINT uTIMER_ID);
  22. void StartGame( void );
  23. void EndGame( void );
  24. //创建一个桌子
  25. CTable table;
  26. int tableBlockWidth = 0;  //桌子的格子的宽度
  27. int tableBlockHeight = 0; //桌子的格子的高度
  28. int iScores = 0;          //游戏的得分
  29. UINT uGameState = GAME_STATE_WAIT; //当前游戏状态
  30. HDC windowDC = NULL;      //windows屏幕设备
  31. HDC bufferDC = NULL;      //缓冲设备环境
  32. HDC picDC = NULL;         //snake图像内存设备
  33. HDC endDC = NULL;  //游戏终结图像内存设备
  34. HDC scoreDC = NULL;      //分数板内存设备
  35. HWND hAppWnd = NULL;     //本application窗口句柄
  36. HBITMAP picBMP = NULL;      //snake图像位图句柄
  37. HBITMAP bufferBMP = NULL;   //缓冲位图句柄
  38. HBITMAP endBMP = NULL;      //游戏终结图像内存句柄
  39. HBITMAP hbmpWall = NULL;    //墙位图句柄
  40. HBITMAP hbmpScore = NULL;   //分数板位图句柄
  41. HBRUSH hbrushWall = NULL;      //墙画刷
  42. //定时器标识
  43. UINT uSnakeMoveTimer;  //蛇的移动
  44. UINT uFoodAddTimer;    //水果的产生
  45. //框架的位置数据定义
  46. //GDI RECT 而不是 MFC CRect
  47. RECT g_ClientRect;
  48. RECT g_GameValueRect;
  49. int g_iClientWidth;
  50. int g_iClientHeight;
  51. int WINAPI WinMain(HINSTANCE hCurrentInst,HINSTANCE hPrevInstance,
  52.    PSTR lpszCmdLine,int nCmdShow)
  53. {
  54. WNDCLASS wndClass;
  55. HWND hWnd;
  56. MSG msg;
  57. UINT width,height;
  58. //定义窗口
  59. wndClass.style=CS_HREDRAW | CS_VREDRAW;
  60. wndClass.lpfnWndProc=WndProc;
  61. wndClass.cbClsExtra=0;
  62. wndClass.cbWndExtra=0;
  63. wndClass.hInstance=hCurrentInst;
  64. wndClass.hIcon=LoadIcon(NULL,MAKEINTRESOURCE(IDI_MAIN));
  65. wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
  66. wndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
  67. wndClass.lpszMenuName=NULL;
  68. wndClass.lpszClassName="Snake_CLASS";
  69. //注册窗口
  70. RegisterClass(&wndClass);
  71. //取整个屏幕的尺寸
  72. width=GetSystemMetrics(SM_CXSCREEN);
  73. height= GetSystemMetrics(SM_CYSCREEN);
  74. //创建窗口
  75. hWnd=CreateWindow(
  76. "Snake_CLASS",
  77. "skyblue snake",
  78. WS_POPUP,
  79. 0,0,
  80. width,height,
  81. NULL,NULL,
  82. hCurrentInst,
  83. NULL);
  84. hAppWnd = hWnd;
  85. //显示窗口
  86. ShowWindow(hWnd,nCmdShow);
  87. UpdateWindow(hWnd);
  88.     //获取窗体大小
  89. GetClientRect(hAppWnd, &g_ClientRect);
  90. g_iClientWidth = g_ClientRect.right-g_ClientRect.left;
  91. g_iClientHeight = g_ClientRect.bottom-g_ClientRect.top;
  92. //将游戏区域分成纵,横均为20块的小方块
  93. //并计算每块区域的大小
  94. tableBlockWidth = (g_iClientWidth-2*WALL_WIDTH)/20;
  95. tableBlockHeight = (g_iClientHeight-2*WALL_HEIGHT)/20;
  96. //获取当前主窗口设备与windowDC关联
  97. windowDC=GetDC(NULL);
  98. //创建与windowDC兼容的内存设备环境
  99. bufferDC=CreateCompatibleDC(windowDC);
  100. picDC=CreateCompatibleDC(windowDC);
  101. endDC=CreateCompatibleDC(windowDC);
  102. scoreDC=CreateCompatibleDC(windowDC);
  103. //位图的初始化或载入位图
  104. bufferBMP=CreateCompatibleBitmap(windowDC,g_iClientWidth,g_iClientHeight);
  105. picBMP=(HBITMAP)LoadImage(NULL,"snake.bmp",IMAGE_BITMAP,160,80,LR_LOADFROMFILE);
  106. hbmpWall=(HBITMAP)LoadImage(NULL,"brick.bmp",IMAGE_BITMAP,16,16,LR_LOADFROMFILE);
  107. endBMP = (HBITMAP)LoadImage(NULL,"end.bmp",IMAGE_BITMAP,369,300,LR_LOADFROMFILE);
  108. hbmpScore=(HBITMAP)LoadImage(NULL,"scoreboard.bmp",IMAGE_BITMAP,265,55,LR_LOADFROMFILE);
  109. //声明位图与设备环境的关联
  110. SelectObject(bufferDC,bufferBMP);
  111. SelectObject(picDC,picBMP);
  112. SelectObject(endDC,endBMP);
  113. SelectObject(scoreDC,hbmpScore);
  114. //建立画刷与其名相对应的图像的关联,
  115. //以备用刷子将墙刷出来,用PatBlt()实现
  116. hbrushWall = CreatePatternBrush(hbmpWall);
  117. StartGame();
  118. while(GetMessage(&msg,NULL,0,0))
  119. {
  120. TranslateMessage(&msg);
  121. DispatchMessage(&msg);
  122. }
  123. return msg.wParam;
  124. }
  125. LRESULT CALLBACK WndProc(HWND hWnd,UINT message,
  126.  WPARAM wParam,LPARAM lParam)
  127. {
  128. switch(message)
  129. {
  130. case WM_TIMER :
  131. OnTimer((UINT)wParam);
  132. break;
  133. case WM_KEYDOWN:
  134. switch(wParam)
  135. {
  136. case VK_ESCAPE:
  137. exit(0);
  138. break;
  139. case VK_UP:
  140. table.ChangeSnakeDirect(S_UP);
  141. break;
  142. case VK_DOWN:
  143. table.ChangeSnakeDirect(S_DOWN);
  144. break;
  145. case VK_LEFT:
  146. table.ChangeSnakeDirect(S_LEFT);
  147. break;
  148. case VK_RIGHT:
  149. table.ChangeSnakeDirect(S_RIGHT);
  150. break;
  151. case VK_SPACE:
  152. if( uGameState == GAME_STATE_END )
  153. {
  154. StartGame();
  155. break;
  156. }
  157. }
  158. return 0;
  159. case WM_SETCURSOR:
  160. SetCursor(NULL);
  161. return 0;
  162. case WM_DESTROY:
  163. ReleaseDC(hWnd,picDC);
  164. ReleaseDC(hWnd,bufferDC);
  165. ReleaseDC(hWnd,windowDC);
  166. PostQuitMessage(0);
  167. return 0;
  168. }
  169. return DefWindowProc(hWnd,message,wParam,lParam);
  170. }
  171. void DrawGame(void)
  172. {
  173. //绘制外壳区域到缓冲
  174. ShellDraw(bufferDC);
  175. //绘制游戏区域到缓冲
  176. GameAreaDraw(bufferDC);
  177. //将整个画面从缓冲DC拷贝出屏幕
  178. BitBlt(windowDC,0,0,g_iClientWidth,g_iClientHeight,bufferDC,0,0,SRCCOPY);
  179. }
  180. void OnTimer(UINT uTIMER_ID)
  181. {
  182. if ( uTIMER_ID == uSnakeMoveTimer )
  183. {
  184. //移动蛇
  185. table.SnakeMove();
  186. //检测是否碰到身体(环绕),结束游戏
  187. if(table.GetSnake()->IsHeadTouchBody(table.GetSnake()->GetPos()[0].x,table.GetSnake()->GetPos()[0].y))
  188. {
  189. EndGame();
  190. }
  191. //根据蛇头所在的区域作出相应的处理
  192. switch(table.GetData(table.GetSnake()->GetPos()[0].x,table.GetSnake()->GetPos()[0].y))
  193. {
  194. case TB_STATE_FOOD:
  195. table.ClearFood(table.GetSnake()->GetPos()[0].x,table.GetSnake()->GetPos()[0].y);
  196. table.AddBlock((rand())%tableBlockWidth,(rand())%tableBlockHeight);
  197. table.GetSnake()->AddBody();
  198. ++iScores;
  199. break;
  200. case TB_STATE_BLOCK:
  201. case TB_STATE_SBLOCK:
  202. //检测是否碰到障碍物,结束游戏
  203. EndGame();
  204. break;
  205. }
  206. //显示
  207. DrawGame();
  208. }
  209. else if ( uTIMER_ID == uFoodAddTimer )
  210. {//定时加食物
  211. table.AddFood((rand())%tableBlockWidth,(rand())%tableBlockHeight);
  212. }
  213. }
  214. void StartGame()
  215. {
  216. iScores=0;
  217. //桌面的初始化
  218. table.InitialTable(tableBlockWidth,tableBlockHeight);
  219. table.GetSnake()->ChangeDirect(S_RIGHT);
  220. table.GetSnake()->SetHeadPos(tableBlockWidth/2,tableBlockHeight/2);
  221. //预先随机产生几个食物
  222. srand( (unsigned)time(NULL) );
  223. for(int iFoodNum=0;  iFoodNum<4; iFoodNum++)
  224. {
  225. table.AddFood((rand())%tableBlockWidth,(rand())%tableBlockHeight);
  226. }
  227. //不部下种子也可以直接用rand(),
  228. //但是每次游戏开始都是产生完全一样的伪随即序列
  229. //打开定时器
  230. uSnakeMoveTimer = SetTimer(hAppWnd,500,100,NULL);
  231. uFoodAddTimer = SetTimer(hAppWnd,600,7000,NULL);
  232. uGameState = GAME_STATE_RUN;
  233. }
  234. void EndGame( void )
  235. {
  236. //关闭定时器
  237. KillTimer(hAppWnd,uSnakeMoveTimer);
  238. KillTimer(hAppWnd,uFoodAddTimer);
  239. uGameState = GAME_STATE_END;
  240. }
  241. void ShellDraw( HDC  hdc )
  242. {
  243. // HDC hMemDc;
  244. // BOOL ret = TRUE;
  245. // HDC hMemoryDC;
  246. // HBITMAP hbmp;
  247. //分数提示显示文字
  248. char szText[30] = "Score: ";
  249. char szNum[20];
  250. int iNowScore = iScores*100;
  251. itoa(iNowScore,szNum,10);
  252. strcat(szText, szNum);
  253. RECT rt, rect;
  254. GetClientRect(hAppWnd, &rt);
  255. //墙的绘制
  256. SelectObject(hdc,hbrushWall);
  257. PatBlt(hdc,rt.left,rt.top,rt.right,rt.bottom,PATCOPY);
  258. //内部游戏区的白色底平面
  259. rect.left = rt.left+WALL_WIDTH;
  260. rect.top = rt.top + WALL_HEIGHT;
  261. rect.right = rt.right - WALL_WIDTH;
  262. rect.bottom = rt.bottom - WALL_HEIGHT;
  263. FillRect(hdc, &rect, (HBRUSH) (COLOR_WINDOW+1));
  264. //分数提示板的绘制
  265. /* hMemoryDC = CreateCompatibleDC(NULL);
  266. hbmp = CreateCompatibleBitmap(hdc,265,55);
  267. SelectObject(hMemoryDC,hbrushScore);
  268. SelectObject(hMemoryDC,hbmp);
  269. PatBlt(hMemoryDC,0,0,256,55,PATCOPY);
  270. BitBlt(hdc,GetSystemMetrics(SM_CXSCREEN)/3,
  271.    10,256,55,hMemoryDC,0,0,SRCCOPY);
  272. */
  273. BitBlt(hdc,GetSystemMetrics(SM_CXSCREEN)/3,
  274.    10,256,55,scoreDC,0,0,SRCCOPY);
  275. //分数的打印绘制
  276. SetBkMode(hdc, TRANSPARENT); 
  277. TextOut(hdc, GetSystemMetrics(SM_CXSCREEN)/3+50, 30,szText,strlen(szText) );
  278. }
  279. void GameAreaDraw(HDC hdc)
  280. {
  281. int i,j;
  282. int x,y, x_pos,y_pos;
  283. BitmapState  state;
  284. char strMark[20];
  285. //绘制水果与 毒果
  286. for(i=0;i<tableBlockHeight;i++)
  287. for(j=0;j<tableBlockWidth;j++)
  288. {
  289. x_pos = j*20+WALL_WIDTH;
  290. y_pos = i*20+WALL_HEIGHT;
  291. switch(table.GetData(j,i))
  292. {
  293. case TB_STATE_FOOD:
  294. BitBlt(hdc,x_pos,y_pos,20,20,picDC,100,0,SRCPAINT);
  295. BitBlt(hdc,x_pos,y_pos,20,20,picDC,20,0,SRCAND);
  296. break;
  297. case TB_STATE_BLOCK:
  298. BitBlt(hdc,x_pos,y_pos,20,20,picDC,80,0,SRCPAINT);
  299. BitBlt(hdc,x_pos,y_pos,20,20,picDC,0,0,SRCAND);
  300. break;
  301. }
  302. }
  303. //根据当前的状态绘制蛇头
  304. x=table.GetSnake()->GetPos()[0].x;
  305. y=table.GetSnake()->GetPos()[0].y;
  306. x_pos = x*20+WALL_WIDTH;
  307. y_pos = y*20+WALL_HEIGHT;
  308. state=table.GetSnake()->GetStateArray()[0];
  309. switch(state)
  310. {
  311. case M_UP_UP:
  312. BitBlt(hdc,x_pos,y_pos,20,20,picDC,80,20,SRCPAINT);
  313. BitBlt(hdc,x_pos,y_pos,20,20,picDC,0,20,SRCAND);
  314. break;
  315. case M_DOWN_DOWN:
  316. BitBlt(hdc,x_pos,y_pos,20,20,picDC,140,20,SRCPAINT);
  317. BitBlt(hdc,x_pos,y_pos,20,20,picDC,60,20,SRCAND);
  318. break;
  319. case M_LEFT_LEFT:
  320. BitBlt(hdc,x_pos,y_pos,20,20,picDC,100,20,SRCPAINT);
  321. BitBlt(hdc,x_pos,y_pos,20,20,picDC,20,20,SRCAND);
  322. break;
  323. case M_RIGHT_RIGHT:
  324. BitBlt(hdc,x_pos,y_pos,20,20,picDC,120,20,SRCPAINT);
  325. BitBlt(hdc,x_pos,y_pos,20,20,picDC,40,20,SRCAND);
  326. break;
  327. }
  328. //根据各个蛇身节点的状态绘制蛇身的形状
  329. for(i=1;i<table.GetSnake()->GetLength()-1;i++)
  330. {
  331. x=table.GetSnake()->GetPos()[i].x;
  332. y=table.GetSnake()->GetPos()[i].y;
  333. x_pos = x*20+WALL_WIDTH;
  334. y_pos = y*20+WALL_HEIGHT;
  335. state=table.GetSnake()->GetStateArray()[i];
  336. switch(state)
  337. {
  338. case M_UP_UP:
  339. case M_DOWN_DOWN:
  340. BitBlt(hdc,x_pos,y_pos,20,20,picDC,80,40,SRCPAINT);
  341. BitBlt(hdc,x_pos,y_pos,20,20,picDC,0,40,SRCAND);
  342. break;
  343. case M_LEFT_LEFT:
  344. case M_RIGHT_RIGHT:
  345. BitBlt(hdc,x_pos,y_pos,20,20,picDC,100,40,SRCPAINT);
  346. BitBlt(hdc,x_pos,y_pos,20,20,picDC,20,40,SRCAND);
  347. break;
  348. case M_RIGHT_DOWN:
  349. case M_UP_LEFT:
  350. BitBlt(hdc,x_pos,y_pos,20,20,picDC,100,60,SRCPAINT);
  351. BitBlt(hdc,x_pos,y_pos,20,20,picDC,20,60,SRCAND);
  352. break;
  353. case M_LEFT_DOWN:
  354. case M_UP_RIGHT:
  355. BitBlt(hdc,x_pos,y_pos,20,20,picDC,80,60,SRCPAINT);
  356. BitBlt(hdc,x_pos,y_pos,20,20,picDC,0,60,SRCAND);
  357. break;
  358. case M_RIGHT_UP:
  359. case M_DOWN_LEFT:
  360. BitBlt(hdc,x_pos,y_pos,20,20,picDC,140,40,SRCPAINT);
  361. BitBlt(hdc,x_pos,y_pos,20,20,picDC,60,40,SRCAND);
  362. break;
  363. case M_LEFT_UP:
  364. case M_DOWN_RIGHT:
  365. BitBlt(hdc,x_pos,y_pos,20,20,picDC,120,40,SRCPAINT);
  366. BitBlt(hdc,x_pos,y_pos,20,20,picDC,40,40,SRCAND);
  367. break;
  368. }
  369. }
  370. //绘制蛇尾巴
  371. x=table.GetSnake()->GetPos()[table.GetSnake()->GetLength()-1].x;
  372. y=table.GetSnake()->GetPos()[table.GetSnake()->GetLength()-1].y;
  373. x_pos = x*20+WALL_WIDTH;
  374. y_pos = y*20+WALL_HEIGHT;
  375. state=table.GetSnake()->GetStateArray()[table.GetSnake()->GetLength()-1];
  376. switch(state)
  377. {
  378. case M_UP_UP:
  379. BitBlt(hdc,x_pos,y_pos,20,20,picDC,120,60,SRCPAINT);
  380. BitBlt(hdc,x_pos,y_pos,20,20,picDC,40,60,SRCAND);
  381. break;
  382. case M_DOWN_DOWN:
  383. BitBlt(hdc,x_pos,y_pos,20,20,picDC,120,0,SRCPAINT);
  384. BitBlt(hdc,x_pos,y_pos,20,20,picDC,40,0,SRCAND);
  385. break;
  386. case M_LEFT_LEFT:
  387. BitBlt(hdc,x_pos,y_pos,20,20,picDC,140,60,SRCPAINT);
  388. BitBlt(hdc,x_pos,y_pos,20,20,picDC,60,60,SRCAND);
  389. break;
  390. case M_RIGHT_RIGHT:
  391. BitBlt(hdc,x_pos,y_pos,20,20,picDC,140,0,SRCPAINT);
  392. BitBlt(hdc,x_pos,y_pos,20,20,picDC,60,0,SRCAND);
  393. break;
  394. }
  395. if(uGameState == GAME_STATE_END)
  396. {//绘制游戏结束图像
  397. int x_pos = g_iClientWidth/3;
  398. int y_pos = g_iClientHeight/4;
  399. BitBlt(hdc, x_pos, y_pos, 369, 300, endDC, 0, 0, SRCCOPY);
  400. }
  401. }