HitCheckDemoDlg.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:12k
源码类别:

游戏

开发平台:

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. BOOL bStop;
  81. RECT rcRect;
  82. DDBLTFX ddbltfx;
  83.     ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
  84.     ddbltfx.dwSize      = sizeof(ddbltfx);
  85.     ddbltfx.dwFillColor = RGB(0,0,0);
  86. bStop = FALSE;
  87.     while(!bStop)
  88. {
  89. ((CHitCheckDemoDlg*)pVoid)->GetWindowRect(&rcRect);
  90. bStop = ((CHitCheckDemoDlg*)pVoid)->m_bStop;
  91. //绘制背景曲面,黑色区域
  92. ((CHitCheckDemoDlg*)pVoid)->m_pBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx );
  93. //绘制飞船
  94. ((CHitCheckDemoDlg*)pVoid)->DrawShip();
  95. //绘制小行星
  96. ((CHitCheckDemoDlg*)pVoid)->DrawAsteroids();
  97. //将背景曲面重绘到前景,即刷屏
  98.         ((CHitCheckDemoDlg*)pVoid)->m_pFrontBuffer->Blt( &rcRect, ((CHitCheckDemoDlg*)pVoid)->m_pBackBuffer,
  99.                                          NULL, DDBLT_WAIT, NULL );
  100. //挂起50毫秒
  101. Sleep(20);
  102. }
  103. return 0;
  104. }
  105. /////////////////////////////////////////////////////////////////////////////
  106. // CHitCheckDemoDlg message handlers
  107. BOOL CHitCheckDemoDlg::OnInitDialog()
  108. {
  109. CDialog::OnInitDialog();
  110. // Add "About..." menu item to system menu.
  111. // IDM_ABOUTBOX must be in the system command range.
  112. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  113. ASSERT(IDM_ABOUTBOX < 0xF000);
  114. CMenu* pSysMenu = GetSystemMenu(FALSE);
  115. if (pSysMenu != NULL)
  116. {
  117. CString strAboutMenu;
  118. strAboutMenu.LoadString(IDS_ABOUTBOX);
  119. if (!strAboutMenu.IsEmpty())
  120. {
  121. pSysMenu->AppendMenu(MF_SEPARATOR);
  122. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  123. }
  124. }
  125. // Set the icon for this dialog.  The framework does this automatically
  126. //  when the application's main window is not a dialog
  127. SetIcon(m_hIcon, TRUE); // Set big icon
  128. SetIcon(m_hIcon, FALSE); // Set small icon
  129. // TODO: Add extra initialization here
  130. //初始化DirectX
  131. InitDirectX();
  132. //载入碰撞信息的文字曲面:“Ship Hitted!”
  133. m_surfShipHitted.Create(80,16, RGB(0,0,0));
  134. m_surfShipHitted.LoadBitmap(AfxGetInstanceHandle(), IDB_SHIPHITTED, 0,0, 80, 16);
  135. //使用cSurface创建小行星和飞船的曲面(平面)
  136. m_surfShip.Create(60,60, RGB(0,0,0));
  137. m_surfShip.LoadBitmap(AfxGetInstanceHandle(), IDB_SPACESHIP, 0,0, 60, 60);
  138. m_surfAsteroid.Create(60,60, RGB(0,0,0));
  139. m_surfAsteroid.LoadBitmap(AfxGetInstanceHandle(), IDB_ASTEROID, 0,0, 50, 50);
  140. //把飞船放到屏幕底部的中间位置
  141. RECT rcRect;
  142. this->GetWindowRect(&rcRect);
  143. pShipPos.x = (rcRect.right - rcRect.left - 60)/2;
  144. pShipPos.y = rcRect.bottom - 70;
  145. m_iIncrement = 0;
  146. //初始化3个小行星的位置
  147. m_pAsteroid1.x = 40;
  148. m_pAsteroid1.y = 0;
  149. m_pAsteroid2.x = 230;
  150. m_pAsteroid2.y = 0;
  151. m_pAsteroid3.x = 380;
  152. m_pAsteroid3.y = 0;
  153. // Here we will create the Heat Checker objects 
  154. // for each one of the objects, Asteroid and Ship
  155. //创建飞船边界的多边形顶点数组
  156. POINT lpPointsShip[] = { {5,42},  {22,48}, {22,52}, {38,52}, 
  157. {38,47}, {54,41}, {54,29}, {37,8},
  158. {31,15}, {28,15}, {22,8}, {5,31} };
  159. //利用上面的数组,创建飞船碰撞检测类
  160. m_hcShip.CreatePolygonBound(lpPointsShip, 12);
  161. //创建小行星的多边形顶点数组
  162. POINT lpPointsAsteroid[] = { {8,31},  {22,46}, {37,38}, {49,26}, 
  163. {37,9}, {19,6}, {10,6}, {8,16} };
  164. //利用上面的数组,创建小行星碰撞检测类
  165. m_hcAsteroid.CreatePolygonBound(lpPointsAsteroid, 8);
  166. //停止运动标志
  167. m_bStop = FALSE;
  168. //创建绘制线程,线程参数就是这个对话框类
  169. AfxBeginThread(UpdateFrame, this);
  170. return TRUE;  // return TRUE  unless you set the focus to a control
  171. }
  172. void CHitCheckDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
  173. {
  174. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  175. {
  176. CAboutDlg dlgAbout;
  177. dlgAbout.DoModal();
  178. }
  179. else
  180. {
  181. CDialog::OnSysCommand(nID, lParam);
  182. }
  183. }
  184. // If you add a minimize button to your dialog, you will need the code below
  185. //  to draw the icon.  For MFC applications using the document/view model,
  186. //  this is automatically done for you by the framework.
  187. void CHitCheckDemoDlg::OnPaint() 
  188. {
  189. if (IsIconic())
  190. {
  191. CPaintDC dc(this); // device context for painting
  192. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  193. // Center icon in client rectangle
  194. int cxIcon = GetSystemMetrics(SM_CXICON);
  195. int cyIcon = GetSystemMetrics(SM_CYICON);
  196. CRect rect;
  197. GetClientRect(&rect);
  198. int x = (rect.Width() - cxIcon + 1) / 2;
  199. int y = (rect.Height() - cyIcon + 1) / 2;
  200. // Draw the icon
  201. dc.DrawIcon(x, y, m_hIcon);
  202. }
  203. else
  204. {
  205. CDialog::OnPaint();
  206. }
  207. }
  208. // The system calls this to obtain the cursor to display while the user drags
  209. //  the minimized window.
  210. HCURSOR CHitCheckDemoDlg::OnQueryDragIcon()
  211. {
  212. return (HCURSOR) m_hIcon;
  213. }
  214. //初始化DirectX
  215. void CHitCheckDemoDlg::InitDirectX()
  216. {
  217. HRESULT hRet;
  218. LPDIRECTDRAW pDD;
  219.     DDSURFACEDESC2 ddsd;
  220.     DDSCAPS2 ddscaps;
  221.     LPDIRECTDRAWCLIPPER pcClipper;
  222. // 首先,创建DirectX对象
  223. hRet = DirectDrawCreate( NULL, &pDD, NULL );
  224. if(hRet != DD_OK)
  225. {
  226. return;
  227. }
  228.     //取DirectDraw7接口
  229.     hRet = pDD->QueryInterface(IID_IDirectDraw7, (LPVOID*)&m_pDD);
  230. if(hRet != DD_OK)
  231. {
  232. return;
  233. }
  234. //既然不再需要DirectDraw接口,所以释放掉
  235. pDD->Release();
  236.     
  237. //确定应用程序的显示方式,正常的窗口显示方式
  238. hRet = m_pDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL);
  239. if(hRet != DD_OK)
  240. {
  241. return;
  242. }
  243.     
  244. //创建主曲面,这里我们不使用cSurface创建而是直接使用IDirectDraw7
  245.     ZeroMemory( &ddsd, sizeof( ddsd ) );
  246.     ddsd.dwSize = sizeof( ddsd );
  247.     ddsd.dwFlags = DDSD_CAPS;
  248.     //创建主曲面,在DirectX中,主曲面需要用主DirectDrawSurface对象表示。
  249. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  250.     //ddsd.dwBackBufferCount = 1;
  251.     //m_pFrontBuffer被DirectDraw对象创建为主曲面
  252. hRet = m_pDD->CreateSurface(&ddsd, &m_pFrontBuffer, NULL );
  253. if(hRet != DD_OK)
  254. {
  255. return;
  256. }
  257.     // Create back buffer
  258.     
  259. ZeroMemory(&ddscaps, sizeof(ddscaps));
  260. RECT rcRect;
  261. this->GetWindowRect(&rcRect);
  262.     //创建后台缓冲曲面
  263.     ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;    
  264.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
  265.     ddsd.dwWidth        = rcRect.right  - rcRect.left;
  266.     ddsd.dwHeight       = rcRect.bottom - rcRect.top;
  267. ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  268.     hRet = m_pDD->CreateSurface( &ddsd, &m_pBackBuffer, NULL );
  269. if(hRet != DD_OK)
  270. {
  271. return;
  272. }
  273. //创建DirectDraw裁剪对象
  274.     if( FAILED( hRet = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) )
  275.         return;
  276. //裁剪对象设置主窗口
  277.     if( FAILED( hRet = pcClipper->SetHWnd( 0, m_hWnd ) ) )
  278.     {
  279.         pcClipper->Release();
  280.         return;
  281.     }
  282. //设置前台缓冲的裁剪对象
  283.     if( FAILED( hRet = m_pFrontBuffer->SetClipper( pcClipper ) ) )
  284.     {
  285.         pcClipper->Release();
  286.         return;
  287.     }
  288.     //释放裁剪对象
  289.     pcClipper->Release();
  290.     
  291. DDBLTFX ddbltfx;
  292.     ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
  293.     ddbltfx.dwSize      = sizeof(ddbltfx);
  294.     ddbltfx.dwFillColor = RGB(0,0,0);
  295. //Blt函数用来进行位块信息传输
  296.     m_pBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx );
  297. }
  298. void CHitCheckDemoDlg::OnClose() 
  299. {
  300. //设置线程结束标志
  301. m_bStop = TRUE;
  302. //休眠一会,等待绘制线程结束
  303. Sleep(100);
  304. // TODO: Add your message handler code here and/or call default
  305. //释放前台缓冲、后台缓冲和DirectDraw对象
  306.     if( m_pBackBuffer != NULL )
  307.         m_pBackBuffer->Release();
  308. if( m_pFrontBuffer != NULL )
  309.         m_pFrontBuffer->Release();
  310.     if( m_pDD != NULL )
  311.         m_pDD->Release();
  312. CDialog::OnClose();
  313. }
  314. //绘制飞船
  315. void CHitCheckDemoDlg::DrawShip()
  316. {
  317. RECT rcRect;
  318. GetWindowRect(&rcRect);
  319. //滑动飞船的水平位置
  320. pShipPos.x += m_iIncrement;
  321. //如果飞船到了边界则停下来
  322. if(pShipPos.x == 0)
  323. m_iIncrement = 0;
  324. if(pShipPos.x == rcRect.right-60)
  325. m_iIncrement = 0;
  326. //在背景绘制表面绘制飞船
  327. m_surfShip.Draw(m_pBackBuffer, pShipPos.x, pShipPos.y);
  328. }
  329. //绘制小行星
  330. void CHitCheckDemoDlg::DrawAsteroids()
  331. {
  332. // Draw each one of the 3 asteroids
  333. RECT rcRect;
  334. GetWindowRect(&rcRect);
  335. //绘制三个小行星
  336. m_surfAsteroid.Draw(m_pBackBuffer, m_pAsteroid1.x, m_pAsteroid1.y);
  337. m_surfAsteroid.Draw(m_pBackBuffer, m_pAsteroid2.x, m_pAsteroid2.y);
  338. m_surfAsteroid.Draw(m_pBackBuffer, m_pAsteroid3.x, m_pAsteroid3.y);
  339. //改变小行星的位置
  340. m_pAsteroid1.y++;
  341. m_pAsteroid2.y+=2;
  342. m_pAsteroid3.y+=3;
  343. if(m_pAsteroid1.y > rcRect.bottom -rcRect.top- 51)
  344. m_pAsteroid1.y = 40;
  345. if(m_pAsteroid2.y > rcRect.bottom - rcRect.top - 51)
  346. m_pAsteroid2.y = 40;
  347. if(m_pAsteroid3.y > rcRect.bottom - rcRect.top - 51)
  348. m_pAsteroid3.y = 40;
  349. //分别测试3个小行星是否和飞船发生了碰撞
  350. if(m_hcShip.HaveHitted(&m_hcAsteroid,m_pAsteroid1.x, m_pAsteroid1.y, pShipPos.x, pShipPos.y) == TRUE)
  351. {
  352. //显示Ship Hitted!
  353. m_surfShipHitted.Draw(m_pBackBuffer, 10,40,0,0);
  354. OutputDebugString("Ship Hitted by Asteroid 1!n");
  355. }
  356. if(m_hcShip.HaveHitted(&m_hcAsteroid,m_pAsteroid2.x, m_pAsteroid2.y, pShipPos.x, pShipPos.y) == TRUE)
  357. {
  358. m_surfShipHitted.Draw(m_pBackBuffer, 10,40,0,0);
  359. OutputDebugString("Ship Hitted by Asteroid 2!n");
  360. }
  361. if(m_hcShip.HaveHitted(&m_hcAsteroid,m_pAsteroid3.x, m_pAsteroid3.y, pShipPos.x, pShipPos.y) == TRUE)
  362. {
  363. m_surfShipHitted.Draw(m_pBackBuffer, 10,40,0,0);
  364. OutputDebugString("Ship Hitted by Asteroid 3!n");
  365. }
  366. }
  367. //需要在PreTranslateMessage中截获对话框中键盘消息,而不是OnKeyDown消息相应函数
  368. BOOL CHitCheckDemoDlg::PreTranslateMessage(MSG* pMsg) 
  369. {
  370. // TODO: Add your specialized code here and/or call the base class
  371. if(pMsg->message == WM_KEYDOWN)
  372. {
  373. int nVirtKey = (int) pMsg->wParam;
  374. switch(nVirtKey)
  375. {
  376. case VK_LEFT:
  377. m_iIncrement = -1;
  378. break;
  379. case VK_RIGHT:
  380. m_iIncrement = +1;
  381. break;
  382. case VK_DOWN:
  383. m_iIncrement = 0;
  384. break;
  385. }
  386. }
  387. return CDialog::PreTranslateMessage(pMsg);
  388. }