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

📄 cbmap.cpp

📁 这是一个游戏程序源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
void MAP_FillRegion( POINT pt, int nPlayer )
{
	// set current point
	struct MAP_REGION_CODE_STRUCT stctR;
	WORD code;
	stctR.nPlayer = nPlayer;
	stctR.nShadow = MAP_SHADOW_NONE;
	stctR.nShadowEx = MAP_SHADOW_NONE;
	code = MAP_RegionEnCode( stctR );

	MAP_SetRegionData( pt.x, pt.y, code );
	MAP_nRegionStack++;	// stack counter

	POINT ptNext;
	for( int i=0; i<4; i++ )
	{
		// get next point
		int bOdd = pt.y&1;	// TRUE if Odd
		ptNext.x = pt.x + MAP_ptSenser[bOdd][0][i*2+1].x;
		ptNext.y = pt.y + MAP_ptSenser[bOdd][0][i*2+1].y;
		if( EYE_IfOutOfRange( ptNext.x, ptNext.y ) )
			continue;
		code = MAP_GetGroundData( 0, ptNext.x, ptNext.y );
		if( code == MAP_DATA_NONE )	continue;
		struct MAP_GROUND_CODE_STRUCT stctG;
		MAP_GroundDeCode( code, &stctG );

		// if it is on the correct ground type
		if( stctG.nFile == 2 && stctG.nCol == 12 && MAP_nRegionStack<MAP_REGION_STACK_MAX )
		{	
			code = MAP_GetRegionData( ptNext.x, ptNext.y );
			MAP_RegionDeCode( code, &stctR );
			// if has filled
			if(  stctR.nPlayer != nPlayer )
				MAP_FillRegion( ptNext, nPlayer );
		}
	}
	MAP_nRegionStack--;
}

// 清除区域
// 只有地图编辑器使用
// pt	:	填充点种子,格子为单位
void MAP_ClearRegion( POINT pt )
{
	// set current point
	struct MAP_UNIT_CODE_STRUCT stctU;
	DWORD codeU;
	codeU = MAP_GetUnitData( pt.x, pt.y );
	if( codeU != MAP_DATA_NONE )
	{
		::MAP_UnitDeCode( codeU, &stctU );
		// if it is flag
		//if( stctU.nFile == 3 && stctU.nCol == 0 )
		// 只有地图编辑器使用
		int nType = MAP_Lib.Unit[stctU.nFile].nType;
		if( nType == MAP_UNIT_TYPE_FLAG )
		{
			// reset to zero
			MAP_SetUnitData( 0, pt.x, pt.y, MAP_DATA_NONE );
		}
	}

	// set region to none
	WORD code;
	code = MAP_GetRegionData( pt.x, pt.y );
	struct MAP_REGION_CODE_STRUCT stctR;
	MAP_RegionDeCode( code, &stctR );
	stctR.nPlayer = MAP_PLAYER_NONE;	// custom value 
	code = MAP_RegionEnCode( stctR );
	MAP_SetRegionData( pt.x, pt.y, code );
	MAP_nRegionStack++;	// stack counter

	POINT ptNext;
	for( int i=0; i<4; i++ )
	{
		// find next point
		int bOdd = pt.y&1;	// TRUE if Odd
		ptNext.x = pt.x + MAP_ptSenser[bOdd][0][i*2+1].x;
		ptNext.y = pt.y + MAP_ptSenser[bOdd][0][i*2+1].y;

		code = MAP_GetGroundData( 0, ptNext.x, ptNext.y );
		if( code == MAP_DATA_NONE )	continue;
		struct MAP_GROUND_CODE_STRUCT stctG;
		MAP_GroundDeCode( code, &stctG );
		// if it is the correct ground type
		if( stctG.nFile == 2 && stctG.nCol == 12 && MAP_nRegionStack<MAP_REGION_STACK_MAX )
		{
			code = MAP_GetRegionData( ptNext.x, ptNext.y );
			MAP_RegionDeCode( code, &stctR );
			// if has been cleared
			if(  stctR.nPlayer != MAP_PLAYER_NONE )
				MAP_ClearRegion( ptNext );
		}
	}
	MAP_nRegionStack--;
}

// 直接将压缩后的代码设置到区域数组中
// nCol		:	列号
// nRow		:	行号
// codeR	:	区域数据代码(压缩)
inline void MAP_SetRegionData( int nCol, int nRow, int codeR )
{
	MAP_wRegionData[nCol][nRow] = codeR;
}

