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

📄 astar.cpp

📁 网络游戏魔域源代码 测试可以完整变异
💻 CPP
字号:
//-------------------------------------------------
// A*
//----------------------------------------------------//
#include "3DGameMap.h"
#include "GamePlayerSet.h"
#include "Hero.h"

void CGameMap::ClearCloseSet()
{
	m_nCloseNodeAmount = 0;
}
//----------------------------------------------------//
void CGameMap::ClearOpenSet()
{
	m_setOpen.clear();
}
//----------------------------------------------------//
void CGameMap::ClearPathSet()
{
	m_setPath.clear();
}
//----------------------------------------------------//
void CGameMap::BuildPlayerMap(CMyPos posStart)
{
	for(int k = 0; k < 37; k ++)
		for(int j = 0; j < 37; j ++)
			m_bPlayerMap[k][j] = 0;
	if(g_objHero.TestStatus(USERSTATUS_DIE))
		return;
	int nBeginX	= posStart.x - 18;
	int nBeginY	= posStart.y - 18;
	int nEndX	= posStart.x + 18;
	int nEndY	= posStart.y + 18;
	m_posPlayerMap.x = nBeginX;
	m_posPlayerMap.y = nBeginY;
	
	int nPlayerAmount = g_objPlayerSet.GetPlayerAmount();
	for(int i =0 ; i < nPlayerAmount+1; i ++)
	{
		CPlayer* pPlayer = NULL;
		if(i == nPlayerAmount)
			pPlayer = &g_objHero;
		else
			pPlayer = g_objPlayerSet.GetPlayerByIndex(i);
		if(pPlayer && !pPlayer->TestStatus(USERSTATUS_DIE))
		{
			CMyPos posPlayer;
			pPlayer->GetPos(posPlayer);
			if(posPlayer.x >= nBeginX && posPlayer.y >= nBeginY &&
				posPlayer.x <= nEndX && posPlayer.y <= nEndY)
			{
				m_bPlayerMap[posPlayer.x - nBeginX][posPlayer.y - nBeginY] = 1;
			}
		}
	}
}
//----------------------------------------------------//
BOOL CGameMap::CheckPlayerMap(CMyPos posCell)
{
	int nBeginX	= m_posPlayerMap.x;
	int nBeginY	= m_posPlayerMap.y;
	int nEndX	= m_posPlayerMap.x + 36;
	int nEndY	= m_posPlayerMap.y + 36;
	if(posCell.x >= nBeginX && posCell.y >= nBeginY &&
		posCell.x <= nEndX && posCell.y <= nEndY)
		if(m_bPlayerMap[posCell.x - nBeginX][posCell.y - nBeginY])
			return true;
	return false;
}
//----------------------------------------------------//
void CGameMap::FindPath(CMyPos posStart, CMyPos posTarget)
{
	m_posRealTarget = posStart;
	m_posStart =posStart;
	m_posTarget =posTarget;
	if((posStart.x ==  posTarget.x) && (posStart.y ==  posTarget.y))
		return;
	this->InitAStar();
	while(true)
	{
		if(m_nCloseNodeAmount >= _MAX_STEP)
			return;
		if(m_setOpen.size() == 0)
			return;
		NodeInfo* pBestNode = this->CheckOpenList();
		if(!pBestNode)
			continue;
		if(this->AddSucNode(pBestNode))
			return;
	}
}
//----------------------------------------------------//
void CGameMap::InitAStar()
{
	//把s压入open
	this->ClearNodeSet();
	this->ClearPathSet();
	this->ClearOpenSet();
	this->ClearCloseSet();
	m_nNodeIndex = 0;
	int nAmount = m_setCellAStar.size();
	for(int i = 0; i < nAmount; i++)
	{
		CellInfo* pCellInfo = m_setCellAStar[i];
		if(pCellInfo)
			pCellInfo->m_bSearched = false;
	}
	m_setCellAStar.clear();
	NodeInfo* pNode = this->CreateNewNode();
	if(pNode)
	{
		pNode->nX = m_posStart.x;
		pNode->nY = m_posStart.y;
		pNode->nG = 0;
		pNode->nH = pNode->nG+this->GetHValue(m_posStart);
		pNode->nStep = 0;
		pNode->pNode = NULL;
		pNode->pChildNode = NULL;
		m_setOpen.push_back(pNode);
	}
	CellInfo* pCellInfo =  this->GetCell(m_posStart.x, m_posStart.y);
	if(pCellInfo)
	{
		pCellInfo->m_bSearched = true;
		m_setCellAStar.push_back(pCellInfo);
	}
}
//----------------------------------------------------//
int CGameMap::GetHValue(CMyPos pos)
{
	int nDx = abs(m_posTarget.x-pos.x);
	int nDy = abs(m_posTarget.y-pos.y);
	if(nDx > nDy)
		return 10*nDx+6*nDy;
	return 10*nDy+6*nDx;
}
//----------------------------------------------------//
NodeInfo* CGameMap::CheckOpenList()
{
	NodeInfo* pNode = this->CheckBestNode();
	if(pNode->nStep >= _MAX_STEP)
		return NULL;
	return pNode;
}
//----------------------------------------------------//
NodeInfo* CGameMap::CheckBestNode()
{
	int nAmount = m_setOpen.size();
	NodeInfo* pBestNode = m_setOpen[0];
	int nBestNodeIndex = 0;
	for(int i = 1; i < nAmount; i++)
	{
		NodeInfo* pNode =  m_setOpen[i];
		if(pNode)
		{
			if(m_nPathMode == _ASTAR_CLOSE)
			{
				if((pNode->nH) < (pBestNode->nH))
				{
					pBestNode = pNode;
					nBestNodeIndex = i;
				}
			}
			else
			{
				if((pNode->nH) > (pBestNode->nH))
				{
					pBestNode = pNode;
					nBestNodeIndex = i;
				}
			}
		}
	}
	//::LogMsg("最佳节点:%d_%d", pBestNode->nX, pBestNode->nY);
	// 从Open表最佳节点
	//pBestNode->nG = 65535555;
	m_setOpen.erase(m_setOpen.begin()+nBestNodeIndex);
	// 添加到Close表
	//m_setClose.push_back(pBestNode);
	m_nCloseNodeAmount ++;
	return pBestNode;
}
//----------------------------------------------------//
BOOL CGameMap::AddSucNode(NodeInfo* pNode)
{
	if(!pNode)
		return false;
	CMyPos posNode;
	posNode.x = pNode->nX;
	posNode.y = pNode->nY;
	CMyPos posNewNode;
	
	int nArrayX[8] = {0, -1, -1, -1,  0,  1, 1, 1};
	int nArrayY[8] = {1,  1,  0, -1, -1, -1, 0, 1};
	
	for(int i = 0; i < 8; i++)
	{
		posNewNode.x = posNode.x+nArrayX[i];
		posNewNode.y = posNode.y+nArrayY[i];
		if(posNewNode.x < 0)
			continue;
		if(posNewNode.y < 0)
			continue;
		if(posNewNode.x > m_sizeMap.iWidth)
			continue;
		if(posNewNode.y > m_sizeMap.iHeight)
			continue;
		
		int nHeight = 0;
		
		CellInfo* pCellInfo = this->GetCell(pNode->nX, pNode->nY);
		if(pCellInfo)
		{
			LayerInfo* pLayerInfo = this->GetLastLayerInfo(pCellInfo);
			if(pLayerInfo)
			{
				nHeight = pLayerInfo->sAltitude;
			}
		}
		
		if(!this->CheckNode(posNewNode, nHeight))
			continue;
		NodeInfo* pNewNode =  this->CreateNewNode();
		if(!pNewNode)
			continue;
		pNewNode->nX = posNewNode.x;
		pNewNode->nY = posNewNode.y;
		//#####代价#####
		pNewNode->nG = pNode->nG;// + 8;
		pNewNode->nH = pNode->nG+this->GetHValue(posNewNode);
		pNewNode->nStep = pNode->nStep + 1;
		pNewNode->pNode = pNode;
		pNewNode->nDir  = i;
		pNode->pChildNode = pNewNode;
		m_setOpen.push_back(pNewNode);

		// 算最近点...
		if(_ASTAR_CLOSE == m_nPathMode)
		{
			DWORD dwOldV =(m_posRealTarget.x-m_posTarget.x) *
				(m_posRealTarget.x-m_posTarget.x) +
				(m_posRealTarget.y-m_posTarget.y) *
				(m_posRealTarget.y-m_posTarget.y);
			DWORD dwNewV =(pNewNode->nX-m_posTarget.x) *
				(pNewNode->nX-m_posTarget.x) +
				(pNewNode->nY-m_posTarget.y) *
				(pNewNode->nY-m_posTarget.y);
			if(dwNewV < dwOldV)
			{
				m_posRealTarget.x = pNewNode->nX;
				m_posRealTarget.y = pNewNode->nY;
			}
		}
		else
		{
			DWORD dwOldV =(m_posRealTarget.x-m_posTarget.x) *
				(m_posRealTarget.x-m_posTarget.x) +
				(m_posRealTarget.y-m_posTarget.y) *
				(m_posRealTarget.y-m_posTarget.y);
			DWORD dwNewV =(pNewNode->nX-m_posTarget.x) *
				(pNewNode->nX-m_posTarget.x) +
				(pNewNode->nY-m_posTarget.y) *
				(pNewNode->nY-m_posTarget.y);
			if(dwNewV > dwOldV)
			{
				m_posRealTarget.x = pNewNode->nX;
				m_posRealTarget.y = pNewNode->nY;
				if(dwNewV >= m_nLeaveDisc*m_nLeaveDisc)
				{
					this->GetPath(pNewNode);
					return true;
				}
			}
		}
		
		//::LogMsg("添加节点:%d_%d", pNewNode->nX, pNewNode->nY);
		if(_ASTAR_CLOSE == m_nPathMode && (pNewNode->nX == m_posTarget.x) && (pNewNode->nY == m_posTarget.y))
		{
			this->GetPath(pNewNode);
			return true;
		}
	}
	return false;
}
//----------------------------------------------------//
void CGameMap::GetPath(NodeInfo* pNode)
{
	NodeInfo* pMyNode = pNode;
	while(true)
	{
		if(pMyNode->pNode)
		{
			m_setPath.push_front(pMyNode);
			pMyNode = pMyNode->pNode;
		}
		else
		{
			break;
		}
	}
}

