intercept_util.cpp

来自「2002年」· C++ 代码 · 共 534 行 · 第 1/2 页

CPP
534
字号
					final_solution = 0;
				else
					final_solution = 1;
			}
			else{
			//try to intercept with front side
				ballvel = ballvel.Rotate(-selfbodyfacing);
				Vector next_ball_pos = ballvel + ballrelpos;
				if (Vector(solution[0], 0).dist2(next_ball_pos) > Vector(solution[1], 0).dist2(next_ball_pos))
					final_solution = 1;
				else
					final_solution =0;
			}
			
			dashpow = solution[final_solution] / dash_rate;
		}
	}else{
		min_dist = (float)sqrt(Sqr(fabs(ballrelpos.x) - maxdasheffect) + Sqr(ballrelpos.y));
		getball_dist = min_dist;
		if (min_dist < kickable_area){
			if (testonly)
				return true;
			if (min_dist >= ClientParam::desired_kickarea){
				dashpow = ServerParam::max_power;
			}
			else{
				dashpow = Max(float(fabs(ballrelpos.x) - sqrt(Sqr(ClientParam::desired_kickarea) - Sqr(ballrelpos.y))) / dash_rate, -ServerParam::max_power);
			}
		}
	}

	if (testonly){
		DoLog(LOG_IT, "maxdasheffect %.2f min_dist %.2f", maxdasheffect, min_dist);
	}

	if (dashpow == 2 * ServerParam::max_power) return false;
	if (ballrelpos.x < 0) dashpow *= -1.0f;

	return true;
}

int Intercept_util::Close_to_ball_line_intercept(Vector selfpos, Vector ballpos, Vector selfvel, Vector ballvel, 
		float selfbodyfacing, float dist_player, float dist_ball, float& dashpow, int maxcycles, bool testonly){
//Try just 3 cycles, last cycle is a adjusting cycle	
	float dashpow_first;
	int i;
	for(i = 1; i <= maxcycles; i ++){
		if (OneCycleIntercept(selfpos, ballpos, selfvel, ballvel, selfbodyfacing, dashpow, testonly || i != 1))
			break;
		//do not move beyond the ball line
		
		dashpow = Min(ServerParam::max_power, (dist_player - selfvel.mod()) / dash_rate);
		
		simulate_one_dash_step(selfpos, ballpos, selfvel, ballvel, selfbodyfacing, dashpow);
		dist_player -= selfvel.mod()/player_decay ;
		dist_ball -= ballvel.mod() / ServerParam::ball_decay;
		if(i == 1){
			dashpow_first = dashpow;
		}
	}

	if (i > maxcycles) // I am not able to intercept it in three cycles
		return -1;

	if (testonly)
		return i;

	if (i != 1){
		if(dashpow != dashpow_first){
			DoLog(LOG_IT, "fix dash (o)%.0f (f)%.0f", dashpow, dashpow_first);
		}
		dashpow = dashpow_first;
	//more delicate control can be added here
		if (i == 2){
		// to avoid collision
			dashpow += TwoCycleAvoidEnemy_Adjust(selfpos, ballpos, selfvel, ballvel, selfbodyfacing);
		}
		DoLog(LOG_IT, "Close to ball line dash pow %.2f %d %.2f", dashpow, i, dist_player);
	}
	return i;
}

