设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 1966|回复: 0
打印 上一主题 下一主题

[已经解决] 这个寻路脚本,怎么让他到达目标后不要跑来跑去

[复制链接]

Lv4.逐梦者

梦石
0
星屑
12157
在线时间
4435 小时
注册时间
2014-4-11
帖子
5955

开拓者

跳转到指定楼层
1
发表于 2016-2-24 21:40:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
我想要到达目标后就不要动,当坐标差<=1时不移动


RUBY 代码复制
  1. #==================================================================#
  2. # AStar Core v1.01 by 禾西 on 2012.01.02
  3. #------------------------------------------------------------------#
  4. # (此算法基于 4 方向)
  5. # public methods
  6. # * new(Game_Map map)
  7. #     生成關聯地圖的 A* 實例
  8. # * set_origin(int ox, int oy)
  9. #     設置起始點(超過地圖范圍會引起 Runtime Error )
  10. # * set_target(int tx, int ty)
  11. #     設置終止點(超過地圖范圍會引起 Runtime Error )
  12. # * Array do_search(bool print_rst = false)
  13. #     進行尋路,返回包含移動信息的數組
  14. #
  15. # private methods
  16. # * int _f(x, y)
  17. #     f 值算法
  18. # * print_data
  19. #     數據打印算法(此方法僅在 do_search(true) 時被使用)
  20. #==================================================================#
  21. #
  22. #調用方法
  23. #    astr = AStar.new($game_map)
  24. #    astr.set_origin($game_player.x, $game_player.y)
  25. #    astr.set_target(0, 0)
  26. #    path = astr.do_search
  27. #
  28. #==================================================================#
  29. class AStar
  30.   Point = Struct.new(:x, :y)
  31.   public
  32.   # ============================================================== #
  33.   # 初始化數據
  34.   # ============================================================== #
  35.   def initialize(map)
  36.     @map_width  = map.width
  37.     @map_height = map.height
  38.     @g_data = Table.new(@map_width, @map_height)
  39.     @f_data = Table.new(@map_width, @map_height)
  40.     @p_data = Table.new(@map_width, @map_height)
  41.     @ox = 0;@oy = 0
  42.     @tx = 0;@ty = 0
  43.     @openList = []
  44.     @g = 0
  45.     @search_done = false
  46.   end
  47.   # ============================================================== #
  48.   # 設置 起始點
  49.   # ============================================================== #
  50.   def set_origin(ox, oy)
  51.     @ox = ox;@oy = oy
  52.     if is_Overmap(ox, oy)
  53.       raise RuntimeError, "Origin location is overmap!"
  54.     end
  55.   end
  56.   # ============================================================== #
  57.   # 設置 目標點
  58.   # ============================================================== #
  59.   def set_target(tx, ty)
  60.     @tx = tx;@ty = ty
  61.     if is_Overmap(tx, ty)
  62.       raise RuntimeError, "Target location is overmap!"
  63.     end
  64.   end
  65.   # ============================================================== #
  66.   # 開始尋路
  67.   # ============================================================== #
  68.   # 主邏輯
  69.   def do_search(print_rst = false)
  70.     x = @ox;y = @oy
  71.     @g_data[x, y] = 2;@f_data[x, y] = 1
  72.     @openList << [x, y]
  73.     t0 = Time.now
  74.     t = 0
  75.     begin
  76.       t += 1
  77.       point = @openList.shift
  78.       return [] if point == nil
  79.     check_4dir(point[0], point[1]) # ->檢查 4 方向
  80.     end until @search_done
  81.     if @g_data[@tx,@ty] == 1
  82.       @tx = point[0];@ty = point[1];
  83.     end
  84.     t1 = Time.now
  85.     make_path # ->生成路徑
  86.     if print_rst
  87.       print "#{t1 - t0}, #{t}\n"
  88.       print_data # ->打印數據
  89.     end
  90.     return @path
  91.   end
  92.  
  93.   private
  94.   # ============================================================== #
  95.   # 檢查 4 方向
  96.   def check_4dir(x, y)
  97.     @g = @g_data[x, y] + 1
  98.     mark_point(x, y - 1, 8) # ->檢查單點
  99.     mark_point(x, y + 1, 2) # ->檢查單點
  100.     mark_point(x - 1, y, 4) # ->檢查單點
  101.     mark_point(x + 1, y, 6) # ->檢查單點
  102.   end
  103.   # ============================================================== #
  104.   # 檢查單點
  105.   def mark_point(x, y, dir)
  106.         if x == @tx && y == @ty
  107.       @search_done = true
  108.     end
  109.  
  110.     if is_Overmap(x, y) # ->檢查地圖是否超界
  111.       return
  112.     end
  113.     if @g_data[x, y] > 1
  114.       return
  115.     end
  116.     if check_passibility(x, y, dir) # ->檢查通行度
  117.       f = _f(x, y)
  118.       @g_data[x, y] = @g
  119.       @f_data[x, y] = f
  120.       point = @openList[0]
  121.       if point.nil?
  122.         @openList.push [x, y]
  123.       elsif (f <= @f_data[point[0], point[1]])
  124.         @openList.unshift [x, y]
  125.       else
  126.         @openList.push [x, y]
  127.       end
  128.     else
  129.       @g_data[x, y] = 1
  130.       @f_data[x, y] = _f(x, y)
  131.     end
  132.   end
  133.   # ============================================================== #
  134.   # 生成路徑
  135.   def make_path
  136.     x = @tx;y = @ty
  137.     @path = []
  138.     while !(x == @ox && y == @oy) #TODO:有過多障礙時死轉……
  139.       @g = @g_data[x, y]
  140.       @best_f = 0
  141.       dir = 0
  142.       dir = make_step(x, y - 1, 2)||dir # ->生成單步
  143.       dir = make_step(x, y + 1, 8)||dir # ->生成單步
  144.       dir = make_step(x - 1, y, 6)||dir # ->生成單步
  145.       dir = make_step(x + 1, y, 4)||dir # ->生成單步
  146.       @path.unshift(dir)
  147.       case dir
  148.       when 2 then y -= 1;
  149.       when 8 then y += 1;
  150.       when 6 then x -= 1;
  151.       when 4 then x += 1;
  152.       end
  153.       @p_data[x, y] = 1
  154.     end
  155.   end
  156.   # ============================================================== #
  157.   # 生成單步
  158.   def make_step(x, y, dir)
  159.     if @g_data[x, y].nil? || @p_data[x, y] == 1
  160.       return nil
  161.     end
  162.     if (@g - @g_data[x, y]) == 1 || @g == 1
  163.       f = @f_data[x, y]
  164.       if f > 0 && (@best_f == 0 || f < @best_f)
  165.         @best_f = f
  166.         return dir
  167.       end
  168.     end
  169.     return nil
  170.   end
  171.   # ============================================================== #
  172.   # 檢查地圖通行度
  173.   def check_passibility(x, y, dir)
  174.     case dir
  175.     when 2 then y -= 1;
  176.     when 8 then y += 1;
  177.     when 4 then x += 1;
  178.     when 6 then x -= 1;
  179.     end
  180.     return $game_player.passable?(x, y, dir)
  181.   end
  182.   # ============================================================== #
  183.   # 檢查地圖是否超界
  184.   def is_Overmap(x, y)
  185.     return (x|y|(@map_width - x - 1)|(@map_height - y - 1)) < 0
  186.   end
  187.   # ============================================================== #
  188.   # f 值算法
  189.   def _f(x, y)
  190.     return ((x - @tx).abs + (y - @ty).abs) + @g
  191.   end
  192.   # ============================================================== #
  193.   # 打印數據
  194.   def print_data
  195.     strf = ""
  196.     strg = ""
  197.     for y in [email]0...@f_data.ysize[/email]
  198.       for x in [email]0...@f_data.xsize[/email]
  199.         if @f_data[x, y] == 0
  200.           strf += "  "
  201.         else
  202.           strf += sprintf("%02d", @f_data[x, y])
  203.         end
  204.         strf += ","
  205.         if @g_data[x, y] < 2
  206.           strg += sprintf("%02d", @g_data[x, y])#"  "
  207.         else
  208.           strg += sprintf("%02d", @g_data[x, y])
  209.         end
  210.         strg += ","
  211.       end
  212.       strf += "\n"
  213.       strg += "\n"
  214.     end
  215.     print "f:\n"
  216.     print strf + "\n"
  217.     print "g:\n"
  218.     print strg + "\n"
  219.     strp = ""
  220.     for y in [email]0...@p_data.ysize[/email]
  221.       for x in [email]0...@p_data.xsize[/email]
  222.         if @p_data[x, y] == 0
  223.           strp += "  "
  224.         else
  225.           strp += sprintf("%02d", @p_data[x, y])
  226.         end
  227.         strp += ","
  228.       end
  229.       strp += "\n"
  230.     end
  231.  
  232.     print "p:\n"
  233.     print strp
  234.     print @path
  235.   end
  236. end
  237.  
  238. class Game_Character
  239.   def move_dr(dr)
  240.     case dr
  241.     when 1
  242.       move_lower_left
  243.     when 2
  244.       move_down
  245.     when 3
  246.       move_lower_right
  247.     when 4
  248.       move_left
  249.     when 6
  250.       move_right
  251.     when 7
  252.       move_upper_left
  253.     when 8
  254.       move_up
  255.     when 9
  256.       move_upper_right
  257.     else
  258.       move_toward_player
  259.     end
  260.   end
  261. #简化脚本,在事件中需要调用的命令减少,并可在移动规则中自定义。
  262. #使用命令:astarmove(终止ID,出发ID(可不填,不填则默认为该事件))
  263. #id:0为player,其他为事件
  264.   def astarmove(to = 0,from = "self")
  265.     from = @id if from=="self"
  266.     astr = AStar.new($game_map)
  267.     from = from==0 ? $game_player : $game_map.events[from]
  268.     to = to==0 ? $game_player : $game_map.events[to]
  269.     #p from.id,to.id if from.is_a?(Game_Event)
  270.     unless from.moving?
  271.       if from != nil and to != nil
  272.       astr.set_origin(from.x,from.y)
  273.       astr.set_target(to.x,to.y)
  274.       dr = astr.do_search
  275.       move_dr(dr[0])
  276.       end
  277.     end
  278.   end
  279. end
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-9-22 19:35

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表