//----------------------------------------------------//
BOOL CGameMap::CheckNode(CMyPos posNode, int nHeight)
{
	// 可达 ...?
	CellInfo* pCellInfo = g_objGameMap.GetCell(posNode.x, posNode.y);
	if(!pCellInfo)
		return false;
	if(pCellInfo->m_bSearched)
		return false;
	LayerInfo* pLayerInfo = g_objGameMap.GetLastLayerInfo(pCellInfo);

	if(!pLayerInfo)
		return false;
	if(!CheckPlayerMap(posNode) && (pLayerInfo->usMask == 0)&& abs(nHeight - pLayerInfo->sAltitude) <= 25)
	{
		pCellInfo->m_bSearched = true;
		m_setCellAStar.push_back(pCellInfo);
		return true;
	}
	return false;
}
//----------------------------------------------------//
int  CGameMap::GetPathAmount()
{
	return m_setPath.size();
}
//----------------------------------------------------//
NodeInfo* CGameMap::GetNodeByIndex(int nIndex)
{
	int nAmount = m_setPath.size();
	if(nIndex < 0)
		return NULL;
	if(nIndex >= nAmount)
		return NULL;
	return m_setPath[nIndex];
}
//----------------------------------------------------//
int  CGameMap::GetStep(CMyPos posCell)
{
	int nAmount =  m_setPath.size();
	for(int i = 0; i < nAmount; i++)
	{
		NodeInfo* pNod = this->GetNodeByIndex(i);
		if(!pNod)
			return -1;
		if((pNod->nX == posCell.x) && (pNod->nY == posCell.y))
			return pNod->nStep;
	}
	return -1;
}
//----------------------------------------------------//
void CGameMap::ClearNodeSet()
{
	int nAmount = m_setNode.size();
	for(int i = 0; i < nAmount; i++)
	{
		NodeInfo* pNod = m_setNode[i];
		SAFE_DELETE(pNod);
	}
	m_setNode.clear();
	m_nNodeIndex=0;
}