int Intercept_util::OnlyDashIntercept(int maxcycles, Vector selfpos, Vector ballpos, Vector selfvel, Vector ballvel, float selfbodyfacing, float& dashpow, bool testonly){
//Ok, see if dashes will bring me close to the ball
	if (maxcycles <= 0)
		return -1;
	float bak_dash = -200.0f, bak_balldist;
	if (OneCycleIntercept(selfpos, ballpos, selfvel, ballvel, selfbodyfacing, dashpow, testonly)){
		//trivial fix for safe close it
		if(getball_dist > 0.9f && safecloseit && !testonly
			&& fabs(selfbodyfacing) < 30 && dashpow < ServerParam::max_power){
			bak_balldist = getball_dist; bak_dash = dashpow;
			simulate_one_dash_step(selfpos, ballpos, selfvel, ballvel, selfbodyfacing, ServerParam::max_power);
			if(OneCycleIntercept(selfpos, ballpos, selfvel, ballvel, selfbodyfacing, dashpow, testonly)){
				if(getball_dist < bak_balldist){
					dashpow = ServerParam::max_power;
					DoLog("safe dash it");
					return 2;
				}
			}
			dashpow = bak_dash;
			getball_dist = bak_balldist;
		}
		return 1;
	}

	Vector intersection_pt;
	Ray ball_course(ballpos, ballvel), player_course(selfpos, selfbodyfacing);
	float dist_ball, dist_player;

	//selffacing is parallel to ball course, unable to get intersection point
	if (ball_course.InRightDir(selfbodyfacing) || ball_course.InOppositeDir(selfbodyfacing)
		|| (ballvel.mod2() < Sqr(0.5f) && player_course.InRightDir((ballpos - selfpos).Angle()))){
		if (ballvel.mod2() > 0.3f){
			if ((ball_course.InRightDir(selfbodyfacing) && ball_course.InRightDir(selfpos))
				|| (ball_course.InOppositeDir(selfbodyfacing) && ball_course.InOppositeDir(selfpos))){
				return -1;
			}
		}
		int i;
		for(i = 2; i <= maxcycles; i ++){
			simulate_one_dash_step(selfpos, ballpos, selfvel, ballvel, selfbodyfacing);
			if (OneCycleIntercept(selfpos, ballpos, selfvel, ballvel, selfbodyfacing, dashpow, testonly || i != 1))
				break;				
		}
		if (i <= maxcycles){
			if (!testonly){
				if (i == 2){
					dashpow = ServerParam::max_power + TwoCycleAvoidEnemy_Adjust(selfpos, ballpos, selfvel, ballvel, selfbodyfacing);
				}
				else
					dashpow = ServerParam::max_power;
			}
			return i;
		}
		return -1;
	}
	
	ball_course.intersection(player_course, intersection_pt);
	dist_ball = ballpos.dist(intersection_pt);
	dist_player = selfpos.dist(intersection_pt);
	
// intercept with more than maxcycles is beyond the reach of this function
	if (dist_player > maxcycles * max_speed + kickarea)
		return -1;
	if (dist_ball  > ballvel.mod() * (1 - Exp(ServerParam::ball_decay, (float)maxcycles)) / (1 - ServerParam::ball_decay) + kickarea){
		if(!testonly && safecloseit && dist_player > 1.5f && AngleDifference(selfbodyfacing, (intersection_pt-selfpos).Angle()) <90) {
			if(dist_ball < ballvel.mod() * (1 - Exp(ServerParam::ball_decay, (float)maxcycles+1.0f)) / (1 - ServerParam::ball_decay) + kickarea){
				return -2;
			}else if(dist_ball < ballvel.mod() * (1 - Exp(ServerParam::ball_decay, (float)maxcycles+2.0f)) / (1 - ServerParam::ball_decay) + kickarea){
				return -3;
			}
		}else 
			return -1;
	}
	if (!player_course.InRightDir(intersection_pt) || !ball_course.InRightDir(intersection_pt)) // no hope
		return -1;
//simulate running num_cycles cycles
	int num_cycles = int((dist_player - kickarea) / max_speed);
	int i;
	for(i =0; i < num_cycles; i++){
		simulate_one_dash_step(selfpos, ballpos, selfvel, ballvel, selfbodyfacing);
		dist_ball -= ballvel.mod() / ServerParam::ball_decay;
		dist_player -= selfvel.mod() / player_decay;
		if (dist_ball < -kickarea) // the ball is passing by
			return -1;
	}
	
	//num_cycles = Close_to_ball_line_intercept(selfpos, ballpos, selfvel, ballvel, selfbodyfacing, dist_player, dist_ball, dashpow, IT_closeball_max_cycles - num_cycles, testonly || i != 0);
	num_cycles = Close_to_ball_line_intercept(selfpos, ballpos, selfvel, ballvel, selfbodyfacing, dist_player, dist_ball, dashpow, 3, testonly || i != 0);

	if (num_cycles == -1) return -1;
	if (i > 0){
		dashpow = rundash_power;
	}

	return i + num_cycles;
}

