⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hitcheckdemodlg.cpp

📁 游戏的算法 碰撞检测 开发环境是VC 库DIRECTX8.1
💻 CPP
字号:
// HitCheckDemoDlg.cpp : implementation file
//

#include "stdafx.h"
#include "HitCheckDemo.h"
#include "HitCheckDemoDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHitCheckDemoDlg dialog
LPDIRECTDRAW7	GetDirectDraw()
{
	return ((CHitCheckDemoDlg*)AfxGetMainWnd())->m_pDD;
}

CHitCheckDemoDlg::CHitCheckDemoDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CHitCheckDemoDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CHitCheckDemoDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CHitCheckDemoDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CHitCheckDemoDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CHitCheckDemoDlg, CDialog)
	//{{AFX_MSG_MAP(CHitCheckDemoDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_CLOSE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

//画面绘制的线程函数UpdateFrame
UINT UpdateFrame(LPVOID	pVoid)
{
	BOOL	bStop;
	RECT	rcRect;

	DDBLTFX ddbltfx;
    ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
    ddbltfx.dwSize      = sizeof(ddbltfx);
    ddbltfx.dwFillColor = RGB(0,0,0);


	bStop = FALSE;
    while(!bStop)
	{
		((CHitCheckDemoDlg*)pVoid)->GetWindowRect(&rcRect);
		bStop = ((CHitCheckDemoDlg*)pVoid)->m_bStop;
		//绘制背景曲面,黑色区域
		((CHitCheckDemoDlg*)pVoid)->m_pBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx );
		//绘制飞船
		((CHitCheckDemoDlg*)pVoid)->DrawShip();
		//绘制小行星
		((CHitCheckDemoDlg*)pVoid)->DrawAsteroids();


		//将背景曲面重绘到前景,即刷屏
        ((CHitCheckDemoDlg*)pVoid)->m_pFrontBuffer->Blt( &rcRect, ((CHitCheckDemoDlg*)pVoid)->m_pBackBuffer,
                                         NULL, DDBLT_WAIT, NULL );
		//挂起50毫秒
		Sleep(20);
	}

	return 0;
}

/////////////////////////////////////////////////////////////////////////////
// CHitCheckDemoDlg message handlers

BOOL CHitCheckDemoDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here

	//初始化DirectX
	InitDirectX();

	//载入碰撞信息的文字曲面:“Ship Hitted!”
	m_surfShipHitted.Create(80,16, RGB(0,0,0));
	m_surfShipHitted.LoadBitmap(AfxGetInstanceHandle(), IDB_SHIPHITTED, 0,0, 80, 16);

	//使用cSurface创建小行星和飞船的曲面(平面)
	m_surfShip.Create(60,60, RGB(0,0,0));
	m_surfShip.LoadBitmap(AfxGetInstanceHandle(), IDB_SPACESHIP, 0,0, 60, 60);

	m_surfAsteroid.Create(60,60, RGB(0,0,0));
	m_surfAsteroid.LoadBitmap(AfxGetInstanceHandle(), IDB_ASTEROID, 0,0, 50, 50);

	//把飞船放到屏幕底部的中间位置
	RECT	rcRect;
	this->GetWindowRect(&rcRect);
	pShipPos.x = (rcRect.right - rcRect.left - 60)/2;
	pShipPos.y = rcRect.bottom - 70;
	m_iIncrement = 0;

	//初始化3个小行星的位置
	m_pAsteroid1.x = 40;
	m_pAsteroid1.y = 0;

	m_pAsteroid2.x = 230;
	m_pAsteroid2.y = 0;

	m_pAsteroid3.x = 380;
	m_pAsteroid3.y = 0;
	
	
	// Here we will create the Heat Checker objects 
	// for each one of the objects, Asteroid and Ship

	//创建飞船边界的多边形顶点数组
	POINT	lpPointsShip[] = {	{5,42},  {22,48}, {22,52}, {38,52}, 
								{38,47}, {54,41}, {54,29}, {37,8},
								{31,15}, {28,15}, {22,8}, {5,31}	};

	//利用上面的数组,创建飞船碰撞检测类
	m_hcShip.CreatePolygonBound(lpPointsShip, 12);


	//创建小行星的多边形顶点数组
	POINT	lpPointsAsteroid[] = {	{8,31},  {22,46}, {37,38}, {49,26}, 
									{37,9}, {19,6}, {10,6}, {8,16}	};

	//利用上面的数组,创建小行星碰撞检测类
	m_hcAsteroid.CreatePolygonBound(lpPointsAsteroid, 8);

	//停止运动标志
	m_bStop = FALSE;

	//创建绘制线程,线程参数就是这个对话框类
	AfxBeginThread(UpdateFrame, this);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CHitCheckDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CHitCheckDemoDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CHitCheckDemoDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

