Esempio n. 1
0
/* decides if we can kick staright to the decired point around the player
   without a collision.
   (EndDist, dir) is a relative polar vector for the ball's final position
   closeMarg is what the radius of the player is considered to be */
int is_straight_kick(float dir, float EndDist, float closeMarg)
{
  Vector btraj = Polar2Vector(EndDist, dir) -  Mem->BallRelativeToBodyPosition();
  float ang;
  float dist;
  int res;

  DebugKick(printf("    isStriaght ball abs pos mod: %f\t dir: %f\n",
	 Mem->BallAbsolutePosition().mod(), Mem->BallAbsolutePosition().dir()));
  DebugKick(printf("    isStriaght ball rel pos mod: %f\t dir: %f\n",
	 Mem->BallRelativePosition().mod(), Mem->BallRelativePosition().dir()));
  DebugKick(printf("    isStriaght btraj mod: %f\t dir: %f\n", btraj.mod(), btraj.dir()));
  /* Apply the law of cosines to the anle formed by the player's center(A),
     the ball's current position(B), and the ball target position(C).
     The angle calculated is ABC */
  ang = ACos( (Sqr(EndDist) - Sqr(btraj.mod()) -
	       Sqr(Mem->BallDistance()))/
	      (-2 * Mem->BallDistance() * btraj.mod()) );
  DebugKick(printf("   isStraight ang: %f\n", ang));
  if (fabs(ang) > 90) {
    DebugKick(printf("    isStraight: Obtuse!\n"));
    LogAction2(120, "is_straight_kick: obtuse angle");
    return 1; /* obtuse angle implies definately straight */
  }
  /* get the height of the triangle, ie how close to the player the ball will
     go */
  dist = Sin(ang) * Mem->BallDistance();
  DebugKick(printf("   isStraight dist: %f\n", dist));
  LogAction3(120, "is_straight_kick: %f", dist);
  res = (fabs(dist) > closeMarg);
  return ( res );  
} 
Esempio n. 2
0
/**
 * Update data used by tackle.
 * \param agent.
 */
void Tackler::UpdateTackleData(const Agent & agent)
{
    if (mAgentID == agent.GetAgentID())  {
        return; /** no need to update */
    }

    mAgentID = agent.GetAgentID();

    const BallState & ball_state     = agent.GetWorldState().GetBall();
    const PlayerState & player_state = agent.GetSelf();
    Vector ball_2_player = (ball_state.GetPos() - player_state.GetPos()).Rotate(-player_state.GetBodyDir());

    Vector ball_vel;
    mMaxTackleSpeed = -1.0;
    mDirMap.clear();

    const double max_tackle_power = ServerParam::instance().maxTacklePower();
    const double min_back_tackle_power = ServerParam::instance().maxBackTacklePower();

    double factor = 1.0 - 0.5 * (fabs(Deg2Rad(ball_2_player.Dir())) / M_PI);

    for (AngleDeg tackle_angle = -180.0 + FLOAT_EPS; tackle_angle <= 180.0 + FLOAT_EPS; tackle_angle += 1.0) {
    	Vector ball_vel(ball_state.GetVel());
        double eff_power = (min_back_tackle_power + ((max_tackle_power - min_back_tackle_power) * (1.0 - fabs(Deg2Rad(tackle_angle)) / M_PI))) * ServerParam::instance().tacklePowerRate();
        eff_power *= factor;
        ball_vel += Polar2Vector(eff_power, tackle_angle + player_state.GetBodyDir());
        ball_vel = ball_vel.SetLength(Min(ball_vel.Mod(), ServerParam::instance().ballSpeedMax()));

        int angle_idx = ang2idx(tackle_angle);
        int dir_idx = dir2idx(ball_vel.Dir());

        mTackleAngle[angle_idx] = tackle_angle;
        mBallVelAfterTackle[angle_idx] = ball_vel;
        mDirMap[dir_idx].push_back(std::make_pair(angle_idx, ang2idx(tackle_angle + 1.0)));

        if (ball_vel.Mod() > mMaxTackleSpeed){
            mMaxTackleSpeed = ball_vel.Mod();
        }

        if (ball_vel.Mod() * ServerParam::instance().ballDecay() < FLOAT_EPS) {
        	mCanTackleStopBall = true;
        	mTackleStopBallAngle = tackle_angle;
        }
    }
//
//
//    for (AngleDeg tackle_angle = -180.0 + 0.3; tackle_angle <= 180.0 + FLOAT_EPS; tackle_angle += 1.0) {
//    	Vector ball_vel = GetBallVelAfterTackle(agent, tackle_angle);
//    	AngleDeg tackle_angle2 = 0.0;
//    	GetTackleAngleToDir(agent, ball_vel.Dir(), & tackle_angle2);
//
//    	std::cout << tackle_angle << " " << tackle_angle2 << std::endl;
//    }
//
//    exit(0);
}
Esempio n. 3
0
/**
 * 通过传入kick的参数,计算kick后球的位置和速度
 * Calculate ball position and velocity after a kick action.
 * \param kick_power.
 * \param kick_angle.
 * \param player_state state of the player who is performing kick.
 * \param ball_state ball state before the kick action is performed.
 * \param ball_pos will be set to ball position after kick.
 * \param ball_vel will be set to ball velocity after kick.
 * \param is_self if the action is performed by the agent this process represents.
 */
