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

📄 chitchecker.cpp

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

#include "stdafx.h"
#include "cHitChecker.h"
#include <stdio.h>

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

cHitChecker::cHitChecker()
{
	hBoundingPoly = NULL;
}

cHitChecker::~cHitChecker()
{
	if(hBoundingPoly != NULL)
	{
		DeleteObject(hBoundingPoly);
	}
}

void cHitChecker::RemovePolyFromBound(LPPOINT lpPoints, int iCount, int iX, int iY)
{
	// Use the combine Rgn API to remove a poly from the class internal region
	HRGN	hRgnSrc = NULL;
	LPPOINT	pStart = lpPoints;

	if(iX != 0)
	{
		for(int i=0;i<iCount;i++)
		{
			lpPoints->x = lpPoints->x + iX;
			lpPoints->y = lpPoints->y + iY;
			lpPoints++;
		}
		lpPoints = pStart;
	}

	hRgnSrc = CreatePolygonRgn(lpPoints, iCount, ALTERNATE);
	if(hRgnSrc == NULL)
	{
		DXTRACE_MSG("ERROR !");
	}
	CombineRgn(hBoundingPoly, hBoundingPoly, hRgnSrc, RGN_DIFF);
	DeleteObject(hRgnSrc);

	if(iX != 0)
	{
		for(int i=0;i<iCount;i++)
		{
			lpPoints->x = lpPoints->x - iX;
			lpPoints->y = lpPoints->y - iY;
			lpPoints++;
		}
		lpPoints = pStart;
	}
}

void cHitChecker::CreatePolygonBound(LPPOINT lpPoints, int nCount)
{
	//使用区域API创建多边形边界区域
	Destroy();
	hBoundingPoly = CreatePolygonRgn(lpPoints, nCount, ALTERNATE);
}