// 直接从区域数组中取出数据
// nCol			:	列号
// nRow			:	行号
// return value	:	区域数据代码(压缩)
inline WORD MAP_GetRegionData( int nCol, int nRow )
{
	return MAP_wRegionData[nCol][nRow];
}

// 检测是否可以在此片地域上修建建筑,return 10 if successful
// nLayer		:	层号
// pt			:	测试点,格子为单位
// codeU		:	建筑代码(压缩)
// codeUEx		:	出发点的单元,检测时可以取得此点,MAP_DATA_NONE时无效
// return value	:	错误代码,见上
int MAP_TestRegion( int nLayer, POINT pt, DWORD codeU, WORD codeUEx/*=MAP_DATA_NONE*/ )
{
	if( codeU == MAP_DATA_NONE )	return 10;

	// should be built on one special ground type
	struct MAP_UNIT_CODE_STRUCT stctU;
	::MAP_UnitDeCode( codeU, &stctU );
	//int nType = MAP_Lib.Unit[stctU.nFile].nType;

	// set locations
	int nLocationSize = MAP_Lib.Unit[stctU.nFile].nLocationSize;
	POINT ptNext;
	int retrns[16];
	int i;

	int bOdd = pt.y&1;	// TRUE if Odd
	for( i=0; i<MAP_nLocationNum[nLocationSize]; i++ )
	{
		ptNext.x = pt.x + MAP_ptLocation[bOdd][i].x;
		ptNext.y = pt.y + MAP_ptLocation[bOdd][i].y;
		if( EYE_IfOutOfRange( ptNext.x, ptNext.y ) )
		{
			retrns[i] = MAP_REGION_ERROR_OUT;
		}
		else
			retrns[i] = MAP_testPointRegion( nLayer, ptNext, codeU, codeUEx );
		if( retrns[i] != MAP_REGION_SUCCESS )
			return retrns[i];
	}

	return MAP_REGION_SUCCESS;
}