void ActionEffector::ComputeInfoAfterKick(const double kick_power, const double kick_angle,
		const PlayerState &player_state, const BallState &ball_state, Vector &ball_pos, Vector &ball_vel, bool is_self)
{
	double power = GetNormalizeKickPower(kick_power);
	double dir = GetNormalizeMoment(kick_angle);

	Vector ball_2_player = (ball_state.GetPos() - player_state.GetPos()).Rotate(-player_state.GetBodyDir());
    double eff_power = power *
        (is_self ? player_state.GetKickRate() : GetKickRate(ball_2_player, player_state.GetPlayerType()));
	Vector accel = Polar2Vector(eff_power, player_state.GetBodyDir() + dir);

	ball_vel = ball_state.GetVel() + accel;
	ball_pos = ball_state.GetPos() + ball_vel;
	ball_vel *= ServerParam::instance().ballDecay();
}
Esempio n. 4
0
/* all the turnball reasoning is done in relative (to body) coordinates
   call this before calling dokick to correct for movement of the player */
void PlayerMovementCorrection(AngleDeg* pdir, float* pdist)
{
  LogAction4(110, "Player movement correction: before dist: %f at dir: %f",
		 *pdist, *pdir);
  DebugKick(printf("Before corr- dir: %f\t dist: %f\n", *pdir, *pdist));
  Vector vRelBallTarg = Mem->BallRelativeToBodyPosition() +
    Polar2Vector(*pdist, *pdir);
  Vector vNewRelTarg = Mem->MyPredictedPosition() +
    vRelBallTarg - Mem->MyPos();
  Vector vNewRelTraj = vNewRelTarg - Mem->BallRelativeToBodyPosition();
  *pdir  = vNewRelTraj.dir();
  *pdist = vNewRelTraj.mod();
  DebugKick(printf("After corr- dir: %f\t dist: %f\n", *pdir, *pdist));
  LogAction4(110, "Player movement correction: after dist: %f at dir: %f",
		 *pdist, *pdir);
}
Esempio n. 5
0
/**
 * 通过传入dash的参数,计算dash后球员的位置和速度
 * Calculate player position and velocity after a dash action. Conflicts or forbidden areas are not
 * considered.
 * \param dash_power.
 * \param dash_dir.
 * \param player_state state of the player who is dashing.
 * \param player_pos will be set to player position after dash.
 * \param player_vel will be set to player velocity after dash.
 */