int Intercept_util::TurnDashIntercept(int maxcycles, Vector selfpos, Vector ballpos, Vector selfvel, Vector ballvel, float selfbodyfacing, InterceptionInfo & inf, bool test){
	Vector predicted_selfpos, predicted_ballpos, predicted_selfvel, predicted_ballvel;
	InterceptionInfo bak_inf;
	float bak_dist;
	bak_inf.IT_valid = false;
	int cycles;
	
	float dashpow;

	simulate_one_dash_step(selfpos, ballpos, selfvel, ballvel, 0, 0);
 
	predicted_selfpos = selfpos; predicted_ballpos = ballpos;
	predicted_selfvel = selfvel; predicted_ballvel = ballvel;

	float turnangle = 0, lastturnangle;
	int i;
	for(i = 1; i < maxcycles; i ++){
		lastturnangle = turnangle;
		turnangle = (predicted_ballpos + predicted_ballvel - predicted_selfpos - predicted_selfvel).Angle();	
		cycles = OnlyDashIntercept(maxcycles, selfpos, ballpos, selfvel, ballvel, turnangle, dashpow, true);

		if (cycles >= 0 && cycles <= i){
			inf.IT_is_closeball = true;
			inf.IT_angle = turnangle;
			inf.IT_cycles = float(cycles + 1);
			inf.IT_point = ballpos + ballvel * (1 - Exp(ServerParam::ball_decay, (float)cycles)) / (1 - ServerParam::ball_decay);
			inf.IT_valid = true;
			if(safecloseit && getball_dist > 0.8f){
				if(!bak_inf.IT_valid){					
					double gangle = fabs(NormalizeAngle(turnangle - ballvel.Angle()));
					if(gangle < 40){
						return cycles;
					}
					bak_inf = inf;
					bak_dist = getball_dist;
				}else{//compare bak_inf to inf
					if(getball_dist >= bak_dist){
						inf = bak_inf;						
						getball_dist = bak_dist;
					}else{
						DoLog("safe close it %.2f-%.2f", getball_dist, bak_dist);
					}
					return (int)inf.IT_cycles - 1;
				}				
			}else{
				if(bak_inf.IT_valid) {					
					DoLog("safe close it %.2f-%.2f", getball_dist, bak_dist);
				}
				return cycles;
			}
		}else if(bak_inf.IT_valid){
			inf = bak_inf;			
			getball_dist = bak_dist;
			return (int)inf.IT_cycles - 1;
		}
		simulate_one_dash_step(predicted_selfpos, predicted_ballpos, predicted_selfvel, predicted_ballvel, 0, 0);
	}
	if(bak_inf.IT_valid){
		inf = bak_inf;
		return (int)inf.IT_cycles - 1;
	}
	return -1;
}

float Intercept_util::TwoCycleAvoidEnemy_Adjust(Vector selfpos, Vector ballpos, Vector selfvel, Vector ballvel, float selfbodyfacing){
	Vector ballrelpos = ballpos + ballvel - selfpos - selfvel;
	float t, t_dashpow = 0.0f;
	if (ballrelpos.mod2() < Sqr(ClientParam::collision_threshold)){
		ballrelpos = ballrelpos.Rotate(- selfbodyfacing);
		t = ballrelpos.x - (float)sqrt(Sqr(ClientParam::desired_kickarea) - Sqr(ballrelpos.y));
		t_dashpow = t / ( dash_rate * (1 + player_decay));
		DoLog(LOG_IT, " two cycle adjust %.2f pow %.2f", t, t_dashpow);
	}
	return t_dashpow;
}

void Intercept_util::simulate_one_dash_step(Vector& selfpos, Vector& ballpos, Vector& selfvel, Vector& ballvel, float bodyfacing, float dashpow){
	selfvel += Polar2Vector(dashpow, bodyfacing) * dash_rate;
	if (selfvel.mod2() > Sqr(max_speed)){
		selfvel = selfvel / selfvel.mod() * max_speed;
	}
	selfpos += selfvel;
	ballpos += ballvel;
	
	selfvel *= player_decay;
	ballvel *= ServerParam::ball_decay;
}

⌨️ 快捷键说明

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