HitCheckDemoDlg.cpp
上传用户:taoyan1984
上传日期:2010-03-01
资源大小:30k
文件大小:14k
源码类别:

射击游戏

开发平台:

Visual C++

  1. // HitCheckDemoDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "HitCheckDemo.h"
  5. #include "HitCheckDemoDlg.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. /////////////////////////////////////////////////////////////////////////////
  12. // CAboutDlg dialog used for App About
  13. class CAboutDlg : public CDialog
  14. {
  15. public:
  16. CAboutDlg();
  17. // Dialog Data
  18. //{{AFX_DATA(CAboutDlg)
  19. enum { IDD = IDD_ABOUTBOX };
  20. //}}AFX_DATA
  21. // ClassWizard generated virtual function overrides
  22. //{{AFX_VIRTUAL(CAboutDlg)
  23. protected:
  24. virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  25. //}}AFX_VIRTUAL
  26. // Implementation
  27. protected:
  28. //{{AFX_MSG(CAboutDlg)
  29. //}}AFX_MSG
  30. DECLARE_MESSAGE_MAP()
  31. };
  32. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  33. {
  34. //{{AFX_DATA_INIT(CAboutDlg)
  35. //}}AFX_DATA_INIT
  36. }
  37. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  38. {
  39. CDialog::DoDataExchange(pDX);
  40. //{{AFX_DATA_MAP(CAboutDlg)
  41. //}}AFX_DATA_MAP
  42. }
  43. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  44. //{{AFX_MSG_MAP(CAboutDlg)
  45. //}}AFX_MSG_MAP
  46. END_MESSAGE_MAP()
  47. /////////////////////////////////////////////////////////////////////////////
  48. // CHitCheckDemoDlg dialog
  49. LPDIRECTDRAW7 GetDirectDraw()
  50. {
  51. return ((CHitCheckDemoDlg*)AfxGetMainWnd())->m_pDD;
  52. }
  53. CHitCheckDemoDlg::CHitCheckDemoDlg(CWnd* pParent /*=NULL*/)
  54. : CDialog(CHitCheckDemoDlg::IDD, pParent)
  55. {
  56. //{{AFX_DATA_INIT(CHitCheckDemoDlg)
  57. // NOTE: the ClassWizard will add member initialization here
  58. //}}AFX_DATA_INIT
  59. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  60. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  61. }
  62. void CHitCheckDemoDlg::DoDataExchange(CDataExchange* pDX)
  63. {
  64. CDialog::DoDataExchange(pDX);
  65. //{{AFX_DATA_MAP(CHitCheckDemoDlg)
  66. // NOTE: the ClassWizard will add DDX and DDV calls here
  67. //}}AFX_DATA_MAP
  68. }
  69. BEGIN_MESSAGE_MAP(CHitCheckDemoDlg, CDialog)
  70. //{{AFX_MSG_MAP(CHitCheckDemoDlg)
  71. ON_WM_SYSCOMMAND()
  72. ON_WM_PAINT()
  73. ON_WM_QUERYDRAGICON()
  74. ON_WM_CLOSE()
  75. //}}AFX_MSG_MAP
  76. END_MESSAGE_MAP()
  77. //画面绘制的线程函数UpdateFrame
  78. UINT UpdateFrame(LPVOID pVoid)
  79. {
  80. CHitCheckDemoDlg* pWnd;
  81. BOOL bStop;
  82. RECT rcRect;
  83. DDBLTFX ddbltfx;
  84.     ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
  85.     ddbltfx.dwSize      = sizeof(ddbltfx);
  86.     ddbltfx.dwFillColor = RGB(0, 255, 0);
  87. pWnd = (CHitCheckDemoDlg*)pVoid;
  88. bStop = FALSE;
  89.     while(!bStop)
  90. {
  91. pWnd->GetWindowRect(&rcRect);
  92. bStop = pWnd->m_bStop;
  93. //绘制背景曲面,黑色区域
  94. pWnd->m_pBackBuffer->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx);
  95. //绘制飞船
  96. pWnd->DrawShip();
  97. //绘制小行星
  98. pWnd->DrawAsteroids();
  99. //将背景曲面重绘到前景,即刷屏
  100.         if( pWnd->m_pFrontBuffer->Blt(&rcRect, pWnd->m_pBackBuffer, NULL, DDBLT_WAIT, NULL) == DDERR_SURFACELOST) 
  101. pWnd->m_pDD->RestoreAllSurfaces();
  102. //挂起50毫秒
  103. Sleep(20);
  104. }
  105. return 0;
  106. }
  107. /////////////////////////////////////////////////////////////////////////////
  108. // CHitCheckDemoDlg message handlers
  109. BOOL CHitCheckDemoDlg::OnInitDialog()
  110. {
  111. CDialog::OnInitDialog();
  112. // Add "About..." menu item to system menu.
  113. // IDM_ABOUTBOX must be in the system command range.
  114. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  115. ASSERT(IDM_ABOUTBOX < 0xF000);
  116. CMenu* pSysMenu = GetSystemMenu(FALSE);
  117. if (pSysMenu != NULL)
  118. {
  119. CString strAboutMenu;
  120. strAboutMenu.LoadString(IDS_ABOUTBOX);
  121. if (!strAboutMenu.IsEmpty())
  122. {
  123. pSysMenu->AppendMenu(MF_SEPARATOR);
  124. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  125. }
  126. }
  127. // Set the icon for this dialog.  The framework does this automatically
  128. //  when the application's main window is not a dialog
  129. SetIcon(m_hIcon, TRUE); // Set big icon
  130. SetIcon(m_hIcon, FALSE); // Set small icon
  131. // TODO: Add extra initialization here
  132. //初始化DirectX
  133. InitDirectX();
  134. //载入碰撞信息的文字曲面:“Ship Hitted!”
  135. m_surfShipHitted.Create(80,16, RGB(0, 0, 0));
  136. m_surfShipHitted.LoadBitmap(AfxGetInstanceHandle(), IDB_SHIPHITTED, 0,0, 80, 16);
  137. //使用cSurface创建小行星和飞船的曲面(平面)
  138. m_surfShip.Create(60,60, RGB(0, 0, 0));
  139. m_surfShip.LoadBitmap(AfxGetInstanceHandle(), IDB_SPACESHIP, 0,0, 60, 60);
  140. m_surfAsteroid.Create(60,60, RGB(0, 0, 0));
  141. m_surfAsteroid.LoadBitmap(AfxGetInstanceHandle(), IDB_ASTEROID, 0,0, 50, 50);
  142. //把飞船放到屏幕底部的中间位置
  143. RECT rcRect;
  144. this->GetWindowRect(&rcRect);
  145. pShipPos.x = (rcRect.right - rcRect.left - 60)/2;
  146. pShipPos.y = rcRect.bottom - 70;
  147. m_xIncrement = 0;
  148. m_yIncrement = 0;
  149. //初始化3个小行星的位置
  150. srand(time(NULL));
  151. m_pAsteroid1.x = rand() % (rcRect.right - rcRect.left);
  152. m_pAsteroid1.y = 0;
  153. m_pAsteroid2.x = rand() % (rcRect.right - rcRect.left);
  154. m_pAsteroid2.y = 0;
  155. m_pAsteroid3.x = rand() % (rcRect.right - rcRect.left);
  156. m_pAsteroid3.y = 0;
  157. // Here we will create the Heat Checker objects 
  158. // for each one of the objects, Asteroid and Ship
  159. //创建飞船边界的多边形顶点数组
  160. POINT lpPointsShip[] = { {5,42},  {22,48}, {22,52}, {38,52}, 
  161. {38,47}, {54,41}, {54,29}, {37,8},
  162. {31,15}, {28,15}, {22,8}, {5,31} };
  163. //利用上面的数组,创建飞船碰撞检测类
  164. m_hcShip.CreatePolygonBound(lpPointsShip, 12);
  165. //创建小行星的多边形顶点数组
  166. POINT lpPointsAsteroid[] = { {8,31},  {22,46}, {37,38}, {49,26}, 
  167. {37,9}, {19,6}, {10,6}, {8,16} };
  168. //利用上面的数组,创建小行星碰撞检测类
  169. m_hcAsteroid.CreatePolygonBound(lpPointsAsteroid, 8);
  170. //停止运动标志
  171. m_bStop = FALSE;
  172. //创建绘制线程,线程参数就是这个对话框类
  173. AfxBeginThread(UpdateFrame, this);
  174. return TRUE;  // return TRUE  unless you set the focus to a control
  175. }
  176. void CHitCheckDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
  177. {
  178. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  179. {
  180. CAboutDlg dlgAbout;
  181. dlgAbout.DoModal();
  182. }
  183. else
  184. {
  185. CDialog::OnSysCommand(nID, lParam);
  186. }
  187. }
  188. // If you add a minimize button to your dialog, you will need the code below
  189. //  to draw the icon.  For MFC applications using the document/view model,
  190. //  this is automatically done for you by the framework.
  191. void CHitCheckDemoDlg::OnPaint() 
  192. {
  193. if (IsIconic())
  194. {
  195. CPaintDC dc(this); // device context for painting
  196. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  197. // Center icon in client rectangle
  198. int cxIcon = GetSystemMetrics(SM_CXICON);
  199. int cyIcon = GetSystemMetrics(SM_CYICON);
  200. CRect rect;
  201. GetClientRect(&rect);
  202. int x = (rect.Width() - cxIcon + 1) / 2;
  203. int y = (rect.Height() - cyIcon + 1) / 2;
  204. // Draw the icon
  205. dc.DrawIcon(x, y, m_hIcon);
  206. }
  207. else
  208. {
  209. CDialog::OnPaint();
  210. }
  211. }
  212. // The system calls this to obtain the cursor to display while the user drags
  213. //  the minimized window.
  214. HCURSOR CHitCheckDemoDlg::OnQueryDragIcon()
  215. {
  216. return (HCURSOR) m_hIcon;
  217. }
  218. //初始化DirectX
  219. void CHitCheckDemoDlg::InitDirectX()
  220. {
  221. HRESULT hRet;
  222.     DDSURFACEDESC2 ddsd;
  223.     DDSCAPS2 ddscaps;
  224.     LPDIRECTDRAWCLIPPER pcClipper;
  225. // 首先,创建DirectX对象
  226. // hRet = DirectDrawCreate(NULL, &pDD, NULL);
  227. // if(hRet != DD_OK)
  228. {
  229. // return;
  230. }
  231.     //取DirectDraw7接口
  232. //    hRet = pDD->QueryInterface(IID_IDirectDraw7, (LPVOID*)&m_pDD);
  233. // if(hRet != DD_OK)
  234. {
  235. // return;
  236. }
  237. // 首先,创建DirectX对
  238. if(DirectDrawCreateEx(NULL, (LPVOID*)&m_pDD, IID_IDirectDraw7, NULL) != DD_OK)
  239. return;
  240. //既然不再需要DirectDraw接口,所以释放掉
  241. //pDD->Release();
  242.     
  243. //确定应用程序的显示方式,正常的窗口显示方式
  244. if( MessageBox("全屏显示吗?", NULL, MB_YESNO) == IDYES )
  245. {
  246. hRet = m_pDD->SetCooperativeLevel(m_hWnd, DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT);
  247. hRet = m_pDD->SetDisplayMode(800, 600, 16, 0, 0);
  248. }
  249. else
  250. hRet = m_pDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL);
  251. if(hRet != DD_OK)
  252. {
  253. return;
  254. }
  255.     
  256. //创建主曲面,这里我们不使用cSurface创建而是直接使用IDirectDraw7
  257.     ZeroMemory( &ddsd, sizeof( ddsd ) );
  258.     ddsd.dwSize = sizeof( ddsd );
  259.     ddsd.dwFlags = DDSD_CAPS;
  260.     //创建主曲面,在DirectX中,主曲面需要用主DirectDrawSurface对象表示。
  261. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  262.     //ddsd.dwBackBufferCount = 1;
  263.     //m_pFrontBuffer被DirectDraw对象创建为主曲面
  264. hRet = m_pDD->CreateSurface(&ddsd, &m_pFrontBuffer, NULL );
  265. if(hRet != DD_OK)
  266. {
  267. return;
  268. }
  269.     // Create back buffer
  270.     
  271. ZeroMemory(&ddscaps, sizeof(ddscaps));
  272. RECT rcRect;
  273. this->GetWindowRect(&rcRect);
  274.     //创建后台缓冲曲面
  275.     ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;    
  276.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
  277.     ddsd.dwWidth        = rcRect.right  - rcRect.left;
  278.     ddsd.dwHeight       = rcRect.bottom - rcRect.top;
  279. ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  280.     hRet = m_pDD->CreateSurface( &ddsd, &m_pBackBuffer, NULL );
  281. if(hRet != DD_OK)
  282. {
  283. return;
  284. }
  285. //创建DirectDraw裁剪对象
  286.     if( FAILED( hRet = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) )
  287.         return;
  288. //裁剪对象设置主窗口
  289.     if( FAILED( hRet = pcClipper->SetHWnd( 0, m_hWnd ) ) )
  290.     {
  291.         pcClipper->Release();
  292.         return;
  293.     }
  294. //设置前台缓冲的裁剪对象
  295.     if( FAILED( hRet = m_pFrontBuffer->SetClipper( pcClipper ) ) )
  296.     {
  297.         pcClipper->Release();
  298.         return;
  299.     }
  300.     //释放裁剪对象
  301.     pcClipper->Release();
  302.     
  303. DDBLTFX ddbltfx;
  304.     ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
  305.     ddbltfx.dwSize      = sizeof(ddbltfx);
  306.     ddbltfx.dwFillColor = RGB(0, 255, 0);
  307. //Blt函数用来进行位块信息传输
  308.     m_pBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx );
  309. }
  310. void CHitCheckDemoDlg::OnClose() 
  311. {
  312. //设置线程结束标志
  313. m_bStop = TRUE;
  314. //休眠一会,等待绘制线程结束
  315. Sleep(100);
  316. // TODO: Add your message handler code here and/or call default
  317. //释放前台缓冲、后台缓冲和DirectDraw对象
  318.     if( m_pBackBuffer != NULL )
  319.         m_pBackBuffer->Release();
  320. if( m_pFrontBuffer != NULL )
  321.         m_pFrontBuffer->Release();
  322.     if( m_pDD != NULL )
  323.         m_pDD->Release();
  324. CDialog::OnClose();
  325. }
  326. //绘制飞船
  327. void CHitCheckDemoDlg::DrawShip()
  328. {
  329. RECT rcRect;
  330. GetClientRect(&rcRect);
  331. //滑动飞船的水平位置
  332. pShipPos.x += m_xIncrement;
  333. pShipPos.y += m_yIncrement;
  334. //如果飞船到了边界则停下来
  335. if(pShipPos.x < 5)
  336. pShipPos.x = rcRect.right - 60;
  337. if(pShipPos.x > rcRect.right - 60)
  338. pShipPos.x = 5;
  339. if(pShipPos.y < rcRect.top + 5)
  340. pShipPos.y = rcRect.bottom - 35;
  341. if(pShipPos.y > rcRect.bottom - 35)
  342. pShipPos.y = rcRect.top + 5;
  343. //在背景绘制表面绘制飞船
  344. m_surfShip.Draw(m_pBackBuffer, pShipPos.x, pShipPos.y);
  345. }
  346. //绘制小行星
  347. void CHitCheckDemoDlg::DrawAsteroids()
  348. {
  349. RECT rcRect;
  350. HDC hdc;
  351. char str[256];
  352. GetWindowRect(&rcRect);
  353. if( m_pBackBuffer->GetDC(&hdc) == DD_OK )
  354. {
  355. //分别测试3个小行星是否和飞船发生了碰撞
  356. if(m_hcShip.HaveHitted(&m_hcAsteroid,m_pAsteroid1.x, m_pAsteroid1.y, pShipPos.x, pShipPos.y) == TRUE)
  357. {
  358. //显示Ship Hitted!
  359. //m_surfShipHitted.Draw(m_pBackBuffer, 10,40,0,0);
  360. //OutputDebugString("Ship Hitted by Asteroid 1!n");
  361. SetBkColor(hdc, RGB(0, 0, 255));
  362. SetTextColor(hdc, RGB(255, 0, 0));
  363. strcpy(str, "Ship Hitted by Asteroid 1!");
  364. TextOut(hdc, 10, 40, str,strlen(str));
  365. srand(rand());
  366. m_pAsteroid1.x = rand() % (rcRect.right - rcRect.left);
  367. m_pAsteroid1.y = 40;
  368. }
  369. if(m_hcShip.HaveHitted(&m_hcAsteroid,m_pAsteroid2.x, m_pAsteroid2.y, pShipPos.x, pShipPos.y) == TRUE)
  370. {
  371. //m_surfShipHitted.Draw(m_pBackBuffer, 10,40,0,0);
  372. //OutputDebugString("Ship Hitted by Asteroid 2!n");
  373. SetBkColor(hdc, RGB(0, 0, 255));
  374. SetTextColor(hdc, RGB(255, 0, 0));
  375. strcpy(str, "Ship Hitted by Asteroid 2!");
  376. TextOut(hdc, 10, 40, str,strlen(str));
  377. srand(rand());
  378. m_pAsteroid2.x = rand() % (rcRect.right - rcRect.left);
  379. m_pAsteroid2.y = 40;
  380. }
  381. if(m_hcShip.HaveHitted(&m_hcAsteroid,m_pAsteroid3.x, m_pAsteroid3.y, pShipPos.x, pShipPos.y) == TRUE)
  382. {
  383. //m_surfShipHitted.Draw(m_pBackBuffer, 10,40,0,0);
  384. //OutputDebugString("Ship Hitted by Asteroid 3!n");
  385. SetBkColor(hdc, RGB(0, 0, 255));
  386. SetTextColor(hdc, RGB(255, 0, 0));
  387. strcpy(str, "Ship Hitted by Asteroid 3!");
  388. TextOut(hdc, 10, 40, str,strlen(str));
  389. srand(rand());
  390. m_pAsteroid3.x = rand() % (rcRect.right - rcRect.left);
  391. m_pAsteroid3.y = 40;
  392. }
  393. m_pBackBuffer->ReleaseDC(hdc);
  394. }
  395. //绘制三个小行星
  396. m_surfAsteroid.Draw(m_pBackBuffer, m_pAsteroid1.x, m_pAsteroid1.y);
  397. m_surfAsteroid.Draw(m_pBackBuffer, m_pAsteroid2.x, m_pAsteroid2.y);
  398. m_surfAsteroid.Draw(m_pBackBuffer, m_pAsteroid3.x, m_pAsteroid3.y);
  399. //改变小行星的位置
  400. m_pAsteroid1.y++;
  401. m_pAsteroid2.y+=2;
  402. m_pAsteroid3.y+=3;
  403. if( m_pAsteroid1.y > rcRect.bottom - rcRect.top- 51 )
  404. {
  405. srand(rand());
  406. m_pAsteroid1.x = rand() % (rcRect.right - rcRect.left);
  407. m_pAsteroid1.y = 40;
  408. }
  409. if(m_pAsteroid2.y > rcRect.bottom - rcRect.top - 51)
  410. {
  411. srand(rand());
  412. m_pAsteroid2.x = rand() % (rcRect.right - rcRect.left);
  413. m_pAsteroid2.y = 40;
  414. }
  415. if(m_pAsteroid3.y > rcRect.bottom - rcRect.top - 51)
  416. {
  417. srand(rand());
  418. m_pAsteroid3.x = rand() % (rcRect.right - rcRect.left);
  419. m_pAsteroid3.y = 40;
  420. }
  421. }
  422. //需要在PreTranslateMessage中截获对话框中键盘消息,而不是OnKeyDown消息相应函数
  423. BOOL CHitCheckDemoDlg::PreTranslateMessage(MSG* pMsg) 
  424. {
  425. // TODO: Add your specialized code here and/or call the base class
  426. if(pMsg->message == WM_KEYDOWN)
  427. {
  428. switch(pMsg->wParam)
  429. {
  430. case VK_LEFT:
  431. m_xIncrement = -8;
  432. m_yIncrement = 0;
  433. break;
  434. case VK_RIGHT:
  435. m_xIncrement = +8;
  436. m_yIncrement = 0;
  437. break;
  438. case VK_UP:
  439. m_yIncrement = -8;
  440. m_xIncrement = 0;
  441. break;
  442. case VK_DOWN:
  443. m_yIncrement = +8;
  444. m_xIncrement = 0;
  445. break;
  446. }
  447. }
  448. return CDialog::PreTranslateMessage(pMsg);
  449. }
  450. void CHitCheckDemoDlg::OnCancel() 
  451. {
  452. if( MessageBox("Exit the Game?", NULL, MB_YESNO) == IDYES )
  453. CDialog::OnCancel();
  454. }
  455. void CHitCheckDemoDlg::OnOK() 
  456. {
  457. if( MessageBox("Close the Game?", NULL, MB_YESNO) == IDYES )
  458. CDialog::OnOK();
  459. }