// only called by MAP_TestRegion()
// 检测是否可以在点上修建建筑,return 10 if successful
// nLayer		:	层号
// pt			:	测试点,格子为单位
// codeU		:	建筑代码(压缩)
// codeUEx		:	出发点的单元,检测时可以取得此点,MAP_DATA_NONE时无效
// return value	:	错误代码,见上
int MAP_testPointRegion( int nLayer, POINT pt, DWORD codeU, WORD codeUEx/*=MAP_DATA_NONE*/ )
{
	WORD codeG1;
	for(;;)
	{
		// 没有地形图素而且在最底层,错误返回
		// cannot build below ground
		codeG1 = MAP_GetGroundData( nLayer, pt.x, pt.y );
		if( codeG1 != MAP_DATA_NONE )
			break;
		if( nLayer == 0	&& codeG1 == MAP_DATA_NONE )
		{
			return MAP_REGION_ERROR_UNDER;
		}
		nLayer--;
	}
	Assert( nLayer >= 0 );

	struct MAP_UNIT_CODE_STRUCT stctU;
	::MAP_UnitDeCode( codeU, &stctU );
	int nType = MAP_Lib.Unit[stctU.nFile].nType;

	// cannot build building on other unit
	WORD cUEx = ::MAP_GetUnitDataEx( pt.x, pt.y );
//	if( cUEx != MAP_DATA_NONE && codeUEx != cUEx )	
//		return MAP_REGION_ERROR_CANNOT;
	if( cUEx != MAP_DATA_NONE )	
		return MAP_REGION_ERROR_CANNOT;

	// cannot build on resources
	struct MAP_GROUND_CODE_STRUCT stctG;
	MAP_GroundDeCode( codeG1, &stctG );
	if( stctG.nAttr != MAP_SPECIAL_NONE 
		&& stctG.nAttr != MAP_SPECIAL_CUT_WOOD 
		&& stctG.nAttr != MAP_SPECIAL_CUT_WHEAT )	// cannot move in Forest and Field
		return MAP_REGION_ERROR_RES;

	// cannot build on other layers
	if( nLayer <MAP_DATA_THICK-1 )
	{
		WORD codeG2 = MAP_GetGroundData( nLayer+1, pt.x, pt.y );
		if( codeG2 != MAP_DATA_NONE )	return MAP_REGION_ERROR_CANNOT;
	}

	// should be built on one special ground type
	if( nType == MAP_UNIT_TYPE_SHIPYARD )	// shipyard
	{
		WORD codeG = MAP_GetGroundData( nLayer, pt.x, pt.y );
		struct MAP_GROUND_CODE_STRUCT stctG;
		::MAP_GroundDeCode( codeG, &stctG );
		if( !(stctG.nFile == 3 && stctG.nCol == 12) )
		{	// shipyard can only be placed in water
			return MAP_REGION_ERROR_SHIPYARD;
		}
	}
	else if( nType == MAP_UNIT_TYPE_SHIP 
		|| nType == MAP_UNIT_TYPE_SGEN )	// sailer
	{
		WORD codeG = MAP_GetGroundData( nLayer, pt.x, pt.y );
		struct MAP_GROUND_CODE_STRUCT stctG;
		::MAP_GroundDeCode( codeG, &stctG );
		if( !(stctG.nFile == 3 && stctG.nCol == 12) )
		{	// ships can only be placed in water
			return MAP_REGION_ERROR_SHIP;
		}
	}
	else
	{	// 陆上单元
		WORD codeG = MAP_GetGroundData( nLayer, pt.x, pt.y );
		struct MAP_GROUND_CODE_STRUCT stctG;
		::MAP_GroundDeCode( codeG, &stctG );
		if( stctG.nFile == 3 && stctG.nCol == 12 )
			return MAP_REGION_ERROR_WATER;	// 不能建在水中

		if( nType == MAP_UNIT_TYPE_BUILDING ||
			nType == MAP_UNIT_TYPE_FLAG )	// generic building
		{
			if( !(stctG.nFile == 2 && stctG.nCol == 12) )
			{	// generic building can only be placed on TUDI
				return MAP_REGION_ERROR_TUDI;	// 只能建在土地上
			}
		}
	}

#ifdef	_MAP_EDIT_
	if( nType == MAP_UNIT_TYPE_FLAG )	// if it is flag
	{
		// clear region
		MAP_nRegionStack=0;
		::MAP_ClearRegion( pt );
		// set region to this flag
		MAP_nRegionStack=0;
		::MAP_FillRegion( pt, stctU.nPlayer );
	}
	else if( nType == MAP_UNIT_TYPE_BUILDING )	// other unit data
	{
		// must be placed with the same flag
		WORD codeR = MAP_GetRegionData( pt.x, pt.y );
		struct MAP_REGION_CODE_STRUCT stctR;
		MAP_RegionDeCode( codeR, &stctR );
		if( stctR.nPlayer == MAP_PLAYER_NONE )
		{
			// set flag first
			return MAP_REGION_ERROR_FLAG;
		}
		else
		{	// change the flag of the unit to the same as the region
			stctU.nPlayer = stctR.nPlayer;
			codeU = MAP_UnitEnCode( stctU );
		}
	}
#endif // _MAP_EDIT_
	return MAP_REGION_SUCCESS;
}

// 自动找到一个可以放置该单元的位置,在MAP_SENSER_MAX格范围内寻找
// nZ, nX, nY	:	开始的坐标
// codeU		:	该单元的压缩代码
// codeUEx		:	出发点的单元,检测时可以取得此点,MAP_DATA_NONE时无效
// return		:	(-1,-1)时为没有找到
POINT MAP_FindRegion( int nZ, int nX, int nY, DWORD codeU, WORD codeUEx/*=MAP_DATA_NONE*/ )
{
	POINT pt;
	int ret;
	int bOdd;

	// test for the current position
	pt.x = nX, pt.y = nY;
	ret = MAP_TestRegion( nZ, pt, codeU, codeUEx );
	if( ret == MAP_REGION_SUCCESS )
	{
		Assert( MAP_GetUnitData( pt.x, pt.y ) == MAP_DATA_NONE );
		return pt;
	}

	// test for the positions around the current one
	bOdd = nY%2;
	for( int i=0; i< MAP_SENSER_MAX; i++ )
	for( int j=0; j< ((i+1)<<3); j++ )
	{
		pt.x = nX + MAP_ptSenser[bOdd][i][j].x;
		pt.y = nY + MAP_ptSenser[bOdd][i][j].y;
		if( EYE_IfOutOfRange( pt.x, pt.y ) )
			continue;
		ret = MAP_TestRegion( nZ, pt, codeU, codeUEx );
		if( ret == MAP_REGION_SUCCESS )
		{
			Assert( MAP_GetUnitDataEx( pt.x, pt.y ) == MAP_DATA_NONE 
				|| MAP_GetUnitDataEx( pt.x, pt.y ) == codeUEx );
			return pt;
		}
	}
	pt.x = -1, pt.y = -1;
	return pt;
}
///////////

