Project1

标题: 怎么看自动寻路的路程 [打印本页]

作者: weew163com    时间: 2016-12-13 18:04
标题: 怎么看自动寻路的路程
本帖最后由 VIPArcher 于 2016-12-13 18:54 编辑

这是我网上下的自动寻路脚本
想要可以输出一个变量显示他寻路的路程
比如找到寻路最短路线是6格就输出6
或者有更好的脚本有人提供下吗OAO
谢谢!
RUBY 代码复制
  1. #encoding:utf-8
  2. #==============================================================================
  3. #   ■ 事件自动寻路
  4. #
  5. #   本插件的前置插件为:《多帧4_8方图,4_8向行走》+《多帧事件连续移动》
  6. #   1.定点,障碍绕行,可后台超低速寻路,保障帧率
  7. #   2.多个事件一起寻路,帧率影响不太明显,但会寻路比较慢
  8. #------------------------------------------------------------------------------
  9. #使用说明:
  10. #   让事件可以寻路,调用make_passing(true),false则该事件不能寻路
  11. #   自动寻向指定点,move_toward_pos(x,y)函数
  12. #   取消当前寻路指令,cancel_pathing函数
  13. #   如果有几个事件一起寻路的话,最好不要同时放出,建议间隔10帧,若目标很远要隔久一点。
  14. #   若要追逐玩家的话,不要每帧都追,隔几十帧追一下。
  15. #
  16. #   注意:是全地图搜索。越远越慢,地形越迷宫越慢,建议距离不要超过100图块
  17. #------------------------------------------------------------------------------
  18. #  by rmav (有任何问题请毫无顾忌滴提出)
  19. #
  20. #  
  21. #   v1.04 若在路径中发生意外,重新寻路
  22. #==============================================================================
  23. $imported ||= {}
  24. $imported[:rmav_pathing] = 20140213.1
  25. module Rmav
  26.   Opt_pathing={
  27.     detour: true,       #在路径上碰到临时障碍,是否绕行
  28.                         ##不绕行的话,障碍消失,会自动继续下去
  29.  
  30.     total_cycles: 50,   #越大寻路越快,但在超大地图迷宫地形上相隔很远的话,容易卡顿
  31.                         ##如果在游戏中掉帧明显,可降低10
  32.  
  33.     failed_and_stop: false,  #全地图寻路失败时,停止
  34.     failed_and_rand: false,  #全地图寻路失败时,随机移动
  35.     failed_and_back: true    #全地图寻路失败时,在后台极低速一直寻路
  36.                              ##全地图寻路失败时,以上只能三选一
  37.  
  38.   }
  39.  
  40.  
  41.  
  42. class Path_node
  43. attr_accessor :i,:j,:f,:g,:h,:pre,:next,:pos
  44.         def initialize(point=[0,0])
  45.                 @i=point[0]
  46.                 @j=point[1]
  47.                 @f=@g=@h=0
  48.                 @pre=@next=nil
  49.         end
  50.         def p
  51.                 [@i,@j]
  52.         end
  53.  
  54.         def cal_fgh(s_p, e_p)
  55.                 if @pre
  56.                         @g=@pre.g+(@pre.p[0]-@i).abs+(@pre.p[1]-@j).abs
  57.                 else
  58.                         @g=(s_p[0]-@i).abs+(s_p[1]-@j).abs
  59.                 end
  60.                 @h=(e_p[0]-@i).abs+(e_p[1]-@j).abs
  61.                 @f=@g+@h
  62.         end
  63. end
  64.  
  65. class Pathfinder
  66.   @@total_cycles_per_frame=Rmav::Opt_pathing[:total_cycles]
  67.   @@left_cycles_curFrame=Rmav::Opt_pathing[:total_cycles]
  68.   @@finder_cnt=0
  69.   @@total_low_speeds=0
  70.   @@mini_cycles_per_frame=10
  71.   @@mini_finder_cnt=0
  72.   @@low_speed_max=10
  73.   def initialize(passable,p_max=[99,99],p_min=[0,0])
  74.     @open_nodes=[]
  75.     @open_points={}
  76.     @close_points={}
  77.     @passable=passable
  78.                 @p_min=p_min
  79.                 @p_max=p_max
  80.     @cancel=false
  81.     @mini_cancel=false
  82.     @low_speed=0
  83.   end
  84.   def set_low_speed(low_speed)
  85.     tmp=[low_speed,@@low_speed_max].min
  86.     if @@total_low_speeds+@low_speed<@@total_cycles_per_frame      
  87.       @low_speed=tmp
  88.       @@total_low_speeds+=@low_speed
  89.     end   
  90.   end
  91.   def self.reset_left_cycles
  92.     @@left_cycles_curFrame=Rmav::Opt_pathing[:total_cycles]
  93.   end
  94.   def self.clear_left_cycles
  95.     @@left_cycles_curFrame=0
  96.   end
  97.  
  98.  
  99.  
  100. def min_heapify(sz,i)
  101.         return nil if sz.size<=i || i<0
  102.         l_child=r_child=min_child=0
  103.         cur_size=sz.size
  104.         i_node=sz[i]
  105.         loop do
  106.                 l_child=2*i+1
  107.                 r_child=2*i+2
  108.                 if l_child>=cur_size
  109.                         break
  110.                 elsif r_child>=cur_size
  111.                         min_child=l_child
  112.                 else
  113.                         min_child=
  114.                         (sz[l_child].f<=sz[r_child].f)?(l_child):(r_child)
  115.                 end
  116.  
  117.                 if sz[min_child].f>=i_node.f
  118.                         break
  119.                 else
  120.                         sz[i]=sz[min_child]
  121.                         sz[i].pos=i
  122.                         i=min_child
  123.                 end
  124.         end
  125.         sz[i]=i_node
  126.         sz[i].pos=i
  127. end
  128.  
  129. def heap_extract_min(sz)
  130.         return nil if sz.size<=0
  131.         min=sz[0]
  132.         sz[0] = sz[-1]
  133.         sz[0].pos=0
  134.         sz.pop
  135.         min_heapify(sz,0)
  136.         min
  137. end
  138.  
  139. def heap_decrease_key(sz,i,f)
  140.         return nil if sz.size<=0|| sz[i].f<=f
  141.  
  142.         sz[i].f=f
  143.         tmp=i
  144.         i_node=sz[i]
  145.         parent=0
  146.         loop do
  147.                 parent=(tmp-1)/2
  148.                 if sz[parent].f>f
  149.                         sz[tmp]=sz[parent]
  150.                         sz[tmp].pos=tmp
  151.                         tmp=parent
  152.                 else
  153.                         break
  154.                 end
  155.           break if parent<=0
  156.         end
  157.         sz[tmp]=i_node
  158.         sz[tmp].pos=tmp
  159. end
  160.  
  161.  
  162. def min_heap_insert(sz,node)
  163.         f=node.f
  164.         node.f=999999999
  165.         node.pos=sz.size
  166.         sz<<node
  167.         heap_decrease_key(sz,sz.size-1,f)
  168. end
  169.  
  170. def adj_p(p,d,p_max=@p_max,p_min=@p_min)
  171.   case d
  172.   when 2; [p[0],p[1]+1]  if p[1]+1<=p_max[1]
  173.   when 4; [p[0]-1,p[1]]  if p[0]-1>=p_min[0]
  174.   when 6; [p[0]+1,p[1]]  if p[0]+1<=p_max[0]
  175.   when 8; [p[0],p[1]-1]  if p[1]-1>=p_min[1]
  176.   end
  177. end
  178.  
  179. def a_star(start_p,end_p)
  180.   return nil if start_p==end_p
  181.   @cancel=false
  182.   @@finder_cnt+=1
  183.   while (@@total_cycles_per_frame-@@total_low_speeds)/@@finder_cnt<8
  184.     Fiber.yield
  185.     if @cancel
  186.       @@finder_cnt-=1
  187.       @@total_low_speeds-=@low_speed
  188.       @low_speed=0
  189.       return nil
  190.     end
  191.   end
  192.         @open_nodes.clear
  193.         @open_points.clear
  194.         @close_points.clear
  195.   cycles_cnt=0
  196.         reach_end_node=nil
  197.         start_node=Path_node.new(start_p)
  198.         @open_nodes<<start_node
  199.                 node = @open_nodes.shift       
  200.                 [2,4,6,8].each{|d|
  201.       point=adj_p(node.p,d)
  202.                         if point&&@passable.call(node.i,node.j,d)
  203.                                 tmp=Path_node.new(point)
  204.                                 tmp.pre=node
  205.                                 tmp.cal_fgh(start_p, end_p)
  206.                                 min_heap_insert(@open_nodes,tmp)
  207.                                 @open_points[tmp.p]=tmp
  208.                         end
  209.                 }
  210.                 @close_points[node.p]=node
  211.  
  212.         while(@open_nodes.size>0)
  213.  
  214.     if @low_speed>0
  215.       if cycles_cnt>@low_speed
  216.         @@left_cycles_curFrame-=cycles_cnt
  217.         cycles_cnt=0
  218.         Fiber.yield
  219.       end
  220.     elsif cycles_cnt>(@@total_cycles_per_frame-@@total_low_speeds)/@@finder_cnt
  221.       @@left_cycles_curFrame-=cycles_cnt
  222.       cycles_cnt=0
  223.       Fiber.yield
  224.     end
  225.     if @cancel      
  226.       break
  227.     end
  228.     if @@left_cycles_curFrame<1
  229.       Fiber.yield
  230.       break if @cancel
  231.     end
  232.  
  233.                 min=heap_extract_min(@open_nodes)
  234.                 @open_points.delete(min.p)
  235.                 [2,4,6,8].each{|d|
  236.       point=adj_p(min.p,d)
  237.       next unless point
  238.       if point==end_p
  239.           tmp=Path_node.new(point)
  240.                                         tmp.pre=min         
  241.                                         reach_end_node=tmp
  242.         break
  243.       end
  244.                         if point!=min.pre.p&&@passable.call(min.i,min.j,d)
  245.                                 if !@close_points.has_key?(point)                                 
  246.                                         tmp=Path_node.new(point)
  247.                                         tmp.pre=min
  248.                                         tmp.cal_fgh(start_p, end_p)
  249.                                         tmp2=@open_points[tmp.p]
  250.                                         if tmp2
  251.                                                 if tmp2.g>tmp.g
  252.                                                         tmp2_f_pre=tmp2.f
  253.                                                         tmp2.pre=min
  254.                                                         tmp2.g=tmp.g
  255.                                                         new_f=tmp.g+tmp.h                                                       
  256.                                                         heap_decrease_key(@open_nodes,tmp2.pos,new_f)
  257.                                                 end
  258.                                         else       
  259.                                                 min_heap_insert(@open_nodes,tmp)
  260.                                                 @open_points[tmp.p]=tmp
  261.  
  262.           end
  263.  
  264.                                 end
  265.  
  266.                         end
  267.                 }
  268.                 @close_points[min.p]=min
  269.                 break if reach_end_node
  270.                 cycles_cnt+=1
  271.         end
  272.   @@finder_cnt-=1
  273.   @@total_low_speeds-=@low_speed
  274.   @low_speed=0
  275.   @open_nodes.clear
  276.         @open_points.clear
  277.         @close_points.clear
  278.         reach_end_node
  279. end
  280.  
  281. def terminate
  282.         @open_nodes.clear
  283.         @open_points.clear
  284.         @close_points.clear
  285. end
  286.  
  287. def mini_star(start_p,end_p,view=9)
  288.   return nil if start_p==end_p
  289.   @mini_cancel=false
  290.   @@mini_finder_cnt+=1
  291.   while @@mini_cycles_per_frame/@@mini_finder_cnt<5
  292.     Fiber.yield
  293.     if @mini_cancel
  294.       @@mini_finder_cnt-=1
  295.       return nil
  296.     end
  297.   end
  298.   cycles_cnt=0
  299.  
  300.   p_min=[];p_max=[]
  301.   p_min[0]=(start_p[0]<end_p[0])?(start_p[0]-view/2):(end_p[0]-view/2)
  302.   p_min[1]=(start_p[1]<end_p[1])?(start_p[1]-view/2):(end_p[1]-view/2)
  303.   p_max[0]=(start_p[0]>end_p[0])?(start_p[0]+view/2):(end_p[0]+view/2)
  304.   p_max[1]=(start_p[1]>end_p[1])?(start_p[1]+view/2):(end_p[1]+view/2)
  305.   p_min[0]=@p_min[0] if p_min[0]<@p_min[0]
  306.   p_min[1]=@p_min[1] if p_min[1]<@p_min[1]
  307.   p_max[0]=@p_max[0] if p_max[0]>@p_max[0]
  308.   p_max[1]=@p_max[1] if p_max[1]>@p_max[1]
  309.         open_nodes=[]
  310.         open_points={}
  311.         close_points={}
  312.         reach_end_node=nil
  313.         start_node=Path_node.new(start_p)
  314.  
  315.         open_nodes<<start_node
  316.                 node = open_nodes.shift       
  317.                 [2,4,6,8].each{|d|
  318.       point=adj_p(node.p,d,p_max,p_min)
  319.                         if point&&@mini_passable.call(node.i,node.j,d)
  320.  
  321.                                 tmp=Path_node.new(point)
  322.                                 tmp.pre=node
  323.                                 tmp.cal_fgh(start_p, end_p)
  324.                                 min_heap_insert(open_nodes,tmp)
  325.                                 open_points[tmp.p]=tmp
  326.                         end
  327.                 }
  328.                 close_points[node.p]=node
  329.         while(open_nodes.size>0)
  330.  
  331.     if cycles_cnt>@@mini_cycles_per_frame/@@mini_finder_cnt
  332.       cycles_cnt=0
  333.       Fiber.yield
  334.     end
  335.     if @mini_cancel
  336.         break
  337.     end
  338.                 min=heap_extract_min(open_nodes)
  339.                 open_points.delete(min.p)
  340.                 [2,4,6,8].each{|d|
  341.       point=adj_p(min.p,d,p_max,p_min)
  342.       next unless point
  343.       if point==end_p
  344.           tmp=Path_node.new(point)
  345.                                         tmp.pre=min
  346.                                         reach_end_node=tmp       
  347.         break
  348.       end
  349.                         if point!=min.pre.p&&@mini_passable.call(min.i,min.j,d)        
  350.                                 if !close_points.has_key?(point)
  351.                                         tmp=Path_node.new(point)
  352.                                         tmp.pre=min
  353.                                         tmp.cal_fgh(start_p, end_p)
  354.                                         tmp2=open_points[tmp.p]
  355.                                         if tmp2
  356.                                                 if tmp2.g>tmp.g
  357.                                                         tmp2_f_pre=tmp2.f
  358.                                                         tmp2.pre=min
  359.                                                         tmp2.g=tmp.g
  360.                                                         new_f=tmp.g+tmp.h                                                       
  361.                                                         heap_decrease_key(open_nodes,tmp2.pos,new_f)
  362.                                                 end
  363.                                         else       
  364.                                                 min_heap_insert(open_nodes,tmp)
  365.                                                 open_points[tmp.p]=tmp
  366.                                         end
  367.  
  368.                                 end
  369.  
  370.                         end
  371.                 }
  372.                 close_points[min.p]=min
  373.                 break if reach_end_node
  374.                 cycles_cnt+=1
  375.         end
  376.   @@mini_finder_cnt-=1
  377.   open_nodes.clear
  378.         open_points.clear
  379.         close_points.clear
  380.         reach_end_node
  381. end
  382.  
  383. def cancel
  384.   @cancel=@mini_cancel=true
  385. end
  386. def mini_cancel
  387.   @mini_cancel=true
  388. end
  389. def set_localpassable_method(method)
  390.   @mini_passable=method
  391. end
  392. def set_pass_method(method)
  393.   @passable=method
  394. end
  395.  
  396. end#class Pathfinder
  397. end#module Rmav
  398.  
  399.  
  400. class Game_Event
  401.   alias_method :initialize_org_event_rmav_7,:initialize
  402.   def initialize(map_id, event)
  403.     initialize_org_event_rmav_7(map_id, event)
  404.  
  405.     @path_finder=false
  406.   end
  407.   def make_passing(enable=true)
  408.     @path_finder=enable
  409.     init_pathing if enable
  410.   end
  411.   def init_pathing
  412.     @path_to_point=nil
  413.     @blocked_cnt=0
  414.     @repassable=Proc.new{|x,y,d| passable_ex?(x, y, d)}
  415.   end
  416.  
  417.   #--------------------------------------------------------------------------
  418.   # ● 判定是否可以通行(检查 地图的通行度 和 前方是否有路障)
  419.   #     d : 方向(2,4,6,8)
  420.   #--------------------------------------------------------------------------
  421.   def passable_ex?(x, y, d)
  422.     x2 = $game_map.round_x_with_direction(x, d)
  423.     y2 = $game_map.round_y_with_direction(y, d)
  424.     return false unless $game_map.valid?(x2, y2)
  425.     return true if @through || debug_through?
  426.     return false unless map_passable?(x, y, d)
  427.     return false unless map_passable?(x2, y2, reverse_dir(d))
  428.     return false if collide_with_characters?(x2, y2)
  429.     return false if $game_player.pos_nt?(x2, y2)
  430.     return true
  431.   end
  432.  
  433.   def find_path_to(x,y)
  434.       cancel_pathing
  435.       @path_to_point=[x,y]
  436.       @pathnode=nil
  437.       passable_method=Proc.new{|x,y,d| $game_map.passable?(x,y,d)}
  438.       unless @pathfinder
  439.         @pathfinder=Rmav::Pathfinder.new(
  440.              passable_method,[$game_map.width,$game_map.height])
  441.  
  442.       end
  443.       @pathfinder.set_pass_method(passable_method)
  444.       @pathing=Fiber.new{
  445.         @pathnode=@pathfinder.a_star([x,y],[@x,@y])
  446.         @pathing=nil
  447.       }
  448.   end
  449.  
  450.   def move_toward_pos(x,y)
  451.     if @path_to_point!=[x,y]
  452.       find_path_to(x,y)
  453.     end
  454.   end
  455.  
  456.   def repath_to(x,y,speed_ctl=0)
  457.       reset_pathing
  458.       node=nil
  459.       unless @pathfinder
  460.         @pathfinder=Rmav::Pathfinder.new(
  461.              nil,[$game_map.width,$game_map.height])
  462.  
  463.       end
  464.       @pathfinder.set_pass_method(@repassable)
  465.       @pathfinder.set_low_speed(speed_ctl)
  466.       @pathing=Fiber.new{
  467.         @pathnode=@pathfinder.a_star([x,y],[@x,@y])
  468.         @pathing=nil
  469.       }
  470.  
  471.   end
  472.  
  473.   def local_pathing(s_p,e_p)
  474.      return nil unless @pathfinder
  475.      reset_local_pathing
  476.      @mini_node=nil
  477.      @pathfinder.set_localpassable_method(@repassable)
  478.      @local_pathing=Fiber.new{
  479.        @mini_node=@pathfinder.mini_star(s_p,e_p)
  480.        @local_pathing=nil
  481.      }
  482.   end
  483.  
  484. def reset_pathing
  485.     @pathnode=nil
  486.     @pathfinder.cancel if @pathfinder
  487.     @pathing.resume    if @pathing
  488.  
  489.     @repathing.resume if @repathing
  490.     @local_pathing.resume if @local_pathing
  491. end
  492. def cancel_pathing
  493.   @path_to_point=nil
  494.   reset_pathing
  495. end
  496. def reset_local_pathing
  497.   @pathfinder.mini_cancel if @pathfinder
  498.   @local_pathing.resume if @local_pathing
  499. end
  500.  
  501.   alias_method :update_self_movement_rmav_org_rmav_7,:update_self_movement_rmav
  502.   def update_self_movement_rmav
  503.     return if moving? || @move_route_forcing
  504.     if @path_finder&&!$game_map.interpreter.running?
  505.  
  506.       return unless @path_to_point#没有目标点
  507.       if near_the_screen?
  508.  
  509.         if @pathing
  510.           @pathing.resume;return
  511.         end
  512.         if @repathing
  513.           @repathing.resume;return
  514.         end
  515.         if @local_pathing
  516.           @local_pathing.resume;return
  517.         end
  518.         unless @pathnode  #全地图寻路失败
  519.           @rand_steps||=1
  520.             if Rmav::Opt_pathing[:failed_and_rand]
  521.               if (@rand_steps%=3)!=0
  522.                 move_type_random_rmav
  523.                 @rand_steps+=1
  524.               elsif @stop_count>180
  525.                 move_type_random_rmav
  526.                 @rand_steps+=1
  527.               end
  528.             elsif Rmav::Opt_pathing[:failed_and_back]  
  529.               repath_to(*@path_to_point,2)
  530.             end
  531.           return
  532.         end
  533.         @pathnode=@pathnode.pre if @pathnode.p==[@x,@y]
  534.         if @pathnode
  535.           #@path_to_point=nil if @[email protected] #到达目的         
  536.           dx=@pathnode.p[0]-@x
  537.           dy=@pathnode.p[1]-@y
  538.  
  539.           if Rmav::Opt_walk[:dir8_on]
  540.             if @pathnode.pre&&@pathnode.pre.p[0]!=@x&&@pathnode.pre.p[1]!=@y
  541.               dx=@pathnode.pre.p[0]-@x
  542.               dy=@pathnode.pre.p[1]-@y
  543.  
  544.             end
  545.           end
  546.           if dx.abs>1||dy.abs>1
  547.             @pathnode=nil
  548.             repath_to(*@path_to_point,10)
  549.             return
  550.           end
  551.           move_diagonal([0,6,4][dx],[0,2,8][dy])
  552.             if @move_succeed
  553.               @path_to_point=nil if @path_to_point==@pathnode.p #到达目的
  554.               if Rmav::Opt_walk[:dir8_on]&&dx.abs==dy.abs
  555.                 @pathnode=@pathnode.pre.pre
  556.               else
  557.                 @pathnode=@pathnode.pre
  558.               end
  559.               @failed_node=nil
  560.               @blocked_cnt=0
  561.             else
  562.             #挡住了
  563.             @blocked_cnt+=1
  564. #p "dang~~~"
  565.               if Rmav::Opt_walk[:dir8_on]&&dx.abs==dy.abs
  566.                 @failed_node=@pathnode.pre
  567.               else
  568.                 @failed_node=@pathnode
  569.               end
  570.  
  571.               if Rmav::Opt_pathing[:detour]
  572.                 if @blocked_cnt>60
  573.                   repath_to(*@path_to_point,10)
  574.                   @blocked_cnt=1                  
  575.                 else               
  576.                     if @failed_node.pre
  577.                        if collide_with_characters?(*@failed_node.pre.p)
  578.                          failed_node=@failed_node.pre
  579.                        else
  580.                          failed_node=@failed_node
  581.                        end
  582.                        if failed_node.pre &&!collide_with_characters?(*failed_node.pre.p)
  583.  
  584.                           if @mini_node
  585.                             tmp2_node=@mini_node
  586.                             while tmp2_node&&tmp2_node.pre
  587.                               tmp2_node=tmp2_node.pre
  588.                             end
  589.                             tmp2_node.pre=@failed_node_reserved.pre.pre
  590.                             @pathnode=@mini_node                             
  591.                             @mini_node=nil
  592.                             @failed_node_reserved=nil
  593.                             while @pathnode&&@pathnode.p!=[@x,@y]
  594.                               @pathnode=@pathnode.pre
  595.                             end
  596.                           else
  597.                             if @local_pathing
  598.                               @local_pathing.resume
  599.                             else
  600.                               @failed_node_reserved=failed_node
  601.                               local_pathing(failed_node.pre.p,[@x,@y])
  602.                             end                          
  603.                           end
  604.                        else#后续多点被堵
  605.                         #repathing
  606.                         repath_to(*@path_to_point) if @blocked_cnt>5
  607.                        end
  608.  
  609.                     else
  610.                         #终点被占用,到达倒数第2点
  611.                     end
  612.                   end#@blocked_cnt
  613.                 else#指定不绕,会停在那直到障碍移开
  614.                  #不用处理,不绕
  615.                 end
  616.             end
  617.  
  618.         end
  619.       end
  620.       return
  621.     end
  622.     update_self_movement_rmav_org_rmav_7
  623.   end
  624. end
  625.  
  626.  
  627. class Scene_Base
  628.   alias_method :update_org_base_rmav_7,:update
  629.   def update
  630.     Rmav::Pathfinder.reset_left_cycles
  631.     update_org_base_rmav_7
  632.   end
  633. end
发代码可以使用代码框<>工具 —— VIPArcher 留




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1