查看: 1840|回复: 0

[已经解决] 求助,帮忙把这个寻路脚本这几句改一下,不然太卡了

[复制链接]
梦石
0
星屑
12161
在线时间
4435 小时
注册时间
2014-4-11
回帖
5616

开拓者

发表于 2016-4-8 01:23:52 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 yang1zhi 于 2016-4-9 00:03 编辑

我添加了等待解决了
[pre lang="ruby"]class Game_Character
  def move_dr(dr)
    case dr
    when 2
      move_down
          @wait_count += 1
    when 4
      move_left
          @wait_count += 1
    when 6
      move_right
          @wait_count += 1
    when 8
      move_up
          @wait_count += 1
    else
      move_toward_player
    @wait_count += 1
    end
  end
[/pre]


[pre lang="ruby"]  # ============================================================== #
  # 生成路徑
  def make_path
    x = @tx;y = @ty
    @path = []
   # while !(x == @ox && y == @oy) #TODO:有過多障礙時死轉……
      @g = @g_data[x, y]
      @best_f = 0
      dir = 0
      dir = make_step(x, y - 1, 2)||dir # ->生成單步
      dir = make_step(x, y + 1, 8)||dir # ->生成單步
      dir = make_step(x - 1, y, 6)||dir # ->生成單步
      dir = make_step(x + 1, y, 4)||dir # ->生成單步
      @path.unshift(dir)
      case dir
      when 2 then y -= 1;
      when 8 then y += 1;
      when 6 then x -= 1;
      when 4 then x += 1;
      end
      @p_data[x, y] = 1
   # end
  end
  # ============================================================== #
[/pre]
就是那个注释里写着TODO:有過多障礙時死轉……那个。
障碍多了就不寻路,还有重点是目标被围住后变得很卡。
我把他#了后就不卡了。不过他们就变成了背对我。

是被障碍挡住过不来的事件造成很卡,不是身边的
1.png

寻路脚本[pre lang="ruby"]#==================================================================#
# AStar Core v1.01 by 禾西 on 2012.01.02
#------------------------------------------------------------------#
# (此算法基于 4 方向)
# public methods
# * new(Game_Map map)
#     生成關聯地圖的 A* 實例
# * set_origin(int ox, int oy)
#     設置起始點(超過地圖范圍會引起 Runtime Error )
# * set_target(int tx, int ty)
#     設置終止點(超過地圖范圍會引起 Runtime Error )
# * Array do_search(bool print_rst = false)
#     進行尋路,返回包含移動信息的數組
#
# private methods
# * int _f(x, y)
#     f 值算法
# * print_data
#     數據打印算法(此方法僅在 do_search(true) 時被使用)
#==================================================================#
#
#調用方法
#    astr = AStar.new($game_map)
#    astr.set_origin($game_player.x, $game_player.y)
#    astr.set_target(0, 0)
#    path = astr.do_search
#
#==================================================================#
class AStar
  Point = Struct.new(:x, :y)
  public
  # ============================================================== #
  # 初始化數據
  # ============================================================== #
  def initialize(map)
    @map_width  = map.width
    @map_height = map.height
    @g_data = Table.new(@map_width, @map_height)
    @f_data = Table.new(@map_width, @map_height)
    @p_data = Table.new(@map_width, @map_height)
    @ox = 0;@oy = 0
    @tx = 0;@ty = 0
    @openList = []
    @g = 0
    @search_done = false
  end
  # ============================================================== #
  # 設置 起始點
  # ============================================================== #
  def set_origin(ox, oy)
    @ox = ox;@oy = oy
    if is_Overmap(ox, oy)
      raise RuntimeError, "Origin location is overmap!"
    end
  end
  # ============================================================== #
  # 設置 目標點
  # ============================================================== #
  def set_target(tx, ty)
    @tx = tx;@ty = ty
    if is_Overmap(tx, ty)
      raise RuntimeError, "Target location is overmap!"
    end
  end
  # ============================================================== #
  # 開始尋路
  # ============================================================== #
  # 主邏輯
  def do_search(print_rst = false)
    x = @ox;y = @oy
    @g_data[x, y] = 2;@f_data[x, y] = 1
    @openList << [x, y]
    t0 = Time.now
    t = 0
    begin
      t += 1
      point = @openList.shift
      return [] if point == nil
    check_4dir(point[0], point[1]) # ->檢查 4 方向
    end until @search_done
    if @g_data[@tx,@ty] == 1
      #到达目的地后不跑来跑去
      @tx = point[0];@ty = point[1];