///////////
// 只有在CBBuild.cpp中使用,建造建筑时用
// 检测是否可以在此片地域上修建建筑
// nLayer		:	输入,层号
// pt			:	输入,测试点,格子为单位
// codeU		:	输入,建筑代码(压缩)
// pnRet		:	输出,返回值数组
// nRetNum		:	输入,数组的内容的个数
void MAP_TestRegionBuild( int nLayer, POINT pt, DWORD codeU, int *pnRet, int nRetNum )
{
	if( codeU == MAP_DATA_NONE )	return;

	POINT ptNext;
	int retrns[16];
	int i;

	int bOdd = pt.y&1;	// TRUE if Odd
	for( i=0; i<nRetNum; i++ )
	{
		ptNext.x = pt.x + MAP_ptLocation[bOdd][i].x;
		ptNext.y = pt.y + MAP_ptLocation[bOdd][i].y;
		if( EYE_IfOutOfRange( ptNext.x, ptNext.y ) )
		{
			retrns[i] = MAP_REGION_ERROR_OUT;
		}
		else
		{
			// 如果被阴影遮挡则不能建造
			WORD codeR = MAP_GetRegionData( ptNext.x, ptNext.y );
			struct MAP_REGION_CODE_STRUCT stctR;
			MAP_RegionDeCode( codeR, &stctR );
			if( stctR.nShadow == MAP_SHADOW_NONE )
				retrns[i] = MAP_REGION_ERROR_SHADOW;
			else
			{
				retrns[i] = MAP_testPointRegion( nLayer, ptNext, codeU );
			}
		}
	}

// 重新计算船坞是否靠着岸边
	BOOL bSuccess = TRUE;
	for( i=0; i<nRetNum; i++ )
	{
		if( retrns[i] != MAP_REGION_SUCCESS )
		{
			bSuccess = FALSE;
			break;
		}
	}
	// 如果可以成功建造
	if( bSuccess == TRUE )
	{	
		WORD codeG = MAP_GetGroundData( nLayer, pt.x, pt.y );
		if( codeG != MAP_DATA_NONE )
		{
			struct MAP_GROUND_CODE_STRUCT stctG;
			MAP_GroundDeCode( codeG, &stctG );
			if( stctG.nFile == 3 )	// 是水
			{	// 只能在水边才能建造船坞,所以肯定是要建造船坞
				bSuccess = EYE_IfNearBank( nLayer, pt.x, pt.y, 2 );
			}
		}
		if( bSuccess == FALSE )
		{	// 地点周围没有岸,失败
			for( i=0; i<nRetNum; i++ )
			{
				retrns[i] = MAP_REGION_ERROR_BANK;
			}
		}
	}

	memcpy( pnRet, retrns, nRetNum*sizeof( int ) );
	return;
}
///////////

///////////
// 计算其它数据的矩形区域
// ptOff	:	屏幕左上角相对于整个战场的坐标
// nLayer, nCol, nRow	:	在战场的三维坐标
// nFile	:	其它数据结构的文件号
// return	:	相对于屏幕的点坐标和范围
RECT MAP_GetOtherRect( CONST POINT ptOff, int nLayer, int nCol, int nRow, int nFile )
{
	int left, top;
	int widthG = MAP_Lib.szItem.cx;
	int heightG = MAP_Lib.szItem.cy;
	int width = MAP_Lib.Other[nFile].szItem.cx;
	int height = MAP_Lib.Other[nFile].szItem.cy;
	RECT rect;

	// calc top-left position on screen
	top = nRow*(heightG>>1) + heightG - height;	// 底边与格子对齐
	if( (nRow&1) == 0 )
	{
		left = nCol*widthG+(widthG>>1)-(width>>1);
	}
	else
	{
		left = (nCol+1)*widthG-(width>>1);
	}

	// re-adjust coords
	left -= ptOff.x;
	top -= ptOff.y;
	
	rect.left = left, rect.top = top, 
	rect.right = left+width, rect.bottom = top + height;
	return rect;
}
///////////

⌨️ 快捷键说明

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