//当单位配置中 keepdist = 1 时,攻击时将尽量保持与目标间的距离为自己的攻击距离 public static void update_keep_atk_range(IBaseUnit sprite, long tm_elasped_s) { var pl = sprite.get_pack_data(); if (pl.atking == null) { return; } if (sprite.has_state(pl_state_type.PST_CANT_MOVE)) { // can't move return; } var gmap = sprite.gmap; if (gmap.has_sprite_by_iid(pl.atking.tar_iid)) { //Utility.trace_err("monster["+this.mondata.iid+"] atking tar_iid[" + this.mondata.atking.tar_iid +"] cur tm[" +cur_clock_tm+"] last_trace_tm ["+ last_trace_target_tm +"] \n"); var target = gmap.map_sprites[pl.atking.tar_iid]; var tar_pl = target.get_pack_data(); double dist_x = pl.x - tar_pl.x; double dist_y = pl.y - tar_pl.y; var dist2 = dist_x * dist_x + dist_y * dist_y; var dist = Math.Sqrt(dist2); var atk_rang2 = pl.atkrange * pl.atkrange; // 处于最佳攻击距离 var best_atk_rang = pl.atkrange; if (dist.CompareTo(best_atk_rang) <= 0) { //Utility.trace_info("atk_trace stop:"+dist2+"="+atk_rang2+"\n"); if (pl.moving != null) { //// 停止移动 ////var cur_grid_pos = {x=(pl.x/game_const.map_grid_pixel), y=(pl.y/game_const.map_grid_pixel)} //var data = {tm=sys.clock_time()- pl.atking.trace_tm_left, iid=pl.iid, x=pl.x, y=pl.y, face=pl.face}; //// send stop move msg to clients ////gmap.broadcast_map_rpc(10, data); //sprite.broad_cast_zone_msg_and_self(10, data); //delete pl.moving; pl.moving = null; } } else { //if(dist > best_atk_rang) //{ // Utility.trace_info("atk_trace:"+dist+">"+best_atk_rang+"\n"); //} //else if(dist < best_atk_rang) //{ // Utility.trace_info("atk_trace:"+dist+"<"+best_atk_rang+"\n"); //} // 保持距离 //var cur_pos = gmap.get_grid_by_pt(pl.x, pl.y); //var tar_pos = gmap.get_grid_by_pt(tar_pl.x, tar_pl.y); //var k = (best_atk_rang / dist); //var best_pos = {}; //best_pos.x <- (tar_pos.x + (cur_pos.x - tar_pos.x) * k); //best_pos.y <- (tar_pos.y + (cur_pos.y - tar_pos.y) * k); // 计算和目标之间的角度atan(a),范围为[-PI/2, PI/2],为了获得整个圆周的范围,当(x<0)时角度为:PI+atan(a) /* * | * (-,-)|(+,-) * -----O------>X * (-,+)|(+,+) * | * \/Y */ double alpha = 0; if (dist != 0) { alpha = Math.PI / 2; if (dist_x != 0) { alpha = Math.Atan((dist_y / dist_x)); if (dist_x < 0) { alpha += Math.PI; } } else if (dist_y < 0) { alpha = -Math.PI / 2; } } //Utility.trace_info("atan("+dist_y+"/"+dist_x+"="+k+")="+alpha+"\n"); // 在最佳攻击距离圈上选取最近可达点 var new_pos = gmap.valpoint_on_round(tar_pl.x, tar_pl.y, best_atk_rang, alpha); if (new_pos != null) { new_pos = gmap.get_grid_by_pt(new_pos.x, new_pos.y); sprite._move_to(new_pos.x, new_pos.y); } //Utility.trace_info("keep range pos:("+tar_pos.x+","+tar_pos.y+","+best_atk_rang+")->("+new_pos.x+","+new_pos.y+")\n"); } } }