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

Project1

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

[已经解决] 求助,帮我把这个寻路脚本改成一次走一步,不要一路走完

[复制链接]

Lv4.逐梦者

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

开拓者

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

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

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

x
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.       #到达目的地后不跑来跑去
  83.    #   @tx = point[0];@ty = point[1];
  84.     end
  85.     t1 = Time.now
  86.     make_path # ->生成路徑
  87.     if print_rst
  88.       print "#{t1 - t0}, #{t}\n"
  89.       print_data # ->打印數據
  90.     end
  91.     return @path
  92.   end
  93.  
  94.   private
  95.   # ============================================================== #
  96.   # 檢查 4 方向
  97.   def check_4dir(x, y)
  98.     @g = @g_data[x, y] + 1
  99.     mark_point(x, y - 1, 8) # ->檢查單點
  100.     mark_point(x, y + 1, 2) # ->檢查單點
  101.     mark_point(x - 1, y, 4) # ->檢查單點
  102.     mark_point(x + 1, y, 6) # ->檢查單點
  103.   end
  104.   # ============================================================== #
  105.   # 檢查單點
  106.   def mark_point(x, y, dir)
  107.         if x == @tx && y == @ty
  108.       @search_done = true
  109.     end
  110.  
  111.     if is_Overmap(x, y) # ->檢查地圖是否超界
  112.       return
  113.     end
  114.     if @g_data[x, y] > 1
  115.       return
  116.     end
  117.     if check_passibility(x, y, dir) # ->檢查通行度
  118.       f = _f(x, y)
  119.       @g_data[x, y] = @g
  120.       @f_data[x, y] = f
  121.       point = @openList[0]
  122.       if point.nil?
  123.         @openList.push [x, y]
  124.       elsif (f <= @f_data[point[0], point[1]])
  125.         @openList.unshift [x, y]
  126.       else
  127.         @openList.push [x, y]
  128.       end
  129.     else
  130.       @g_data[x, y] = 1
  131.       @f_data[x, y] = _f(x, y)
  132.     end
  133.   end
  134.   # ============================================================== #
  135.   # 生成路徑
  136.   def make_path
  137.     x = @tx;y = @ty
  138.     @path = []
  139.     while !(x == @ox && y == @oy) #TODO:有過多障礙時死轉……
  140.       @g = @g_data[x, y]
  141.       @best_f = 0
  142.       dir = 0
  143.       dir = make_step(x, y - 1, 2)||dir # ->生成單步
  144.       dir = make_step(x, y + 1, 8)||dir # ->生成單步
  145.       dir = make_step(x - 1, y, 6)||dir # ->生成單步
  146.       dir = make_step(x + 1, y, 4)||dir # ->生成單步
  147.       @path.unshift(dir)
  148.       case dir
  149.       when 2 then y -= 1;
  150.       when 8 then y += 1;
  151.       when 6 then x -= 1;
  152.       when 4 then x += 1;
  153.       end
  154.       @p_data[x, y] = 1
  155.     end
  156.   end
  157.   # ============================================================== #
  158.   # 生成單步
  159.   def make_step(x, y, dir)
  160.     if @g_data[x, y].nil? || @p_data[x, y] == 1
  161.       return nil
  162.     end
  163.     if (@g - @g_data[x, y]) == 1 || @g == 1
  164.       f = @f_data[x, y]
  165.       if f > 0 && (@best_f == 0 || f < @best_f)
  166.         @best_f = f
  167.         return dir
  168.       end
  169.     end
  170.     return nil
  171.   end
  172.   # ============================================================== #
  173.   # 檢查地圖通行度
  174.   def check_passibility(x, y, dir)
  175.     case dir
  176.     when 2 then y -= 1;
  177.     when 8 then y += 1;
  178.     when 4 then x += 1;
  179.     when 6 then x -= 1;
  180.     end
  181.     return $game_player.passable?(x, y, dir)
  182.   end
  183.   # ============================================================== #
  184.   # 檢查地圖是否超界
  185.   def is_Overmap(x, y)
  186.     return (x|y|(@map_width - x - 1)|(@map_height - y - 1)) < 0
  187.   end
  188.   # ============================================================== #
  189.   # f 值算法
  190.   def _f(x, y)
  191.     return ((x - @tx).abs + (y - @ty).abs) + @g
  192.   end
  193.   # ============================================================== #
  194.   # 打印數據
  195.   def print_data
  196.     strf = ""
  197.     strg = ""
  198.     for y in [email]0...@f_data.ysize[/email]
  199.       for x in [email]0...@f_data.xsize[/email]
  200.         if @f_data[x, y] == 0
  201.           strf += "  "
  202.         else
  203.           strf += sprintf("%02d", @f_data[x, y])
  204.         end
  205.         strf += ","
  206.         if @g_data[x, y] < 2
  207.           strg += sprintf("%02d", @g_data[x, y])#"  "
  208.         else
  209.           strg += sprintf("%02d", @g_data[x, y])
  210.         end
  211.         strg += ","
  212.       end
  213.       strf += "\n"
  214.       strg += "\n"
  215.     end
  216.     print "f:\n"
  217.     print strf + "\n"
  218.     print "g:\n"
  219.     print strg + "\n"
  220.     strp = ""
  221.     for y in [email]0...@p_data.ysize[/email]
  222.       for x in [email]0...@p_data.xsize[/email]
  223.         if @p_data[x, y] == 0
  224.           strp += "  "
  225.         else
  226.           strp += sprintf("%02d", @p_data[x, y])
  227.         end
  228.         strp += ","
  229.       end
  230.       strp += "\n"
  231.     end
  232.  
  233.     print "p:\n"
  234.     print strp
  235.     print @path
  236.   end
  237. end
  238.  
  239. class Game_Character
  240.   def move_dr(dr)
  241.     case dr
  242.     when 1
  243.       move_lower_left
  244.     when 2
  245.       move_down
  246.     when 3
  247.       move_lower_right
  248.     when 4
  249.       move_left
  250.     when 6
  251.       move_right
  252.     when 7
  253.       move_upper_left
  254.     when 8
  255.       move_up
  256.     when 9
  257.       move_upper_right
  258.     else
  259.       move_toward_player
  260.     end
  261.   end
  262. #简化脚本,在事件中需要调用的命令减少,并可在移动规则中自定义。
  263. #使用命令:astarmove(终止ID,出发ID(可不填,不填则默认为该事件))
  264. #id:0为player,其他为事件
  265.   def astarmove(to = 0,from = "self")
  266.     from = @id if from=="self"
  267.     astr = AStar.new($game_map)
  268.     from = from == 0 ? $game_player : $game_map.events[from]
  269.     if to == 0
  270.       to = $game_player
  271.       else
  272.     to =  $game_map.events[to]
  273.     end
  274.     #p from.id,to.id if from.is_a?(Game_Event)
  275. #    unless from.moving?
  276.       if from != nil and to != nil
  277.       astr.set_origin(from.x,from.y)
  278.       astr.set_target(to.x,to.y)
  279.       dr = astr.do_search
  280.       move_dr(dr[0])
  281. #     end
  282.     end
  283.   end
  284. end

Lv2.观梦者

梦石
0
星屑
409
在线时间
286 小时
注册时间
2015-10-4
帖子
294
2
发表于 2016-2-28 13:06:38 | 只看该作者
直接修改移动频率和移动速度不行吗?

点评

我试了下,似乎并不是这个的问题,用靠近主角也会那样,我需要再试试  发表于 2016-2-28 13:33
不行。要用这个做AI。但是一路走到底的话,走的途中就不好判断了。每走一步就跳出来,然后判断  发表于 2016-2-28 13:24
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

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

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

GMT+8, 2024-11-11 21:37

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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