//初始化DirectX
void CHitCheckDemoDlg::InitDirectX()
{
	HRESULT			hRet;
	LPDIRECTDRAW	pDD;

    DDSURFACEDESC2		ddsd;
    DDSCAPS2			ddscaps;

    LPDIRECTDRAWCLIPPER pcClipper;

	// 首先,创建DirectX对象
	hRet = DirectDrawCreate( NULL, &pDD, NULL );
	if(hRet != DD_OK)
	{
		return;
	}

    //取DirectDraw7接口
    hRet = pDD->QueryInterface(IID_IDirectDraw7, (LPVOID*)&m_pDD);
	if(hRet != DD_OK)
	{
		return;
	}

	//既然不再需要DirectDraw接口,所以释放掉
	pDD->Release();
    
	//确定应用程序的显示方式,正常的窗口显示方式
	hRet = m_pDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL);
	if(hRet != DD_OK)
	{
		return;
	}
    
	//创建主曲面,这里我们不使用cSurface创建而是直接使用IDirectDraw7
    ZeroMemory( &ddsd, sizeof( ddsd ) );

    ddsd.dwSize = sizeof( ddsd );
    ddsd.dwFlags = DDSD_CAPS;
    //创建主曲面,在DirectX中,主曲面需要用主DirectDrawSurface对象表示。
	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
							
    //ddsd.dwBackBufferCount = 1;

    //m_pFrontBuffer被DirectDraw对象创建为主曲面
	hRet = m_pDD->CreateSurface(&ddsd, &m_pFrontBuffer, NULL );
	if(hRet != DD_OK)
	{
		return;
	}

    // Create back buffer
    
	ZeroMemory(&ddscaps, sizeof(ddscaps));
	RECT	rcRect;
	this->GetWindowRect(&rcRect);

    //创建后台缓冲曲面
    ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;    
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
    ddsd.dwWidth        = rcRect.right  - rcRect.left;
    ddsd.dwHeight       = rcRect.bottom - rcRect.top;

	ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
    hRet = m_pDD->CreateSurface( &ddsd, &m_pBackBuffer, NULL );
	
	if(hRet != DD_OK)
	{
		return;
	}
	
	//创建DirectDraw裁剪对象
    if( FAILED( hRet = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) )
        return;

	//裁剪对象设置主窗口
    if( FAILED( hRet = pcClipper->SetHWnd( 0, m_hWnd ) ) )
    {
        pcClipper->Release();
        return;
    }

	//设置前台缓冲的裁剪对象
    if( FAILED( hRet = m_pFrontBuffer->SetClipper( pcClipper ) ) )
    {
        pcClipper->Release();
        return;
    }

    //释放裁剪对象
    pcClipper->Release();

    
	DDBLTFX ddbltfx;
    ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
    ddbltfx.dwSize      = sizeof(ddbltfx);
    ddbltfx.dwFillColor = RGB(0,0,0);
	//Blt函数用来进行位块信息传输
    m_pBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx );
}