//----------------------------------------------------//
NodeInfo* CGameMap::CreateNewNode()
{
	int nAmount =  m_setNode.size();
	NodeInfo* pNode = NULL;
	m_nNodeIndex ++;
	if(m_nNodeIndex >= nAmount)
	{
		pNode = new(NodeInfo);
		m_setNode.push_back(pNode);
	}
	else
	{
		pNode = m_setNode[m_nNodeIndex];
	}
	return pNode;
}
//----------------------------------------------------//
BOOL CGameMap::TestPath(CMapObj* pObj, CMyPos posTarget)
{
	if(!pObj)
		return false;
	int nType = pObj->GetObjType();
	if(nType == MAP_ROLE || nType == MAP_HERO || nType == MAP_PLAYER)
	{
		CPath objPath;
		CMyPos posObj = {0, 0};
		objPath.SetPlayer(pObj);
		pObj->GetPos(posObj);
		this->FindPath(objPath, posObj, posTarget);
		return objPath.IsReachable();
	}
	return false;
}
//----------------------------------------------------//
void CGameMap::FindPath(CPath& objPath, CMyPos posStart, CMyPos posTarget)
{
	this->BuildPlayerMap(posStart);
	m_nLeaveDisc = objPath.GetData();
	m_nLeaveDisc = 15;
	this->FindPath(posStart, posTarget);
	objPath.ClearStep();
	int nAmount = this->GetPathAmount();
	m_nPathMode = objPath.GetSearchMethod();
	if(nAmount == 0 || m_nPathMode == _ASTAR_LEAVE)
	{
		objPath.ClearStep();
		if(m_nPathMode == _ASTAR_LEAVE)
		{
			m_nPathMode = _ASTAR_CLOSE;
			this->FindPath(posStart, m_posRealTarget);
			m_nPathMode = _ASTAR_LEAVE;
		}
		else
		{
			this->FindPath(posStart, m_posRealTarget);
		}
		objPath.SetReachable(false);
	}
	else
	{
		objPath.SetReachable(true);
	}
	if((posStart.x == posTarget.x) && (posStart.y == posTarget.y)&& (m_nPathMode != _ASTAR_LEAVE))
	{
		objPath.SetReachable(true);
		objPath.ClearStep();
		return;
	}

	nAmount = this->GetPathAmount();
	for(int i = 0; i < nAmount; i++)
	{
		NodeInfo* pInfo = g_objGameMap.GetNodeByIndex(i);
        if(pInfo)
        {
				
			objPath.AddStep(pInfo->nDir, 0);
        }
	}
}
//----------------------------------------------------//
void CGameMap::ShowPath()
{
	int nAmount = this->GetPathAmount();
	for(int i = 0; i < nAmount; i++)
	{
		NodeInfo* pInfo = g_objGameMap.GetNodeByIndex(i);
        if(pInfo)
        {
			char szStep[64];
			sprintf(szStep, "%d", i);
			CMyPos posScr, posWorld;
			this->Cell2World(pInfo->nX, pInfo->nY, posWorld.x, posWorld.y);
			this->World2Screen(posWorld.x, posWorld.y, posScr.x, posScr.y);
			CMyBitmap::ShowString(posScr.x+10, posScr.y, 0xffffffff, szStep);
        }
	}
}
//----------------------------------------------------//
/*void CGameMap::FindPath(CMyPos posStart, CMyPos posTarget)
{
	const DWORD dwStepLimit = 0;
	
	while(true)
	{
		if(posStart.x == posTarget.x && posStart.y == posTarget.y)
			return;
		if()			
	}
}*/
//----------------------------------------------------//

⌨️ 快捷键说明

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