void ActionEffector::ComputeInfoAfterDash(const double dash_power, double dash_dir,
		const PlayerState &player_state, Vector &player_pos, Vector &player_vel)
{
	double dir_rate = GetDashDirRate(dash_dir);

	if (dash_power < 0.0) {
		dash_dir += 180.0;
	}
    double eff_dash_power = fabs(dash_power) * player_state.GetEffort() * player_state.GetDashPowerRate() * dir_rate;

	Vector accel = Polar2Vector(eff_dash_power, GetNormalizeAngleDeg(player_state.GetBodyDir() + dash_dir));

	player_vel = player_state.GetVel() + accel;
	player_pos = player_state.GetPos() + player_vel;
	player_vel *= player_state.GetPlayerDecay();
}
Esempio n. 6
0
/**
* 计算用同一dash_power到达某点需要的时间
* Caculate cycles needed to a target position with a certain dash power.
* @param player the player to caculate.
* @param target the target position to go to.
* @param dash_power the power for dash to predict.
* @return an integer to show the cycles caculated.
*/
int Dasher::CyclePredictedToPoint(const PlayerState& player , Vector target , double dash_power)
{
	double corrected_dash_power = dash_power;
	double effective_power;
	double predicted_stamina = player.GetStamina();
	double predicted_effort  = player.GetEffort();
	double predicted_recovery = player.GetRecovery();
	double predicted_capacity = player.GetCapacity();
	double myang = player.GetBodyDir();
	Vector position = player.GetPos();
	Vector velocity;

	if (player.GetVelConf() < FLOAT_EPS)
	{
		velocity = Vector(0,0);
	}
	else
	{
		velocity = player.GetVel();
	}

	Vector last_position = position;
	int max_cyc = (int)(position.Dist(target) / player.GetEffectiveSpeedMax() + 100);
	int last_action = 0; /* 0 -- turn , 1 -- dash*/

	for (int i = 0;i < max_cyc;i++)
	{
		if (position.Dist(target) < PlayerParam::instance().AtPointBuffer())
		{
			return i;
		}

		if (position.Dist(target) > last_position.Dist(target) + FLOAT_EPS && last_action == 1)
		{
			return i;
		}

		last_position = position;

		/*decide if we should turn*/
		double targ_ang;
		if (dash_power > 0)
		{
			targ_ang = (target - position).Dir() - myang;
		}
		else
		{
			targ_ang = (target - position).Dir() - GetNormalizeAngleDeg(myang + 180);
		}

		double max_go_to_point_angle_err = 4; //见08CP_max_go_to_point_angle_err
		if (fabs(GetNormalizeAngleDeg(targ_ang)) > max_go_to_point_angle_err)
		{
			/*turnint*/
			double this_turn = MinMax(-player.GetMaxTurnAngle(), GetNormalizeAngleDeg(targ_ang) , player.GetMaxTurnAngle());

			myang += this_turn;
			corrected_dash_power = 0;
			last_action = 0;
		}
		else
		{
			corrected_dash_power = player.CorrectDashPowerForStamina(dash_power);
			if (fabs(corrected_dash_power) > predicted_stamina)
			{
				effective_power = Sign(corrected_dash_power) * predicted_stamina;
			}
			else
			{
				effective_power = corrected_dash_power;
			}

			effective_power *= predicted_effort;
			effective_power *= player.GetDashPowerRate();
			velocity += Polar2Vector(effective_power , myang);
			last_action = 1;
		}

		if (velocity.Mod() > player.GetEffectiveSpeedMax())
		{
			velocity *= (player.GetEffectiveSpeedMax()/ velocity.Mod());
		}

		position += velocity;
		velocity *= player.GetPlayerDecay();

		//08 内UpdatePredictStaminaWithDash函数 直接写入此函数
		if (dash_power > 0)
		{
			predicted_stamina -= dash_power;
		}
		else
		{
			predicted_stamina -= 2 * dash_power;
		}

		if (predicted_stamina < 0)
		{
			predicted_stamina = 0;
		}

		if (predicted_stamina < ServerParam::instance().recoverDecStamina() && predicted_recovery > ServerParam::instance().recoverMin())
		{
			predicted_recovery -= ServerParam::instance().recoverDec();
		}

		if (predicted_stamina < ServerParam::instance().effortDecStamina()  && predicted_effort > player.GetEffortMin())
		{
			predicted_effort -= ServerParam::instance().effortDec();
		}

		if (predicted_stamina > ServerParam::instance().effortIncStamina() && predicted_effort < player.GetEffortMax())
		{
			predicted_effort += ServerParam::instance().effortDec();
		}

		//增加capacity改进
		double stamina_inc = Min(predicted_recovery * player.GetStaminaIncMax() , predicted_capacity);
		predicted_stamina += stamina_inc;
		if (predicted_stamina > ServerParam::instance().staminaMax())
		{
			predicted_stamina = ServerParam::instance().staminaMax();
		}

		predicted_capacity -= stamina_inc;
		if (predicted_capacity < 0)
		{
			predicted_capacity = 0;
		}
	}

	return max_cyc;
}
Esempio n. 7
0
/* we always reason about the right trajectory for the ball leave velocity
   correction for dokick */
KickToRes turnball_kick(AngleDeg target_dir, TurnDir rotate, 
		  Bool StopBall, TurnKickCommand* pCom,
		  float EndDist, float closeMarg, float kickFac)
{
  float dir;
  float dist;
  Vector btraj;

  pCom->time = -1;
  pCom->turn_neck = FALSE;
  
  DebugKick(printf("\nat turnball_kick: target_dir: %f\n", target_dir));
  LogAction4(60, "Turnball_kick: targ_dir: %.1f  dir: %d", target_dir, (int)rotate);
  
  NormalizeAngleDeg(&target_dir);
  
  //DebugKick(printf("HERE Time: %d\n", Mem->CurrentTime.t));
  /* the pos valid is not really right - if we are turning the ball and didn't
     actually see it last time, then there's a problem */
  if ( !Mem->BallPositionValid() || !Mem->BallKickable() ) {
    LogAction2(90, "turnball_kick: lost the ball");
    return KT_LostBall;
  }

  /* if the velocity isn's valid, turn to face ball */
  if ( !Mem->BallVelocityValid() ) {
    float ball_ang_from_body = Mem->BallAngleFromBody(); /* for efficiency */
    LogAction2(90, "turnball_kick: vel is not valid, looking at it");
    DebugKick(printf("turning to face ball\n"));
    if (Mem->CanSeeBallWithNeck()) {
      pCom->time = Mem->CurrentTime;
      pCom->type = CMD_kick;
      pCom->angle = ball_ang_from_body + 180;
      pCom->power = Mem->CP_stop_ball_power;

      pCom->turn_neck = TRUE;
      pCom->turn_neck_angle = Mem->LimitTurnNeckAngle(Mem->BallAngleFromNeck());
    } else {
      /* turn body to face ball, and turn neck to straight ahead */
      pCom->time = Mem->CurrentTime;
      pCom->type = CMD_turn;
	pCom->turn_neck = TRUE;
      if (fabs(ball_ang_from_body) > Mem->MaxEffectiveTurn()) {
	/* out body can't get to where we want to go */
	pCom->angle = 180; /* get our maximum effective turn */
	pCom->turn_neck_angle = ball_ang_from_body -
	  signf(ball_ang_from_body)*Mem->MaxEffectiveTurn();
      } else {
	pCom->angle = ball_ang_from_body;
	pCom->turn_neck_angle = -Mem->MyNeckRelAng();
      }
      
    }
    
    return KT_TurnedToBall;
  } 
  
  DebugKick(printf(" ball.dist: %f\t.dir: %f\n",
	 Mem->BallDistance(), Mem->BallAngle()));
  DebugKick(printf(" HERE ball.vel.x: %f\t.y: %f\tmod: %f\n",
	 Mem->BallRelativeVelocity().x, Mem->BallRelativeVelocity().y,
	 Mem->BallSpeed()));
  DebugKick(printf(" ball.rpos.x: %f\t.y: %f\n",
	 Mem->BallRelativePosition().x, Mem->BallRelativePosition().y));
  DebugKick(printf(" target_dir: %f\n", target_dir));

  if ( fabs(GetNormalizeAngleDeg(target_dir - Mem->BallAngleFromBody())) < Mem->CP_KickTo_err) {
    /* Do something to indicate we are done */
    if (!StopBall || Mem->BallSpeed() < Mem->CP_max_ignore_vel)
      return KT_DidNothing;
    LogAction2(90, "turnball_kick: we're there, stopping the ball");
    DebugKick(printf("  Stop ball kick\n"));
    dir = 0;
    dist = 0;    
    PlayerMovementCorrection(&dir, &dist);
    *pCom = dokick(dir, dist, 1.0);
    pCom->turn_neck = FALSE;
    return KT_Success;
  }

  if (rotate == TURN_AVOID) {
    rotate = RotToAvoidOpponent(target_dir + Mem->MyBodyAng());
  }
  
  if (rotate == TURN_CLOSEST) {
    rotate = RotClosest(target_dir + Mem->MyBodyAng());
  }
  
  
  if (is_straight_kick(target_dir, EndDist, closeMarg)) {
    float pow;
      
    btraj = Polar2Vector(EndDist, target_dir) - Mem->BallRelativeToBodyPosition();
    dir = btraj.dir();
    dist = btraj.mod();
    
    /* now we're goign to do some distance twiddling to get the ball to
       get to the right angle and stop */
    pow = dist / Mem->BallKickRate();
    pow = Min(pow, Mem->CP_max_turn_kick_pow);
    dist = pow * Mem->BallKickRate();
      
    LogAction4(90, "turnball_kick: striaght kick: dist %f at %f", dist, dir);
    DebugKick(printf("  Straight kick# dir: %f dist: %f\n", dir, dist));
    PlayerMovementCorrection(&dir, &dist);
    *pCom = dokick(dir, dist, 1.0);
    pCom->turn_neck = FALSE;

  } else if (Mem->BallDistance() < closeMarg) {

    /* ball is too close to do a tangent kick, so do a kick at 90 degrees */
    dir = ((int)rotate)*(-90) + Mem->BallAngleFromBody();
    dist = 2.0*sqrt(Sqr(Mem->CP_opt_ctrl_dist) - Sqr(Mem->BallDistance()));
    LogAction2(90, "turnball_kick: 90 deg kick");
    DebugKick(printf("  Close kick# dir: %f dist: %f\n", dir, dist));
    PlayerMovementCorrection(&dir, &dist);
    *pCom = dokick(dir, dist, kickFac);
    pCom->turn_neck = FALSE;

  } else {

    /* do a turning kick */
    /* we make a circle around the player of radius closeMarg
       and calculate the trajectory that goes in the right direction and is
       tangent to the circle */
    dir = 180 + Mem->BallAngleFromBody() + ((int)rotate)*ASin(closeMarg / Mem->BallDistance());
    DebugKick(printf(" ball dist: %f\tclosest_margin: %f\n",
	   Mem->BallDistance(), closeMarg));
    dist = sqrt(Sqr(Mem->BallDistance()) - Sqr(closeMarg));
    dist +=
      sqrt(Sqr(Mem->CP_opt_ctrl_dist) - Sqr(closeMarg));
    DebugKick(printf("  Turning ball# dir: %f dist: %f\n", dir, dist));
    LogAction2(90, "turnball_kick: turning kick");
    PlayerMovementCorrection(&dir, &dist);
    *pCom = dokick(dir, dist, kickFac);
    pCom->turn_neck = FALSE;

  }

  return KT_DidKick;
}
Esempio n. 8
0
/* returns KickCommand.time = -1 for error */
TurnKickCommand dokick(AngleDeg ddir, float ddist, float distFactor,
		       Bool* pCanKickToTraj) 
{
  float v0;
  float power;
  float kick_dir = ddir;
  TurnKickCommand com;
  com.time = -1;
  com.type = CMD_kick;
  com.turn_neck = FALSE;
  if (pCanKickToTraj)
    *pCanKickToTraj = TRUE;

  LogAction6(110, "dokick: %.2f (%.2f) at %.2f, rate %.5f",
		  ddist, distFactor, ddir, Mem->BallKickRate());
  
  v0 = ddist * distFactor;

  NormalizeAngleDeg(&ddir);

  DebugKick(printf(" dokick: ddir: %f\tv0: %f\n", ddir, v0));
  DebugKick(printf(" kickrate: %f\tmyang: %f\n", Mem->BallKickRate(), Mem->MyAng() ));

  if (Mem->BallKickRate() == 0.0)
    my_error("dokick: Huh? BallKickRate is 0!");

  if (!Mem->BallVelocityValid()) {
    DebugKick(printf("In dokick with velocity not valid. Assuming it's 0."));
    LogAction2(130, "dokick: assuming vel 0");
  }
  
  if (Mem->BallVelocityValid() &&
      Mem->BallAbsoluteVelocity() != 0) { /* correct for ball velocity */
    Vector tmp = Polar2Vector(v0, ddir) - Mem->BallRelativeToBodyVelocity();
    kick_dir = tmp.dir();
    power = tmp.mod() / Mem->BallKickRate();
    DebugKick(printf(" Correcting for ball velocity# vel.x: %f\tvel.y:%f\n",
	  Mem->BallRelativeVelocity().x, Mem->BallRelativeVelocity().y));
    DebugKick(printf(" New stuff# power: %f\t ddir:%f\n", power, kick_dir));
    LogAction4(130, "dokick: vel corr: %f at %f", power, kick_dir);
  } else {
    LogAction2(130, "dokick: vel is 0");
    power = v0  / Mem->BallKickRate();
  }
  

  if (power > Mem->SP_max_power) {
    DebugKick(printf("Trying to kick over SP_max_power! Correcting...\n"));
    //LogAction2(130, "dokick: trying to kick too hard, correcting");
    if (!Mem->BallVelocityValid() || Mem->BallAbsoluteVelocity() == 0) {
      power = Mem->SP_max_power;
      LogAction4(130, "dokick: max_pow corr: (stopped ball) %f at %f",
		      power, kick_dir);
    } else if (ddist == 0) {
      /* this is probably a stop_ball kick, but ddir is meaningless for
	 the RayCircleIntersection below.
	 Therefore, we just kick against the ball's velocity */
      kick_dir = GetNormalizeAngleDeg(Mem->BallRelativeToBodyHeading() + 180);
      power = Mem->SP_max_power;
      LogAction4(130, "dokick: max_pow corr: (ddist = 0) %f at %f",
		      power, kick_dir);
    } else {
      /* this is a ray circle intersection problem
         We want to kick in the right direction, but not as hard as desired */
      Vector sol1, sol2;
      int numSol;
      Vector vNewTraj;
      numSol =
	RayCircleIntersect(Ray(Mem->BallRelativeToBodyPosition(), ddir),
			   Mem->SP_max_power * Mem->BallKickRate(),
			   Mem->Global2RelativeToMyBody(Mem->BallPredictedPosition()),
			   &sol1, &sol2);
      /* we want the solution that's furthest along the ray - that's sol2
	 if there are two solution */
      if (numSol == 0) {
	/* we can't kick ball to desired trajectory, so let's just slow it
	   down by kicking directly against velocity
	   It might be better to return an error and have the caller decide
	   what to do, but this works pretty well */
	DebugKick(printf("Can't kick ball to right trajectory!\n"));
	power = Mem->SP_max_power;
	kick_dir = Mem->BallRelativeToBodyHeading() + 180;
	if (pCanKickToTraj)
	  *pCanKickToTraj = FALSE;
	LogAction4(130, "dokick: max_pow corr: can't get to trajectory! %.2f at %.2f",
			power, kick_dir);
      } else {
	if (numSol == 1) {
	  vNewTraj = sol1;
	} else if (numSol == 2) {
	  /* we want the solution closer to the target point we wanted */
	  Vector targ = Mem->BallRelativeToBodyPosition() + Polar2Vector(v0, ddir);
	  LogAction8(130, "dokick: 2 solutions (%.2f, %.2f) (%.2f, %.2f) targ (%.2f, %.2f)",
			 sol1.x, sol1.y, sol2.x, sol2.y, targ.x, targ.y);
	  if (sol1.dist2(targ) < sol2.dist2(targ)) {
	    LogAction4(140, "Picked sol1: %.2f < %.2f",
			    sol1.dist2(targ), sol2.dist2(targ));
	    vNewTraj = sol1;
	  } else {
	    LogAction4(140, "Picked sol2: %.2f > %.2f",
			    sol1.dist2(targ), sol2.dist2(targ));	    
	    vNewTraj = sol2;
	  }	  
	} else {
	  my_error("dokick: How many solutions to RayCircleIntersection? %d", numSol);
	}
	
	Vector vNewKick = vNewTraj -
	  Mem->Global2RelativeToMyBody(Mem->BallPredictedPosition());
	power = vNewKick.mod() / Mem->BallKickRate();
	kick_dir = vNewKick.dir();

	DebugKick(printf(" Correcting for ball velocity AND max power# vel.x: %f\tvel.y:%f\n",
	       Mem->BallRelativeVelocity().x, Mem->BallRelativeVelocity().y));
	DebugKick(printf("New stuff# power: %f\t dir:%f\n", power, kick_dir));
	LogAction4(130, "dokick: max_pow corr: %f at %f", power, kick_dir);
      }
    }    
  } 

  power = Min(Round(power, -2), Mem->SP_max_power);
  kick_dir = Round(kick_dir, -2);
  NormalizeAngleDeg(&kick_dir);
  DebugKick(printf("kicking with power: %f at dir: %f\n", power, kick_dir));
  com.time = Mem->CurrentTime;
  com.power = power;
  com.angle = kick_dir;
  return com;
}
Esempio n. 9
0
/* returns whether we are in the right place or not */
Bool go_to_static_ball(float kick_ang, float dash_pow)
{
  Line l;

  LogAction6(50, "go_to_static_ball: ball at (%.1f, %.1f) for kick angle %.2f, dash_pow %.2f",
		  Mem->BallX(), Mem->BallY(), kick_ang, dash_pow);
  
  if (!Mem->BallPositionValid())
    my_error("go_to_static_ball: lost ball");

  /* we can be pretty tolerant of angle errors, but distance errors start to matter
     real quickly */

  Vector targ_pt = get_static_ball_pos(Mem->BallAbsolutePosition(), kick_ang);

  /* we want to try and face the ball at all times */
  turn_neck(Mem->LimitTurnNeckAngle(Mem->BallAngleFromNeck()));
  
  if (Mem->MySpeed() == 0 &&
      Mem->DistanceTo(targ_pt) <= Mem->CP_static_kick_dist_err) {
    LogAction3(60, "go_to_static_ball: I am done %.2f", Mem->DistanceTo(targ_pt));
    return TRUE;
  }

  /* if we are real far from the ball, just use the regular go_to_point */
  if (Mem->BallDistance() > 2 * Mem->My_kickable_area()) {
    LogAction2(60, "go_to_static_ball: far away, using go_to_point");
    if (go_to_point(targ_pt, 0 /* no buffer */, dash_pow)
	!= AQ_ActionQueued)
      my_error("go_to_static_ball: far away, why didn't go_to_point do anything?");
    return FALSE;
  }

  /* make sure that we go around the ball */
  l.LineFromTwoPoints(Mem->MyPos(), targ_pt);
  Vector proj_ball_pt = l.ProjectPoint(Mem->BallAbsolutePosition());
  if (proj_ball_pt.dist(Mem->BallAbsolutePosition()) <=
      Mem->My_size() + Mem->SP_ball_size + Mem->CP_collision_buffer &&
      l.InBetween(proj_ball_pt, Mem->MyPos(), targ_pt)) {
    /* we'll do a 90 degree dodge -we always go right */
    Vector dodge_pt = Mem->MyPos() +
      Polar2Vector(Mem->My_size(), Mem->BallAngleFromBody() + Mem->MyBodyAng() + 90);
    LogAction2(60, "go_to_static_ball: dodging the ball");
    if (go_to_point(dodge_pt, 0 /* no buffer */, dash_pow)
	!= AQ_ActionQueued)
      my_error("go_to_static_ball: dodging, why didn't go_to_point do anything?");
    return FALSE;
  }

  /* now we need to get to the target_point */
  /* first see if we need to turn */
  l.LineFromRay(Mem->MyPos(), Mem->MyBodyAng());
  float ang = Mem->AngleToFromBody(targ_pt);
  if (fabs(ang) > 90 ||
      (l.dist(targ_pt) > Mem->CP_static_kick_dist_err &&
       ang > Mem->CP_static_kick_ang_err)) {
    LogAction2(60, "go_to_static_ball: turning to target_point");
    turn(Mem->AngleToFromBody(targ_pt));
    return FALSE;
  }
  
  /* now calculate the speed we should be going to land right on the point */
  float targ_speed =
    SolveForFirstTermInfGeomSeries(Mem->My_decay(), Mem->DistanceTo(targ_pt));
  float dash_pow_to_use =
    MinMax(-dash_pow / 2,
	   (targ_speed - Mem->MySpeed()) / Mem->My_dash_power_rate(),
	   dash_pow);
  LogAction5(60, "go_to_static_ball: targ_speed: %.2f\tMySpeed: %.2f\tdash_pow: %.2f",
	    targ_speed, Mem->MySpeed(), dash_pow_to_use);
  if (fabs(dash_pow_to_use) > 1) {
    LogAction3(70, "go_to_static_ball: dash power is too small %.2f", dash_pow_to_use);
    dash(Mem->CorrectDashPowerForStamina(dash_pow_to_use));
    return FALSE;
  }

  return TRUE;
}
Esempio n. 10
0
Vector get_static_ball_pos(Vector ball_pos, float kick_ang)
{
  return ball_pos + Polar2Vector(Mem->CP_hardest_kick_ball_dist, kick_ang);
}