void CHitCheckDemoDlg::OnClose() 
{
	//设置线程结束标志
	m_bStop = TRUE;

	//休眠一会,等待绘制线程结束
	Sleep(100);
	
	// TODO: Add your message handler code here and/or call default
	
	//释放前台缓冲、后台缓冲和DirectDraw对象
    if( m_pBackBuffer != NULL )
        m_pBackBuffer->Release();

	if( m_pFrontBuffer != NULL )
        m_pFrontBuffer->Release();

    if( m_pDD != NULL )
        m_pDD->Release();

	CDialog::OnClose();
}

//绘制飞船
void CHitCheckDemoDlg::DrawShip()
{
	RECT	rcRect;
	GetWindowRect(&rcRect);
	//滑动飞船的水平位置
	pShipPos.x += m_iIncrement;
	//如果飞船到了边界则停下来
	if(pShipPos.x == 0)
		m_iIncrement = 0;
	if(pShipPos.x == rcRect.right-60)
		m_iIncrement = 0;

	//在背景绘制表面绘制飞船
	m_surfShip.Draw(m_pBackBuffer, pShipPos.x, pShipPos.y);
}

//绘制小行星
void CHitCheckDemoDlg::DrawAsteroids()
{
	// Draw each one of the 3 asteroids

	RECT	rcRect;
	GetWindowRect(&rcRect);
	//绘制三个小行星
	m_surfAsteroid.Draw(m_pBackBuffer, m_pAsteroid1.x, m_pAsteroid1.y);
	m_surfAsteroid.Draw(m_pBackBuffer, m_pAsteroid2.x, m_pAsteroid2.y);
	m_surfAsteroid.Draw(m_pBackBuffer, m_pAsteroid3.x, m_pAsteroid3.y);

	//改变小行星的位置
	m_pAsteroid1.y++;
	m_pAsteroid2.y+=2;
	m_pAsteroid3.y+=3;


	if(m_pAsteroid1.y > rcRect.bottom -rcRect.top- 51)
		m_pAsteroid1.y = 40;

	if(m_pAsteroid2.y > rcRect.bottom - rcRect.top - 51)
		m_pAsteroid2.y = 40;

	if(m_pAsteroid3.y > rcRect.bottom - rcRect.top - 51)
		m_pAsteroid3.y = 40;

	//分别测试3个小行星是否和飞船发生了碰撞
	if(m_hcShip.HaveHitted(&m_hcAsteroid,m_pAsteroid1.x, m_pAsteroid1.y, pShipPos.x, pShipPos.y) == TRUE)
	{
		//显示Ship Hitted!
		m_surfShipHitted.Draw(m_pBackBuffer, 10,40,0,0);
		OutputDebugString("Ship Hitted by Asteroid 1!\n");
	}

	if(m_hcShip.HaveHitted(&m_hcAsteroid,m_pAsteroid2.x, m_pAsteroid2.y, pShipPos.x, pShipPos.y) == TRUE)
	{
		m_surfShipHitted.Draw(m_pBackBuffer, 10,40,0,0);
		OutputDebugString("Ship Hitted by Asteroid 2!\n");
	}

	if(m_hcShip.HaveHitted(&m_hcAsteroid,m_pAsteroid3.x, m_pAsteroid3.y, pShipPos.x, pShipPos.y) == TRUE)
	{
		m_surfShipHitted.Draw(m_pBackBuffer, 10,40,0,0);
		OutputDebugString("Ship Hitted by Asteroid 3!\n");
	}
}

//需要在PreTranslateMessage中截获对话框中键盘消息,而不是OnKeyDown消息相应函数
BOOL CHitCheckDemoDlg::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
	if(pMsg->message == WM_KEYDOWN)
	{
		int nVirtKey = (int) pMsg->wParam;
		switch(nVirtKey)
		{
		case VK_LEFT:
			m_iIncrement = -1;
			break;
		case VK_RIGHT:
			m_iIncrement = +1;
			break;
		case VK_DOWN:
			m_iIncrement = 0;
			break;
		}
	}
	return CDialog::PreTranslateMessage(pMsg);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -