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 + -
显示快捷键?