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

📄 action.cpp

📁 东北大学机器人足球队决策系统设计.开发环境使用 VS.NET 2003 调试 DLL 程序方法: 启动 VS.Net 选择“工具”菜单
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		+---------------------------+
		
		机器人在球的 上方: 1, 2, 3
					 左方: 4
					 右方: 5
					 下方: 6, 7, 8
*/
//
// 踢球判断时将球场分为四个区域
//
enum KickArea
{
	KA_A,	// A
	KA_B,	// B
	KA_C,	// C
	KA_D,	// D
}; // end enum KickArea

//
// 踢球的方向
//
enum KickDirection
{
	KD_1,
	KD_2,
	KD_3,
	KD_4,
	KD_5,
	KD_6,
	KD_7,
	KD_8,
}; // end KickDirection

//
// 机器人在球的方向
//
enum RobotToBallDirection
{
	RBD_TOP,
	RBD_LEFT,
	RBD_RIGHT,
	RBD_BOTTOM,
}; // end enum RobotToBallDirection

//
// 分析踢球时所需的信息
//
void analyseKickInfo (Robot &robot,
					  const Environment &env,
					  KickArea &area,
					  KickDirection &direction,
					  RobotToBallDirection &rbd)
{
	double robotX = robot.pos.x;
	double robotY = robot.pos.y;

	double ballX = env.currentBall.pos.x;
	double ballY = env.currentBall.pos.y;

	BallField fieldInfo = analyseFieldInfo ();

	//
	// 先分析球在哪个区域
	//
	{
		double aLeftX = FLEFTX,
			   bLeftX = FORBID_ZONE_X,
			   cLeftX = FIELD_CENTER_Y,
			   dLeftX = OPP_FORBID_ZONE_X,
			   dRightX = FRIGHTX;

		double tempY = 0;

		//
		// 将 X,Y 转换为实际情况下的坐标
		//
		transform (aLeftX, tempY);
		transform (bLeftX, tempY); 
		transform (cLeftX, tempY);
		transform (dLeftX, tempY);
		transform (dRightX, tempY);

		if ((aLeftX <= ballX && ballX <= bLeftX) || (aLeftX >= ballX && ballX >= bLeftX))
			area = KA_A;
		else if ((bLeftX <= ballX && ballX <= cLeftX) || (bLeftX >= ballX && ballX >= cLeftX))
			area = KA_B;
		else if ((cLeftX <= ballX && ballX <= dLeftX) || (cLeftX >= ballX && ballX >= dLeftX))
			area = KA_C;
		else if ((dLeftX <= ballX && ballX <= dRightX) || (dLeftX >= ballX && ballX >= dRightX))
			area = KA_D;
	}

	//
	// 分析机器人在球的哪个方向
	//
	{
		if (ballY == robotY) {
			//
			// 球的 X 坐标大于机器人的 X 坐标且我方在左半场则机器人在球的 左边
			// 球的 X 坐标小于机器人的 X 坐标且我方在右半场则机器人在球的 左边
			//
			if ((ballX > robotX && fieldInfo == BF_IS_LEFT) ||
				(ballX < robotX && fieldInfo == BF_IS_LEFT))
				rbd = RBD_LEFT;
			else
				rbd = RBD_RIGHT;
		}
		else if (ballY < robotY) {
			//
			// 机器人在球的上方
			//
			rbd = RBD_TOP;
		}
		else if (ballY > robotY) {
			//
			// 机器人在球的下方
			//
			rbd = RBD_BOTTOM;
		}
	}

	//
	// 分析机器人踢球的方向
	//
	{
		if (rbd == RBD_LEFT) {
			//
			// 机器人在球的左边,踢球方向为 KD_5
			//
			direction = KD_5;
		}
		else if (rbd == RBD_RIGHT) {
			//
			// 机器人在球的右边,踢球方向为 KD_4
			//
			direction = KD_4;
		}
		else if (rbd == RBD_TOP) {
			//
			// 机器人在球的上方 6, 7, 8
			// 机器人的 X 等于 球的 X 则踢的方向为 7
			// 如果我方球门在 左边 - 机器人的 X 小于 球的 X 则踢的方向为 8
			// 如果我方球门在 右边 - 机器人的 X 大于 球的 X 则踢的方向为 8
			//
			if (robotX == ballX)
				direction = KD_7;
			else if ((robotX < ballX && fieldInfo == BF_IS_LEFT) ||
					 (robotX > ballX && fieldInfo == BF_IS_RIGHT))
				direction = KD_8;
			else
				direction = KD_6;

		}
		else if (rbd == RBD_BOTTOM) {
			//
			// 机器人在球的下方 1, 2, 3
			// 机器人的 X 等于 球的 X 则踢的方向为 2
			// 如果我方球门在 左边 - 机器人的 X 小于 球的 X 则踢的方向为 3
			// 如果我方球门在 右边 - 机器人的 X 大于 球的 X 则踢的方向为 3
			//
			if (robotX == ballX)
				direction = KD_2;
			else if ((robotX < ballX && fieldInfo == BF_IS_LEFT) ||
					 (robotX > ballX && fieldInfo == BF_IS_RIGHT))
				direction = KD_3;
			else
				direction = KD_1;
		}
	}
}