end
    t1 = Time.now
    make_path # ->生成路徑
    if print_rst
      print "#{t1 - t0}, #{t}\n"
      print_data # ->打印數據
    end
    return @path
  end

  private
  # ============================================================== #
  # 檢查 4 方向
  def check_4dir(x, y)
    @g = @g_data[x, y] + 1
    mark_point(x, y - 1, 8) # ->檢查單點
    mark_point(x, y + 1, 2) # ->檢查單點
    mark_point(x - 1, y, 4) # ->檢查單點
    mark_point(x + 1, y, 6) # ->檢查單點
  end
  # ============================================================== #
  # 檢查單點
  def mark_point(x, y, dir)
        if x == @tx && y == @ty
      @search_done = true
    end

    if is_Overmap(x, y) # ->檢查地圖是否超界
      return
    end
    if @g_data[x, y] > 1
      return
    end
    if check_passibility(x, y, dir) # ->檢查通行度
      f = _f(x, y)
      @g_data[x, y] = @g
      @f_data[x, y] = f
      point = @openList[0]
      if point.nil?
        @openList.push [x, y]
      elsif (f <= @f_data[point[0], point[1]])
        @openList.unshift [x, y]
      else
        @openList.push [x, y]
      end
    else
      @g_data[x, y] = 1
      @f_data[x, y] = _f(x, y)
    end
  end
  # ============================================================== #
  # 生成路徑
  def make_path
    x = @tx;y = @ty
    @path = []
   # while !(x == @ox && y == @oy) #TODO:有過多障礙時死轉……
      @g = @g_data[x, y]
      @best_f = 0
      dir = 0
      dir = make_step(x, y - 1, 2)||dir # ->生成單步
      dir = make_step(x, y + 1, 8)||dir # ->生成單步
      dir = make_step(x - 1, y, 6)||dir # ->生成單步
      dir = make_step(x + 1, y, 4)||dir # ->生成單步
      @path.unshift(dir)
      case dir
      when 2 then y -= 1;
      when 8 then y += 1;
      when 6 then x -= 1;
      when 4 then x += 1;
      end
      @p_data[x, y] = 1
   # end
  end
  # ============================================================== #
  # 生成單步
  def make_step(x, y, dir)
    if @g_data[x, y].nil? || @p_data[x, y] == 1
      return nil
    end
    if (@g - @g_data[x, y]) == 1 || @g == 1
      f = @f_data[x, y]
      if f > 0 && (@best_f == 0 || f < @best_f)
        @best_f = f
        return dir
      end
    end
    return nil
  end
  # ============================================================== #
  # 檢查地圖通行度
  def check_passibility(x, y, dir)
    case dir
    when 2 then y -= 1;
    when 8 then y += 1;
    when 4 then x += 1;
    when 6 then x -= 1;
    end
    return $game_player.passable?(x, y, dir)
  end
  # ============================================================== #
  # 檢查地圖是否超界
  def is_Overmap(x, y)
    return (x|y|(@map_width - x - 1)|(@map_height - y - 1)) < 0
  end
  # ============================================================== #
  # f 值算法
  def _f(x, y)
    return ((x - @tx).abs + (y - @ty).abs) + @g
  end
  # ============================================================== #
  # 打印數據
  def print_data
    strf = ""
    strg = ""
    for y in 0...@f_data.ysize
      for x in 0...@f_data.xsize
        if @f_data[x, y] == 0
          strf += "  "
        else
          strf += sprintf("%02d", @f_data[x, y])
        end
        strf += ","
        if @g_data[x, y] < 2
          strg += sprintf("%02d", @g_data[x, y])#"  "
        else
          strg += sprintf("%02d", @g_data[x, y])
        end
        strg += ","
      end
      strf += "\n"
      strg += "\n"
    end
    print "f:\n"
    print strf + "\n"
    print "g:\n"
    print strg + "\n"
    strp = ""
    for y in 0...@p_data.ysize
      for x in 0...@p_data.xsize
        if @p_data[x, y] == 0
          strp += "  "
        else
          strp += sprintf("%02d", @p_data[x, y])
        end
        strp += ","
      end
      strp += "\n"
    end

    print "p:\n"
    print strp
    print @path
  end
end

class Game_Character
  def move_dr(dr)
    case dr
    when 1
      move_lower_left
    when 2
      move_down
    when 3
      move_lower_right
    when 4
      move_left
    when 6
      move_right
    when 7
      move_upper_left
    when 8
      move_up
    when 9
      move_upper_right
    else
      move_toward_player
    end
  end
#简化脚本,在事件中需要调用的命令减少,并可在移动规则中自定义。
#使用命令:astarmove(终止ID,出发ID(可不填,不填则默认为该事件))
#id:0为player,其他为事件
  def astarmove(to = 0,from = "self")
    from = @id if from == "self"
    astr = AStar.new($game_map)
    from = from == 0 ? $game_player : $game_map.events[from]
    if to == 0
      to = $game_player
      else
    to =  $game_map.events[to]
  end
            if from != nil and to != nil
    unless to.x == from.x and to.y == from.y
    #p from.id,to.id if from.is_a?(Game_Event)
#    unless from.moving?
###################################################################
#当是穿透的时候
####################################################################
if  self.through == true
      move_toward_eventxx(to)
    else
      astr.set_origin(from.x,from.y)
      astr.set_target(to.x,to.y)
      dr = astr.do_search
      move_dr(dr[0])
      end
      end
    end
  end
end[/pre]
   
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部