BOOL cHitChecker::HaveHitted(cHitChecker *pHitCheck, int nX, int nY, int nSrcX, int nSrcY)
{
	HRGN	hSrcObjectRgn;
	HRGN	hCompObjectRgn;
	BOOL	bResult = FALSE;
	DWORD	dwSize;
	UINT	i = 0;

	RGNDATA*	rgnData;

	//首先检测包围盒矩形,用来快速排除非碰撞的情形
	RECT	rcObj;
	GetRgnBox(pHitCheck->hBoundingPoly,&rcObj);
	rcObj.top  += nY; rcObj.bottom  += nY;
	rcObj.left += nX; rcObj.right   += nX;

	if(nSrcX!=0 && nSrcY!=0)
	{
		//将自己的多边形边界进行偏移
		OffsetRgn(hBoundingPoly, nSrcX, nSrcY);
		//判断目标的包围盒是否和自己的多边形边界相交
		if(RectInRegion(hBoundingPoly, &rcObj) == 0)
		{
			//不相交,则对自己的多边形边界进行反偏移,回到初始状态
			OffsetRgn(hBoundingPoly, -nSrcX, -nSrcY);
			return FALSE;
		}
		//对自己的多边形边界进行反偏移,回到初始状态
		OffsetRgn(hBoundingPoly, -nSrcX, -nSrcY);
	}
	else
	{
		//这是一步优化操作,因为nSrcX和nSrcY等于0,所以它可以节约上面几个函数的调用过程,
		if(RectInRegion(hBoundingPoly, &rcObj) == 0)
			return FALSE;
	}

	//进一步检测是否相交


	//首先拷贝一份目标区域的多边形边界数据
	dwSize = GetRegionData(pHitCheck->hBoundingPoly, sizeof(RGNDATA), NULL);
	rgnData = (RGNDATA*) malloc(dwSize);
	GetRegionData(pHitCheck->hBoundingPoly, dwSize, rgnData);
	hSrcObjectRgn = ExtCreateRegion(NULL, dwSize, rgnData);
	
	//加入偏移量
	OffsetRgn(hSrcObjectRgn, nX, nY);

	//重新获得目标区域的多边形边界数据
	dwSize = GetRegionData(hSrcObjectRgn, sizeof(RGNDATA), NULL);
	rgnData = (RGNDATA*) realloc(rgnData, dwSize);
	GetRegionData(hSrcObjectRgn, dwSize, rgnData);
	
	if(nSrcX !=0 && nSrcY !=0)
	{
		RGNDATA*	rgnData2;

		//和上面的操作一样,拷贝一份边界多边形数据
		dwSize = GetRegionData(hBoundingPoly, sizeof(RGNDATA), NULL);
		rgnData2 = (RGNDATA*) malloc(dwSize);
		GetRegionData(hBoundingPoly, dwSize, rgnData2);
		hCompObjectRgn = ExtCreateRegion(NULL, dwSize, rgnData2);
		
		//加入偏移量
		OffsetRgn(hCompObjectRgn, nSrcX, nSrcY);

		bResult = TRUE;
		//遍历选取多边形边界的连续的两个顶点作为矩形区域。
		for(i=0;i<rgnData->rdh.nCount;i++)
		{
			memcpy(&rcObj, &rgnData->Buffer[i*sizeof(RECT)], sizeof(RECT));
			//相交判断
			if(RectInRegion(hCompObjectRgn, &rcObj) != 0)
			{
				bResult = FALSE;
				break;
			}
		}

		free(rgnData2);
		DeleteObject(hCompObjectRgn);

	}
	else
	{
		bResult = TRUE;

		for(i=0;i<rgnData->rdh.nCount;i++)
		{
			memcpy(&rcObj, &rgnData->Buffer[i*sizeof(RECT)], sizeof(RECT));
			if(RectInRegion(hBoundingPoly, &rcObj) != 0)
			{
				bResult = FALSE;
				break;
			}
		}
	}
	
	// Old stuff
	/*if(nSrcX !=0)
	{
		// Same copy for the region being tested
		dwSize = GetRegionData(hBoundingPoly, sizeof(RGNDATA), NULL);
		rgnData = (RGNDATA*) realloc(rgnData, dwSize);
		GetRegionData(hBoundingPoly, dwSize, rgnData);
		hTmpObjectRgn = ExtCreateRegion(NULL, dwSize, rgnData);
		//free((void*)rgnData);
		
		OffsetRgn(hTmpObjectRgn, nSrcX, nSrcY);
		OffsetRgn(hCompObjectRgn, nSrcX, nSrcY);

		CombineRgn(hCompObjectRgn, hCompObjectRgn, hSrcObjectRgn, RGN_DIFF);
		CombineRgn(hCompObjectRgn, hCompObjectRgn, hTmpObjectRgn, RGN_OR);

		// Combine the source object region with the object region
		// If the combination result in a different region
		// The regions are overllaping and HitChecking is TRUE;
		CombineRgn(hTmpObjectRgn, hTmpObjectRgn, hSrcObjectRgn, RGN_DIFF);
		// Compare the combine resulting
		bResult	= EqualRgn(hTmpObjectRgn, hCompObjectRgn);

		DeleteObject(hTmpObjectRgn);
	}
	else
	{
		// Combine the source object region with the object region
		// If the combination result in a different region
		// The regions are overllaping and HitChecking is TRUE;
		CombineRgn(hCompObjectRgn, hCompObjectRgn, hSrcObjectRgn, RGN_DIFF);
		// Compare the combine resulting
		bResult	= EqualRgn(hCompObjectRgn, hBoundingPoly);
	}
*/
	//释放目标物体资源
	free((void*)rgnData);
	DeleteObject(hSrcObjectRgn);
	return !bResult;
}

void cHitChecker::Destroy()
{
	//如果原来就有区域数据,则把它删掉
	if(hBoundingPoly != NULL)
	{
		DeleteObject(hBoundingPoly);
	}
}

⌨️ 快捷键说明

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