bool actKickBall (Robot &robot, const Environment &env)
{
	/*
		A 区域内允许踢 2, 7, 3, 5, 8 三个角度
		    在以下条件下 "不允许" 踢 2, 7 两个角度
			1. 机器人在球的上方,球在中线的上方
			2. 机器人在球的下方,球在中线的下方

			1, 4 两个方向不允许踢
		    
			    *如果时间和精力允许考虑踢的线路是否会被阻碍物阻档导致改变方向射向我方球门

		B 区域内允许踢 2, 3, 5, 7, 8
			1, 4, 两个方向不允许踢

		C 区域内允许踢 3, 5, 8
			1, 2, 4, 6, 7 不允许踢

		D 区域内允许踢 2, 3, 5, 7, 8
			1, 4, 6 不允许踢
	 */
	double ballX = env.currentBall.pos.x;
	double ballY = env.currentBall.pos.y;
	double centerY = FIELD_CENTER_Y;		// 球场的中心位置 Y
	double robotX = robot.pos.x;
	double robotY = robot.pos.y;

	//
	// 踢球所需要的信息
	//
	KickArea area;
	KickDirection direction;
	RobotToBallDirection rbd;
	analyseKickInfo (robot, env, area, direction, rbd);

	switch (area) {
		case KA_A: {
			if (direction == KD_1 || direction == KD_4)
				return false;

			if (direction == KD_2 || direction == KD_7) {
				if (rbd == RBD_TOP && ballY > centerY)
					return false;
				if (rbd == RBD_BOTTOM && ballY < centerY)
					return false;
			}
		}
		break;

		case KA_B: {
			if (direction == KD_1 || direction == KD_4)
				return false;
		}
		break;

		case KA_C: {
			if (direction == KD_1 || 
				direction == KD_2 || 
				direction == KD_4 || 
				direction == KD_6 || 
				direction == KD_7) {
				return false;
			}
		}
		break;

		case KA_D: {
			if (direction == KD_1 ||
				direction == KD_4 ||
				direction == KD_6) {
				return false;
			}
		}
		break;
	}

	BallField fieldInfo = analyseFieldInfo ();

	//
	// 可以踢球
	//
	double targetX = 0;		// 球的目标点 X 轴
	double targetY = 0;		// 球的目标点 Y 轴

	if (rbd == RBD_BOTTOM) {
		//
		// 机器人在下方,向上踢球
		//
		if (direction == KD_1) {
			//
			// 向左上踢
			//
			if (fieldInfo == BF_IS_LEFT)
				targetX = FLEFTX - FIELD_WIDTH / 2;
			else
				targetX = FRIGHTX + FIELD_WIDTH / 2;
		}
		else if (direction == KD_2) {
			//
			// 向上踢
			//
			targetX = FTOP + FIELD_HEIGHT / 2;
		}
		else if (direction == KD_3) {
			//
			// 向右上踢
			//
			if (fieldInfo == BF_IS_LEFT)
				targetX = FRIGHTX + FIELD_WIDTH / 2;
			else
				targetX = FLEFTX - FIELD_WIDTH / 2;
		}
	}
	else if (rbd == RBD_TOP) {
		//
		// 机器人在上方,向下踢球
		//
		if (direction == KD_6) {
			//
			// 向左下踢
			//
			if (fieldInfo == BF_IS_LEFT)
				targetX = FLEFTX - FIELD_WIDTH / 2;
			else
				targetX = FRIGHTX + FIELD_WIDTH / 2;
		}
		else if (direction == KD_7) {
			//
			// 向下踢
			//
			targetX = FBOT - FIELD_HEIGHT / 2;
		}
		else if (direction == KD_8) {
			//
			// 向右下踢
			//
			if (fieldInfo == BF_IS_LEFT)
				targetX = FRIGHTX + FIELD_WIDTH / 2;
			else
				targetX = FLEFTX - FIELD_WIDTH / 2;
		}
	}
	else if (rbd == RBD_RIGHT) {
		//
		// 机器人在球的右边,向左踢
		//
		if (direction == KD_1 || direction == KD_4 || direction == KD_6)
			targetX = FLEFTX - FIELD_WIDTH / 2;
	}
	else if (rbd == RBD_LEFT) {
		//
		// 机器人在球的左边,向右踢
		//
		if (direction == KD_3 || direction == KD_5 || direction == KD_8)
			targetX = FRIGHTX + FIELD_WIDTH / 2;
	}

	//
	// 因 kickBall 中的 x, y 点都是以实际情况下的点来确定,因此不能使用 transform
	//
	//transform (targetX, targetY);
	//
	/*
                    
                    X
                    |
                    |      #
                 *  |   *
              #     |
                    |
			  |-----|------|
			     1      2

			X 为目标点的 X
			* 为球
			# 为机器人

			1. 第一种情况,机器人在球的左边,球在 X 的左边
			   球映射点的 Y 时,第一个点为 机器人,第二个点为 球
		    2. 第二种情况,机器人在球的右边,球在 X 的右边
			   球映射点的 Y 时,第一个点为 机器人,第二个点为 球
            
            getMappedTargetY (机器人, 球, X);
	 */
	if ((robotX > ballX && ballX > targetX) || (robotX < ballX && ballX < targetX))
		targetY = getMappedTargetY (robotX, robotY, ballX, ballY, targetX);
	else
		targetY = getMappedTargetY (ballX, ballY, robotX, robotY, targetX);
	actToPosition (robot, targetX, targetY);
	return true;
}

//
// boundProcess
//
void actBoundProcess (Robot &robot)
{
	
}

//
// passBall
//
void actPassBall (Robot &robot)
{
	
}

//
// blockMan
//
void actBlockMan (Robot &robot, const OpponentRobot &opponent)
{
	actToPosition (robot, opponent.pos.x, opponent.pos.y);
}

////
//// pointWaiting
////	
//void pointWaiting (Robot &robot)
//{
//	
//}
//
////
//// reaveBall
////
//void reaveBall (Robot &robot)
//{
//	
//}

⌨️ 快捷键说明

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