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

Project1

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

[已经解决] 怪物在地图上移动的AI

[复制链接]

Lv1.梦旅人

梦石
0
星屑
50
在线时间
53 小时
注册时间
2013-2-16
帖子
24
跳转到指定楼层
1
发表于 2013-10-22 13:53:13 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

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

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

x
把怪物放在地图上设置接近玩家

但是怪物和玩家中间只要隔着一个障碍物

怪物就被卡住了

请问该如何做才能让怪物撞到墙壁时

会自动寻找四周有没有通路可以走

而不是直接卡在那里不动呢

评分

参与人数 1星屑 +7 收起 理由
熊喵酱 + 7 主動認可獎勵

查看全部评分

Lv5.捕梦者

梦石
0
星屑
22713
在线时间
8623 小时
注册时间
2011-12-31
帖子
3367
2
发表于 2013-10-22 14:08:54 | 只看该作者
本帖最后由 tseyik 于 2013-10-22 14:35 编辑

経路探索VXAce
http://canarialt.blog.fc2.com/blog-entry-43.html

範本(含有其他脚本)
https://skydrive.live.com/redir. ... ey=!ACU2FoKV2gdVl-w
注釈取得スクリプト (VX Ace用)
RUBY 代码复制
  1. #==============================================================================
  2. # ■ 注釈取得スクリプト (VX Ace用)
  3. #------------------------------------------------------------------------------
  4. # 製作者     : CanariAlternate
  5. # サイト名   : カルトの鳥篭
  6. # サイトURL  : [url]http://canarialt.blog.fc2.com[/url]
  7. #------------------------------------------------------------------------------
  8. # ■ 概要 : 注釈を取得する処理を定義する。
  9. #
  10. # ■ 必須 : なし
  11. #
  12. # ■ 位置 : 「Game_Event」より下
  13. #------------------------------------------------------------------------------
  14. # ■ 注釈での設定方法
  15. #   以下の例のように実行内容の1行目から注釈以外のコマンドまでの注釈のどこかに
  16. #   キーワードを記述すると有効(結果を反転してる場合には無効)になります。
  17. #
  18. #             例 : 実行内容
  19. #                   ◆注釈:キーワードA キーワードC
  20. #                   :    :キーワードG キーワードF
  21. #                   :    :キーワードE
  22. #                   ◆注釈:キーワードD
  23. #                   :    :キーワードH キーワードB
  24. #                   ◆変数の操作などの注釈以外のイベントコマンド
  25. #                   ◆注釈:ここ以下に書いても無視される。
  26. #                   ◆
  27. #
  28. # ※キーワードとなる文字列の設定は正規表現です。詳しいことはヘルプを「正規表現」で検索すると出てきます。
  29. #   簡単に言うと / で囲まれた文字列があるかないかで判定します。
  30. #   \ とか ! みたいな記号を使いたい時はヘルプを参照して下さい。
  31. #   設定例、/\[キーワード\]/  #=>  [キーワード]
  32. #
  33. # ※キーワードを記述すると有効と無効が切り替わります。初期状態は無効です。
  34. #   例 : 初期状態を反転, 記述したイベントの全ての頁を反転, 記述した頁のみを反転
  35. #   まず  「初期状態を反転」                  で有効に
  36. #   次に  「記述したイベントの全ての頁を反転」で無効に
  37. #   最後に「記述した頁のみを反転」            で有効に
  38. #------------------------------------------------------------------------------
  39. # 更新履歴 : 2012/10/05 Ver1.00 コードを共通処理スクリプトに統一
  40. #            2012/10/06 Ver1.01 コードを共通処理スクリプトから分離
  41. #            2012/10/08 Ver1.02 コードの整理
  42. #            2013/02/19 Ver1.03 共通処理スクリプトの廃止による変更を施した。
  43. #==============================================================================
  44.  
  45. $imported ||= {}
  46. $imported[:CanariAlternate_EventNote] = true
  47.  
  48. #==============================================================================
  49. # ■ Calt
  50. #------------------------------------------------------------------------------
  51. #  CanariAlternateが製作したスクリプトの管理用モジュール
  52. #==============================================================================
  53. module Calt
  54.   #--------------------------------------------------------------------------
  55.   # ● イベントコマンドから注釈を取得 [新規]
  56.   #--------------------------------------------------------------------------
  57.   def self.Read_EventNote(list)
  58.     return String.new unless list && list[i = 0].code == 108
  59.     note = list[i].parameters[0]
  60.     note += "\n#{list[i].parameters[0]}" while [108, 408].include?(list[i += 1].code)
  61.     return note
  62.   end
  63. end
  64.  
  65. #==============================================================================
  66. # ■ Game_Event
  67. #------------------------------------------------------------------------------
  68. #  イベントを扱うクラスです。条件判定によるイベントページ切り替えや、並列処理
  69. # イベント実行などの機能を持っており、Game_Map クラスの内部で使用されます。
  70. #==============================================================================
  71. class Game_Event < Game_Character
  72.   #--------------------------------------------------------------------------
  73.   # ● イベントページの設定をセットアップ [追加]
  74.   #--------------------------------------------------------------------------
  75.   alias setup_page_settings_EventNote setup_page_settings
  76.   def setup_page_settings
  77.     setup_page_settings_EventNote
  78.     setup_note_settings
  79.   end
  80.   #--------------------------------------------------------------------------
  81.   # ● イベントページ更新時に注釈から設定を取得 [新規]
  82.   #--------------------------------------------------------------------------
  83.   def setup_note_settings
  84.     # 注釈の取得処理はここに追加
  85.   end
  86.   #--------------------------------------------------------------------------
  87.   # ● 1頁目の注釈にキーワードが含まれているか判定 [新規]
  88.   #--------------------------------------------------------------------------
  89.   def whole_note_include?(keyword)
  90.     return @event.pages[0].event_note =~ keyword ? true : false
  91.   end
  92.   #--------------------------------------------------------------------------
  93.   # ● この頁の注釈にキーワードが含まれているか判定 [新規]
  94.   #--------------------------------------------------------------------------
  95.   def event_note_include?(keyword)
  96.     return @page.event_note =~ keyword ? true : false
  97.   end
  98. end
  99.  
  100. #==============================================================================
  101. # ■ RPG::Event::Page
  102. #------------------------------------------------------------------------------
  103. #  イベントページのデータクラス。
  104. #==============================================================================
  105. class RPG::Event::Page
  106.   #--------------------------------------------------------------------------
  107.   # ● 取得する注釈内容を変更 [新規]
  108.   #--------------------------------------------------------------------------
  109.   attr_writer   :event_note
  110.   #--------------------------------------------------------------------------
  111.   # ● この頁の注釈を取得 [新規]
  112.   #--------------------------------------------------------------------------
  113.   def event_note
  114.     return @event_note ||= Calt::Read_EventNote(@list)
  115.   end
  116. end


経路探索VXAce (VX Ace用)
RUBY 代码复制
  1. #==============================================================================
  2. # ■ 経路探索VXAce (VX Ace用)
  3. #------------------------------------------------------------------------------
  4. # 製作者     : CanariAlternate
  5. # サイト名   : カルトの鳥篭
  6. # サイトURL  : [url]http://canarialt.blog.fc2.com[/url]
  7. #------------------------------------------------------------------------------
  8. # ■ 概要 : 指定した座標(またはキャラクター)まで経路探索をしながら移動する。
  9. #           この経路探索では一定時間動いていないイベントは障害物として認識する。
  10. #
  11. # ■ 必須 : 「注釈取得スクリプト」
  12. #
  13. # ■ 位置 : 「注釈取得スクリプト」より下
  14. #           「マルチレイヤーシステム」より下
  15. #------------------------------------------------------------------------------
  16. # ■ 機能 : 1. 指定した座標(またはキャラクター)まで移動する。
  17. #
  18. #           2. 経路探索の移動で進入禁止の領域をリージョンIDで指定する。
  19. #
  20. #           3. 注釈にキーワードを記述すると経路探索において障害物と見なさない。
  21. #
  22. # ■ スクリプト(移動ルートの設定) :
  23. #           1. route_search(引数)
  24. #              目標に到達するまで移動を繰り返す。
  25. #              移動ルートの設定の「移動できない場合は飛ばす」は route_search には無効である。
  26. #              引数はハッシュで設定する。省略するとあらかじめ設定されている初期値が採用される。
  27. #              a. 目標の設定(※初期値はプレイヤー)
  28. #                 :x => x座標
  29. #                 :y => y座標
  30. #                 :z => z座標(通常は使用しないので省略可能)
  31. #                 :char_id => イベントID
  32. #                 :character => オブジェクト($game_playerなど)
  33. #
  34. #                 指定する方法は以下の3通りである。
  35. #                 :x, :y, :z は座標で指定する。:x と :y の両方設定しないと無効になる。
  36. #                 :char_id はイベントのIDで指定する。プレイヤーを指定したい場合は -1 である。
  37. #                 :character はオブジェクトを直接指定する。
  38. #                 例1 route_search(:x => 5, :y => 7)             座標(5, 7)が目標
  39. #                 例2 route_search(:char_id => 5)                イベントIDが5番のイベントが目標
  40. #                 例3 route_search(:character => $game_player)   プレイヤーが目標
  41. #
  42. #              b. 斜め移動の使用(※初期値はfalse)
  43. #                 :diagonal => true / false
  44. #                 true  は斜め移動を使用する。
  45. #                 false は斜め移動を使用しない。
  46. #
  47. #              c. 探索失敗時の行動(※初期値はtrue)
  48. #                 :fail => true / false
  49. #                 true  は失敗時はランダムに移動する。
  50. #                 false は失敗時はウェイトする。
  51. #
  52. #              d. 経路探索を実行する目標との距離(※初期値は25)
  53. #                 :length => 数値
  54. #                 設定した数値より目標が遠い場合はウェイトする。
  55. #
  56. #              e. ウェイトの時間(※初期値は6)
  57. #                 :wait => フレーム数
  58. #                 false を設定するとウェイトせずに経路探索を中止する。
  59. #
  60. #              f. 目標の何歩前まで移動するか(※初期値は0)
  61. #                 :near => 数値
  62. #                 例えば、1 の場合は目標の1歩手前で探索終了する。
  63. #                 0 であれば目標と重なるまで探索を終了しない。
  64. #
  65. #              g. 探索回数の上限(※初期値はfalse)
  66. #                 :give_up => 数値
  67. #                 false を設定すると自動モードになる。
  68. #                 大きな数値(およそ100以上)を設定すると遠くまで探索するがPCへの負荷も大きくなる。
  69. #
  70. #              h. 1回移動したら次の命令を実行(※初期値はfalse)
  71. #                 :manual => true / false
  72. #                 true  は1回移動すると次の命令を実行します。
  73. #                 false は目標への移動が完了するまで移動を続けます。
  74. #
  75. #              i. 進入禁止のリージョンIDを設定(※初期値はこの下で設定)
  76. #                 :region => [5, 6, 7]
  77. #                 リージョンIDは配列で設定する必要がある。
  78. #
  79. #              これらの引数は全て省略可能で route_search と記述するだけでもプレイヤーを追尾する。
  80. #------------------------------------------------------------------------------
  81. # 更新履歴 : 2013/01/05 Ver2.05 スクリプトを大幅に変更した。スクリプト名を変更した。
  82. #            2013/01/09 Ver3.05 内部処理を大幅に変更した。
  83. #            2013/02/19 Ver3.06 共通処理スクリプトの廃止による変更を施した。
  84. #            2013/06/28 Ver3.07 失敗時のランダム移動のバグを修正した。
  85. #            2013/06/28 Ver3.08 斜め移動では[経路探索で無視]を無効にするように変更した。
  86. #            2013/06/29 Ver3.09 ある条件を満たすと経路情報を捨てる機能を廃止した。
  87. #            2013/06/29 Ver3.10 1回移動したら次の命令を実行するオプションを追加した。
  88. #            2013/06/29 Ver3.11 ループしたマップで正常に移動しないバグを修正した。
  89. #            2013/08/18 Ver3.12 進入禁止のリージョンIDを個別に設定できる機能を追加した。
  90. #==============================================================================
  91.  
  92. $imported ||= {}
  93. $imported[:CanariAlternate_RouteSearch] = true
  94.  
  95. #==============================================================================
  96. # ■ Calt
  97. #------------------------------------------------------------------------------
  98. #  CanariAlternateが製作したスクリプト用のモジュールです。
  99. #==============================================================================
  100. module Calt
  101.   #-----------------------------------------------------------------------------
  102.   # ◆経路探索で進入禁止にするリージョンIDの配列(引数を省略した際に適用される設定)
  103.   NOT_ENTER_REGION_ID = [4]
  104.   #
  105.   # ◆イベントを障害物として扱わないことを設定するキーワード
  106.   SCAN_THROUGH_EVENT_NOTE = /\[経路探索で無視\]/ # 記述した頁に適用
  107.   SCAN_THROUGH_WHOLE_NOTE = /\<経路探索で無視\>/ # 全ての頁に適用(1頁目に記述)
  108.   #-----------------------------------------------------------------------------
  109. end
  110.  
  111. #==============================================================================
  112. # ■ 探索処理 ■
  113. #==============================================================================
  114. #==============================================================================
  115. # ■ Game_Character
  116. #------------------------------------------------------------------------------
  117. #  主に移動ルートなどの処理を追加したキャラクターのクラスです。Game_Player、
  118. # Game_Follower、GameVehicle、Game_Event のスーパークラスとして使用されます。
  119. #==============================================================================
  120. class Game_Character < Game_CharacterBase
  121.   #--------------------------------------------------------------------------
  122.   # ● 定数
  123.   #--------------------------------------------------------------------------
  124.   LongSearchRate = 0.1                    # 探索回数の自動設定で長距離探索する確率
  125.   #--------------------------------------------------------------------------
  126.   # ● クラス変数
  127.   #--------------------------------------------------------------------------
  128.   @@route_search_frame = 0                # 経路探索を実行したフレームを記憶
  129.   @@give_up_rate       = LongSearchRate   # 長距離探索を実行する確率
  130.   #--------------------------------------------------------------------------
  131.   # ● 経路探索で移動 [新規]
  132.   #--------------------------------------------------------------------------
  133.   def route_search(argument={})
  134.     # パラメータの取得
  135.     gx, gy, gz = get_goal_coordinate(argument)                          # 目的地(対象)の座標を取得
  136.     diagonal = argument[:diagonal] != nil ? argument[:diagonal] : false # 斜め移動の使用の有無
  137.     length   = argument[:length]   != nil ? argument[:length]   : 25    # 探索を実行する対象との距離
  138.     wait     = argument[:wait]     != nil ? argument[:wait]     : 6     # ウェイト時間(false は待機せず探索中止)
  139.     near     = argument[:near]     != nil ? argument[:near]     : 0     # 対象の何歩手前で停止するか
  140.     fail     = argument[:fail]     != nil ? argument[:fail]     : true  # 探索失敗時に適当な移動を行うか
  141.     give_up  = argument[:give_up]  != nil ? argument[:give_up]  : false # 探索回数の上限(false は自動)
  142.     manual   = argument[:manual]   != nil ? argument[:manual]   : false # 1回移動したら次の命令を実行
  143.     region   = argument[:region]   != nil ? argument[:region]   : Calt::NOT_ENTER_REGION_ID # 進入禁止のリージョンIDの配列
  144.  
  145.     # 経路探索の設定
  146.     @routing_object ||= Route_Search.new(self)                          # 経路探索のクラスのオブジェクトを生成
  147.     @routing_object.not_enter_region_id     = region                    # 進入禁止のリージョンIDの配列を設定
  148.     @routing_object.limit_search_count      = get_give_up(give_up)      # 探索回数の上限を設定
  149.     @routing_object.always_collide_through  = false                     # 常に衝突判定無視を無効に設定
  150.     @routing_object.ending_collide_distance = near != 0 ? near - 1 : 0  # 終点付近で衝突判定無視の距離を設定
  151.     @routing_object.ending_through_distance = near - 1                  # 終点付近で通行判定無視の距離を設定
  152.     @routing_object.diagonal                = diagonal                  # 斜め移動の使用の有無を設定
  153.     @routing_object.active_collide_through  = 60                        # 指定フレーム以内に移動してるキャラクターは衝突判定無視を設定
  154.  
  155.     # 探索実行範囲内か判定
  156.     distance = @routing_object.distance_xy(@x, @y, gx, gy)              # 終点までの最短距離を取得
  157.     return wait_search(wait, manual) if distance > length               # 探索範囲外の場合はウェイト
  158.  
  159.     # 探索成功範囲内か判定
  160.     if distance <= near && !(gx == @x && gy == @y && gz != z)           # 探索成功の場合
  161.       return end_route_search                                           # 経路探索終了の手続きを実行
  162.     end
  163.  
  164.     last_x, last_y, last_z = @x, @y, z                                  # 現在の座標を記憶
  165.     last_route_list = @route_list                                       # 現在の経路情報を記憶
  166.  
  167.     # 通常の経路探索
  168.     @route_list = @routing_object.a_star_search(gx, gy, gz)             # 経路情報の取得
  169.     if !@route_list || @route_list.empty?                               # 経路情報を取得できなかった場合
  170.       @route_list = nil                                                 # 経路情報を消去
  171.       return wait_search(wait, manual) unless fail                      # 失敗時にランダム移動しない場合はウェイト
  172.       fail_move_random(diagonal, region)                                # 失敗した場合の移動
  173.       set_move_succeed(wait, last_x, last_y, last_z)                    # 移動成功を判定
  174.       continue_route_search unless manual                               # 経路探索継続の手続きを実行
  175.       return
  176.     end
  177.     if @route_list[0] == [gx, gy, gz]                                   # 終点までの経路情報の取得に成功した場合
  178.       route_list_to_move(@route_list)                                   # 経路に従って移動
  179.       set_move_succeed(wait, last_x, last_y, last_z)                    # 移動成功を判定
  180.       continue_route_search unless manual                               # 経路探索継続の手続きを実行
  181.       return
  182.     end
  183.  
  184.     # 以前の経路情報を使用して経路探索
  185.     new_route_list = @route_list                                        # 最新の推定経路情報を記憶
  186.     @routing_object.limit_search_count = get_give_up(give_up)           # 探索回数の上限を設定
  187.     @route_list = @routing_object.reuse_route_list(last_route_list, 5, gx, gy, gz)  # 以前の経路情報を使って探索
  188.     if !@route_list || @route_list.empty?                               # 経路情報を取得できなかった場合
  189.       @route_list = nil                                                 # 経路情報を消去
  190.       return wait_search(wait, manual) unless fail                      # 失敗時に移動しない場合はウェイト
  191.       @route_list = new_route_list                                      # 最新の推定経路情報を復帰
  192.       route_list_to_move(@route_list)                                   # 経路に従って移動
  193.       set_move_succeed(wait, last_x, last_y, last_z)                    # 移動成功を判定
  194.       continue_route_search unless manual                               # 経路探索継続の手続きを実行
  195.       return
  196.     end
  197.     if @route_list[0] == [gx, gy, gz]                                   # 終点までの経路情報の取得に成功した場合
  198.       route_list_to_move(@route_list)                                   # 経路に従って移動
  199.       set_move_succeed(wait, last_x, last_y, last_z)                    # 移動成功を判定
  200.       continue_route_search unless manual                               # 経路探索継続の手続きを実行
  201.       return
  202.     end
  203.     unless fail                                                         # 失敗時に移動しない場合
  204.       @route_list = nil                                                 # 経路情報を消去
  205.       wait_search(wait, manual)                                         # ウェイト
  206.       return
  207.     end
  208.     old_x = @route_list[0][0]
  209.     old_y = @route_list[0][1]
  210.     old_distance = @routing_object.distance_xy(old_x, old_y, gx, gy)    # 更新推定経路の終点までの最短距離を取得
  211.     new_x = new_route_list[0][0]
  212.     new_y = new_route_list[0][1]
  213.     new_distance = @routing_object.distance_xy(new_x, new_y, gx, gy)    # 最新推定経路の終点までの最短距離を取得
  214.     @route_list = new_route_list if old_distance >= new_distance        # 最新推定経路の方が優れている場合は経路情報を復帰
  215.     route_list_to_move(@route_list)                                     # 経路に従って移動
  216.     set_move_succeed(wait, last_x, last_y, last_z)                      # 移動成功を判定
  217.     continue_route_search unless manual                                 # 経路探索継続の手続きを実行
  218.     return
  219.   end
  220.   #--------------------------------------------------------------------------
  221.   # ● 対象の座標を取得 [新規]
  222.   #--------------------------------------------------------------------------
  223.   def get_goal_coordinate(argument)
  224.     if argument[:x] && argument[:y]           # 座標で直接指定の場合
  225.       return [argument[:x], argument[:y], argument[:z] || 0]
  226.     end
  227.     character = argument[:char]               # キャラクターのオブジェクトを直接指定
  228.     if !character && id = argument[:char_id]  # キャラクターのIDで指定の場合
  229.       character = case id
  230.       when 0 ; self                           # id : 0  はこのキャラクター自体
  231.       when -1; $game_player                   # id : -1 はプレイヤー
  232.       else   ; $game_map.events[id] || self   # それ以外はイベント
  233.       end
  234.     else
  235.       character = $game_player                # 指定が無い場合はプレイヤー
  236.     end
  237.     return [character.x, character.y, character.z]
  238.   end
  239.   #--------------------------------------------------------------------------
  240.   # ● 経路探索を待機 [新規]
  241.   #--------------------------------------------------------------------------
  242.   def wait_search(wait, manual)
  243.     if wait
  244.       @wait_count = wait      # ウェイトを設定
  245.       manual ? end_route_search : continue_route_search
  246.     else
  247.       @wait_count = 0         # ウェイトはなし
  248.       end_route_search
  249.     end
  250.   end
  251.   #--------------------------------------------------------------------------
  252.   # ● 経路探索による移動を終了の手続き [新規]
  253.   #--------------------------------------------------------------------------
  254.   def end_route_search
  255.     @move_succeed = true
  256.   end
  257.   #--------------------------------------------------------------------------
  258.   # ● 経路探索による移動を継続の手続き [新規]
  259.   #--------------------------------------------------------------------------
  260.   def continue_route_search
  261.     @move_succeed = true
  262.     @move_route_index -= 1  # もう1度実行されるように実行位置を1つ戻す
  263.   end
  264.   #--------------------------------------------------------------------------
  265.   # ● 経路リストに従って移動 [新規]
  266.   #--------------------------------------------------------------------------
  267.   def route_list_to_move(route_list)
  268.     dx = distance_x_from(route_list[-1][0])
  269.     dy = distance_y_from(route_list[-1][1])
  270.     if dx == 0
  271.       dy == 0 ? nil              : (dy < 0 ? move_straight(2)    : move_straight(8)   )
  272.     elsif dx < 0
  273.       dy == 0 ? move_straight(6) : (dy < 0 ? move_diagonal(6, 2) : move_diagonal(6, 8))
  274.     else
  275.       dy == 0 ? move_straight(4) : (dy < 0 ? move_diagonal(4, 2) : move_diagonal(4, 8))
  276.     end
  277.   end
  278.   #--------------------------------------------------------------------------
  279.   # ● 移動成功を判定 [新規]
  280.   #--------------------------------------------------------------------------
  281.   def set_move_succeed(wait, last_x, last_y, last_z)
  282.     if last_x != @x || last_y != @y || last_z != z
  283.       @move_succeed = true                                      # 移動成功
  284.     else
  285.       @move_succeed = false                                     # 移動失敗
  286.       @wait_count = (wait || 6)                                 # 過負荷を回避する為にウェイト
  287.       @route_list.push [@x, @y, z] if @route_list               # 経路情報を修正
  288.     end
  289.   end
  290.   #--------------------------------------------------------------------------
  291.   # ● 負荷を考慮した探索回数の上限値を取得 [新規]
  292.   #--------------------------------------------------------------------------
  293.   def get_give_up(give_up)
  294.     return give_up if give_up
  295.     if @@route_search_frame != Graphics.frame_count
  296.       @@give_up_rate = LongSearchRate                           # 確率を初期化
  297.       @@route_search_frame = Graphics.frame_count               # フレームの記憶を更新
  298.     end
  299.     if rand(10000) < 10000 * @@give_up_rate
  300.       @@give_up_rate = 0                                        # 確率を更新
  301.       result = 10 + rand(140)                                   # 高い上限を設定
  302.     else
  303.       @@give_up_rate *= @@give_up_rate / (1.0 - @@give_up_rate) # 確率を更新
  304.       result = 10                                               # 低い上限を設定
  305.     end
  306.     return result
  307.   end
  308.   #--------------------------------------------------------------------------
  309.   # ● 失敗した場合の移動 [新規]
  310.   #--------------------------------------------------------------------------
  311.   def fail_move_random(diagonal, region)
  312.     # 斜め移動の場合
  313.     if diagonal && rand(2) == 0
  314.       horz = rand(2) == 0 ? 4 : 6
  315.       vert = rand(2) == 0 ? 2 : 8
  316.       nx = $game_map.round_x_with_direction(@x, horz)
  317.       ny = $game_map.round_y_with_direction(@y, vert)
  318.       return if region.include?($game_map.region_id(nx, ny))
  319.       move_diagonal(horz, vert)
  320.       return
  321.     end
  322.     # 4方向移動の場合
  323.     if rand(2) == 0
  324.       horz = rand(2) == 0 ? 4 : 6
  325.       nx = $game_map.round_x_with_direction(@x, horz)
  326.       return if region.include?($game_map.region_id(nx, @y))
  327.       move_straight(horz)
  328.     else
  329.       vert = rand(2) == 0 ? 2 : 8
  330.       ny = $game_map.round_y_with_direction(@y, vert)
  331.       return if region.include?($game_map.region_id(@x, ny))
  332.       move_straight(vert)
  333.     end
  334.   end
  335. end
  336.  
  337. #==============================================================================
  338. # ■ 基礎定義 ■
  339. #==============================================================================
  340. #==============================================================================
  341. # ■ Game_CharacterBase
  342. #------------------------------------------------------------------------------
  343. #  キャラクターを扱う基本のクラスです。全てのキャラクターに共通する、座標やグ
  344. # ラフィックなどの基本的な情報を保持します。
  345. #==============================================================================
  346. class Game_CharacterBase
  347.   #--------------------------------------------------------------------------
  348.   # ● クラス変数
  349.   #--------------------------------------------------------------------------
  350.   @@active_collide_through = false        # 座標一致判定の無効化
  351.   @@collide_through        = false        # 衝突判定無視
  352.   @@search_diagonal        = false        # 斜めの移動判定か否か
  353.   def active_collide_through=(arg) ; @@active_collide_through = arg ; end
  354.   def collide_through=(arg)        ; @@collide_through        = arg ; end
  355.   def search_diagonal=(arg)        ; @@search_diagonal        = arg ; end
  356.   #--------------------------------------------------------------------------
  357.   # ● 公開インスタンス変数
  358.   #--------------------------------------------------------------------------
  359.   attr_reader   :stopwatch                # 連続停止時間
  360.   #--------------------------------------------------------------------------
  361.   # ● z 座標の取得 [新規]
  362.   #--------------------------------------------------------------------------
  363.   def z
  364.     return 0                              # 座標が3次元の場合は再定義する
  365.   end
  366.   #--------------------------------------------------------------------------
  367.   # ● 公開メンバ変数の初期化 [追加]
  368.   #--------------------------------------------------------------------------
  369.   alias init_public_members_RouteSearch init_public_members
  370.   def init_public_members
  371.     init_public_members_RouteSearch
  372.     @stopwatch = 1.0/0                    # 1.0/0 #=> Infinity
  373.     @movement_record = [[nil, nil, nil]]  # 移動履歴
  374.   end
  375.   #--------------------------------------------------------------------------
  376.   # ● 非公開メンバ変数の初期化 [追加]
  377.   #--------------------------------------------------------------------------
  378.   alias init_private_members_RouteSearch init_private_members
  379.   def init_private_members
  380.     init_private_members_RouteSearch
  381.     @scan_through_event = false           # 経路探索において障害物として扱わないフラグ
  382.   end
  383.   #--------------------------------------------------------------------------
  384.   # ● フレーム更新 [追加]
  385.   #--------------------------------------------------------------------------
  386.   alias update_RouteSearch update
  387.   def update
  388.     update_RouteSearch
  389.     update_stopwatch                      # 連続停止時間を更新
  390.   end
  391.   #--------------------------------------------------------------------------
  392.   # ● 連続停止時間を更新 [新規]
  393.   #--------------------------------------------------------------------------
  394.   def update_stopwatch
  395.     if @movement_record[-1] != [x, y, z]
  396.       @stopwatch = 0 if @movement_record.size > 1
  397.       @movement_record.push [x, y, z]
  398.       @movement_record.shift if @movement_record.size > 10
  399.     elsif !moving?
  400.       @stopwatch += 1
  401.     end
  402.   end
  403.   #--------------------------------------------------------------------------
  404.   # ● 座標一致判定 [追加]
  405.   #--------------------------------------------------------------------------
  406.   alias pos_RouteSearch? pos?
  407.   def pos?(*args)
  408.     return false if @@collide_through and !tile? || @scan_through_event && !@@search_diagonal
  409.     # 連続停止時間が指定値以下の場合は座標を不一致にすることで衝突判定を回避する。
  410.     return false if @@active_collide_through and @stopwatch <= @@active_collide_through && !tile? || @scan_through_event && !@@search_diagonal
  411.     pos_RouteSearch?(*args)
  412.   end
  413. end
  414. #==============================================================================
  415. # ■ Game_Event
  416. #------------------------------------------------------------------------------
  417. #  イベントを扱うクラスです。条件判定によるイベントページ切り替えや、並列処理
  418. # イベント実行などの機能を持っており、Game_Map クラスの内部で使用されます。
  419. #==============================================================================
  420. class Game_Event < Game_Character
  421.   #--------------------------------------------------------------------------
  422.   # ● 衝突判定無視の設定を取得 [新規]
  423.   #--------------------------------------------------------------------------
  424.   def get_scan_through_event_note
  425.     event_result = event_note_include?(Calt::SCAN_THROUGH_EVENT_NOTE)
  426.     whole_result = whole_note_include?(Calt::SCAN_THROUGH_WHOLE_NOTE)
  427.     return event_result ^ whole_result
  428.   end
  429.   #--------------------------------------------------------------------------
  430.   # ● イベントページ更新時に注釈から設定を取得 [追加]
  431.   #--------------------------------------------------------------------------
  432.   alias setup_note_settings_RouteSearch setup_note_settings
  433.   def setup_note_settings
  434.     setup_note_settings_RouteSearch
  435.     @scan_through_event = get_scan_through_event_note
  436.   end
  437. end
  438. #==============================================================================
  439. # ■ Route_Search
  440. #------------------------------------------------------------------------------
  441. #  経路探索の処理を定義したクラスです。
  442. #==============================================================================
  443. class Route_Search
  444.   #--------------------------------------------------------------------------
  445.   # ● 基礎変数の初期化
  446.   #--------------------------------------------------------------------------
  447.   def init_base_instance(character)
  448.     @character = character                # キャラクターへの参照
  449.     @x , @y , @z  = 0, 0, 0               # 今のノードの座標
  450.     @sx, @sy, @sz = 0, 0, 0               # 始点の座標
  451.     @gx, @gy, @gz = 0, 0, 0               # 終点の座標
  452.     @diagonal = false                     # 斜め移動の使用の有無
  453.     @collide_through = false              # 衝突判定を無視するフラグ
  454.     @active_collide_through = 60          # 指定フレーム以内に移動してるキャラクターは衝突判定無視
  455.   end
  456.   #--------------------------------------------------------------------------
  457.   # ● 2点間の x 方向の距離
  458.   #--------------------------------------------------------------------------
  459.   def distance_x(start_x, end_x)
  460.     result = end_x - start_x
  461.     return result unless $game_map.loop_horizontal? && result.abs > $game_map.width / 2
  462.     return result + (result < 0 ? $game_map.width : -$game_map.width)
  463.   end
  464.   #--------------------------------------------------------------------------
  465.   # ● 2点間の y 方向の距離
  466.   #--------------------------------------------------------------------------
  467.   def distance_y(start_y, end_y)
  468.     result = end_y - start_y
  469.     return result unless $game_map.loop_vertical? && result.abs > $game_map.height / 2
  470.     return result + (result < 0 ? $game_map.height : -$game_map.height)
  471.   end
  472.   #--------------------------------------------------------------------------
  473.   # ● 2点間の z 方向の距離
  474.   #--------------------------------------------------------------------------
  475.   def distance_z(start_z, end_z)
  476.     return end_z - start_z
  477.   end
  478.   #--------------------------------------------------------------------------
  479.   # ● 2点の距離を取得
  480.   #--------------------------------------------------------------------------
  481.   def distance_xy(start_x, start_y, end_x, end_y)
  482.     if @diagonal
  483.       return [distance_x(start_x, end_x).abs, distance_y(start_y, end_y).abs].max # 8方向の場合
  484.     else
  485.       return distance_x(start_x, end_x).abs + distance_y(start_y, end_y).abs      # 4方向の場合
  486.     end
  487.   end
  488.   #--------------------------------------------------------------------------
  489.   # ● x 座標の取得
  490.   #--------------------------------------------------------------------------
  491.   def character_x
  492.     return @character.x
  493.   end
  494.   #--------------------------------------------------------------------------
  495.   # ● y 座標の取得
  496.   #--------------------------------------------------------------------------
  497.   def character_y
  498.     return @character.y
  499.   end
  500.   #--------------------------------------------------------------------------
  501.   # ● z 座標の取得
  502.   #--------------------------------------------------------------------------
  503.   def character_z
  504.     return @character.z
  505.   end
  506.   #--------------------------------------------------------------------------
  507.   # ● z 座標の変換
  508.   #--------------------------------------------------------------------------
  509.   def xyz_to_z(x, y, z)
  510.     return z
  511.   end
  512.   #--------------------------------------------------------------------------
  513.   # ● 進入禁止のリージョンIDの座標か判定
  514.   #--------------------------------------------------------------------------
  515.   def not_enter_coordinate?(x, y, z)
  516.     return not_enter_region_id.include?($game_map.region_id(x, y))
  517.   end
  518.   #--------------------------------------------------------------------------
  519.   # ● 終点か判定
  520.   #--------------------------------------------------------------------------
  521.   def end_coordinate?(x, y, z)
  522.     return x == @gx && y == @gy && z == @gz
  523.   end
  524.   #--------------------------------------------------------------------------
  525.   # ● 終点から範囲内か判定
  526.   #--------------------------------------------------------------------------
  527.   def ending_distance?(x, y, z, distance)
  528.     return false if x == @gx && y == @gy && z != @gz
  529.     return false if distance_xy(x, y, @gx, @gy) > distance
  530.     return true
  531.   end
  532.   # #--------------------------------------------------------------------------
  533.   # # ● 始点から範囲内か判定
  534.   # #--------------------------------------------------------------------------
  535.   # def starting_distance?(x, y, z, distance)
  536.   #   return false if x == @sx && y == @sy && z != @sz
  537.   #   return false if distance_xy(x, y, @sx, @sy) > distance
  538.   #   return true
  539.   # end
  540.   # #--------------------------------------------------------------------------
  541.   # # ● 始点の隣接座標か判定(始点を含む)
  542.   # #--------------------------------------------------------------------------
  543.   # def adjoin_coordinate?(x, y, z)
  544.   #   return false unless starting_distance?(x, y, z, 1)
  545.   #   return xyz_to_z(x, y, @sz) == z
  546.   # end
  547.   #--------------------------------------------------------------------------
  548.   # ● 通行可能判定
  549.   #--------------------------------------------------------------------------
  550.   def passable?(d)
  551.     @character.active_collide_through = @active_collide_through
  552.     @character.collide_through = @collide_through
  553.     @character.search_diagonal = false
  554.     result = base_passable?(:passable?, d)
  555.     @character.collide_through = false
  556.     @character.active_collide_through = false
  557.     return result
  558.   end
  559.   #--------------------------------------------------------------------------
  560.   # ● 斜めの通行可能判定
  561.   #--------------------------------------------------------------------------
  562.   def diagonal_passable?(horz, vert)
  563.     @character.active_collide_through = @active_collide_through
  564.     @character.collide_through = @collide_through
  565.     @character.search_diagonal = true
  566.     result = base_passable?(:diagonal_passable?, horz, vert)
  567.     @character.collide_through = false
  568.     @character.active_collide_through = false
  569.     return result
  570.   end
  571.   #--------------------------------------------------------------------------
  572.   # ● 通行可能判定の呼び出し
  573.   #--------------------------------------------------------------------------
  574.   def base_passable?(name, *d)
  575.     return @character.send(name, @x, @y, *d)
  576.   end
  577. end
  578.  
  579. #==============================================================================
  580. # ■ 内部処理 ■
  581. #==============================================================================
  582. #==============================================================================
  583. # ■ Route_Search
  584. #------------------------------------------------------------------------------
  585. #  経路探索の処理を定義したクラスです。
  586. #==============================================================================
  587. class Route_Search
  588.   #--------------------------------------------------------------------------
  589.   # ● 座標の配列のインデックス
  590.   #--------------------------------------------------------------------------
  591.   X = 0                                   # x座標
  592.   Y = 1                                   # y座標
  593.   Z = 2                                   # z座標
  594.   #--------------------------------------------------------------------------
  595.   # ● ノードの配列のインデックス
  596.   #--------------------------------------------------------------------------
  597.   RANK_A = 0                              # 評価値A
  598.   RANK_B = 1                              # 評価値B
  599.   RANK_C = 2                              # 評価値C
  600.   PARENT = 3                              # 親の座標
  601.   LENGTH = 4                              # 移動距離
  602.   #--------------------------------------------------------------------------
  603.   # ● 公開インスタンス変数
  604.   #--------------------------------------------------------------------------
  605.   attr_accessor :not_enter_region_id      # 進入禁止のリージョンIDの配列
  606.   attr_accessor :limit_search_count       # 探索回数の上限値
  607.   attr_accessor :always_collide_through   # 常に衝突判定を無視のフラグ
  608.   attr_accessor :ending_collide_distance  # 終点付近で衝突判定を無視の距離
  609.   attr_accessor :ending_through_distance  # 終点付近で通行判定を無視の距離
  610.   attr_accessor :diagonal                 # 斜め移動の使用の有無
  611.   attr_accessor :active_collide_through   # 指定フレーム以内に移動してるキャラクターは衝突判定無視
  612.   #--------------------------------------------------------------------------
  613.   # ● オブジェクト初期化
  614.   #--------------------------------------------------------------------------
  615.   def initialize(character)
  616.     init_base_instance(character)
  617.     @parent = [nil, nil, nil]             # 親の座標
  618.     @past_distance = 0                    # 探索点までの移動距離
  619.     @open_list = {}                       # 探索候補のノードのリスト
  620.     @close_list = {}                      # 探索済みのノードのリスト
  621.     @limit_search_count = 100
  622.     @always_collide_through = false
  623.     @ending_collide_distance = 0
  624.     @ending_through_distance = 0
  625.   end
  626.   #--------------------------------------------------------------------------
  627.   # ● A*経路探索の通常実行
  628.   #--------------------------------------------------------------------------
  629.   def a_star_search(gx, gy, gz=0)
  630.     init_process(gx, gy, gz)              # A*経路探索の初期化
  631.     return main_process                   # A*経路探索の主要処理
  632.   end
  633.   #--------------------------------------------------------------------------
  634.   # ● A*経路探索の初期化
  635.   #--------------------------------------------------------------------------
  636.   def init_process(gx, gy, gz)
  637.     @x, @y, @z = character_x, character_y, character_z # 現在の座標
  638.     @sx, @sy, @sz = @x, @y, @z            # 始点の座標
  639.     @gx, @gy, @gz = gx, gy, gz            # 終点の座標
  640.     @open_list  = {[@sx, @sy, @sz]=>create_node(@sx, @sy, @sz, [nil, nil, nil], 0)}
  641.     @close_list = {}
  642.   end
  643.   #--------------------------------------------------------------------------
  644.   # ● A*経路探索の主要処理
  645.   #--------------------------------------------------------------------------
  646.   def main_process
  647.     count = 0
  648.     until @open_list.empty?
  649.       node, coordinate = get_best_node(@open_list)  # 最も高評価のノードを探索候補のリストから取得
  650.  
  651.       # 探索成功の場合
  652.       return create_route_list(node, coordinate) if end_coordinate?(*coordinate)
  653.  
  654.       # 探索回数の上限オーバーの場合
  655.       return create_estimate_list if (count += 1) > @limit_search_count
  656.  
  657.       # 隣接点を探索候補に追加する処理
  658.       @close_list[coordinate] = @open_list.delete(coordinate) # 探索候補から探索済みに移動
  659.       @x, @y, @z     = *coordinate
  660.       @parent        = node[PARENT]
  661.       @past_distance = node[LENGTH] + 1
  662.       down  = $game_map.round_y(@y + 1)
  663.       up    = $game_map.round_y(@y - 1)
  664.       right = $game_map.round_x(@x + 1)
  665.       left  = $game_map.round_x(@x - 1)
  666.       open_list_add(@x, down , 2) # 下
  667.       open_list_add(@x, up   , 8) # 上
  668.       open_list_add(right, @y, 6) # 右
  669.       open_list_add(left , @y, 4) # 左
  670.       if @diagonal
  671.         open_list_add_diagonal(right, down, 6, 2) # 右下
  672.         open_list_add_diagonal(left , down, 4, 2) # 左下
  673.         open_list_add_diagonal(right, up  , 6, 8) # 右上
  674.         open_list_add_diagonal(left , up  , 4, 8) # 左上
  675.       end
  676.     end
  677.     return false  # 到達する経路は存在しない。
  678.   end
  679.   #--------------------------------------------------------------------------
  680.   # ● ノードのデータを生成
  681.   #--------------------------------------------------------------------------
  682.   def create_node(x, y, z, parent, length)
  683.     dx = distance_x(x, @gx).abs
  684.     dy = distance_y(y, @gy).abs
  685.     rank_a = length + dx + dy
  686.     rank_b = Math.sqrt(dx ** 2 + dy ** 2)
  687.     rank_c = distance_z(z, @gz).abs
  688.     return [rank_a, rank_b, rank_c, parent, length]
  689.     # [評価値A, 評価値B, 評価値C, 親の座標, 移動距離]
  690.     # 評価値A : 始点から終点までの推定最短経路の距離
  691.     # 評価値B : 終点との直線距離
  692.     # 評価値C : z 座標の距離
  693.     # 親の座標 : 移動元の座標
  694.     # 移動距離 : 始点からこの点までの移動距離
  695.   end
  696.   #--------------------------------------------------------------------------
  697.   # ● 最も高評価のノードを取得
  698.   #--------------------------------------------------------------------------
  699.   def get_best_node(hash_list, compare=:node_a_better?)
  700.     best_node = [1.0/0, 1.0/0, 1.0/0] # 1.0/0 #=> Infinity
  701.     best_coordinate = nil
  702.     hash_list.each do |coordinate, node|
  703.       next if send(compare, best_node, node)  # node よりも best_node が高評価なら next
  704.       best_node = node
  705.       best_coordinate = coordinate
  706.     end
  707.     return best_node, best_coordinate
  708.   end
  709.   #--------------------------------------------------------------------------
  710.   # ● ノードの優劣判定
  711.   #--------------------------------------------------------------------------
  712.   def node_a_better?(node_a, node_b)
  713.     return true  if node_a[RANK_A] < node_b[RANK_A]
  714.     return false if node_a[RANK_A] > node_b[RANK_A]
  715.     return true  if node_a[RANK_B] < node_b[RANK_B]
  716.     return false if node_a[RANK_B] > node_b[RANK_B]
  717.     return true  if node_a[RANK_C] < node_b[RANK_C]
  718.     return false if node_a[RANK_C] > node_b[RANK_C]
  719.     return true
  720.   end
  721.   #--------------------------------------------------------------------------
  722.   # ● 探索候補リストに隣接点を追加
  723.   #--------------------------------------------------------------------------
  724.   def open_list_add(nx, ny, d)
  725.     return if @parent[X] == nx && @parent[Y] == ny
  726.     nz = xyz_to_z(nx, ny, @z)                         # z 座標の変換
  727.     result = exception_decision?(nx, ny, nz)
  728.     return if result == false                         # 通行禁止の場合
  729.     if result == nil                                  # 通行可能判定に委ねる場合
  730.       @collide_through = collide_through?(nx, ny, nz)
  731.       return if !passable?(d)                         # 通行可能判定
  732.     end
  733.     open_list_add_node(nx, ny, nz)                    # 探索候補リストに追加
  734.   end
  735.   #--------------------------------------------------------------------------
  736.   # ● 探索候補リストに隣接点を追加(斜めの判定版)
  737.   #--------------------------------------------------------------------------
  738.   def open_list_add_diagonal(nx, ny, horz, vert)
  739.     return if @parent[X] == nx && @parent[Y] == ny
  740.     nz = xyz_to_z(nx, ny, @z)                         # z 座標の変換
  741.     result = exception_decision?(nx, ny, nz)
  742.     return if result == false                         # 通行禁止の場合
  743.     if result == nil                                  # 通行可能判定に委ねる場合
  744.       @collide_through = collide_through?(nx, ny, nz)
  745.       return if !diagonal_passable?(horz, vert)       # 斜めの通行可能判定
  746.     end
  747.     open_list_add_node(nx, ny, nz)                    # 探索候補リストに追加
  748.   end
  749.   #--------------------------------------------------------------------------
  750.   # ● 例外通行判定
  751.   #--------------------------------------------------------------------------
  752.   def exception_decision?(x, y, z)
  753.     return false if not_enter_coordinate?(x, y, z)
  754.     return true if ending_distance?(x, y, z, @ending_through_distance)
  755.     return nil
  756.   end
  757.   #--------------------------------------------------------------------------
  758.   # ● 衝突判定を無視するか判定
  759.   #--------------------------------------------------------------------------
  760.   def collide_through?(x, y, z)
  761.     return true if @always_collide_through
  762.     return true if ending_distance?(x, y, z, @ending_collide_distance)
  763.     return false
  764.   end
  765.   #--------------------------------------------------------------------------
  766.   # ● 探索候補リストに隣接点を追加する処理
  767.   #--------------------------------------------------------------------------
  768.   def open_list_add_node(nx, ny, nz)
  769.     next_coordinate = [nx, ny, nz]
  770.     if old_node = @close_list[next_coordinate]                            # 探索済みリストに既にある場合
  771.       if old_node[LENGTH] > @past_distance                                # 移動距離が優れている場合
  772.         @open_list[next_coordinate] = @close_list.delete(next_coordinate) # 探索候補リストに移動
  773.         update_node(old_node)
  774.       end
  775.       return
  776.     end
  777.     if old_node = @open_list[next_coordinate]                             # 探索候補リストに既にある場合
  778.       update_node(old_node) if old_node[LENGTH] > @past_distance          # 移動距離が優れている場合
  779.       return
  780.     end
  781.     @open_list[next_coordinate] = create_node(*next_coordinate, [@x, @y, @z], @past_distance)
  782.   end
  783.   #--------------------------------------------------------------------------
  784.   # ● ノードのデータを更新
  785.   #--------------------------------------------------------------------------
  786.   def update_node(old_node)
  787.     old_node[RANK_A] += @past_distance - old_node[LENGTH] # 移動距離の差を減算
  788.     old_node[PARENT]  = [@x, @y, @z]                      # 親の座標を更新
  789.     old_node[LENGTH]  = @past_distance                    # 移動距離を更新
  790.   end
  791.   #--------------------------------------------------------------------------
  792.   # ● 経路の配列を生成
  793.   #--------------------------------------------------------------------------
  794.   def create_route_list(node, coordinate)
  795.     parent = node[PARENT]
  796.     route_list = []
  797.     while parent != [nil, nil, nil]
  798.       route_list.push coordinate
  799.       parent = @close_list[coordinate = parent][PARENT]
  800.     end
  801.     return route_list # 先頭が終点で末尾が始点の次の座標(推定経路の場合は先頭は終点ではない)
  802.   end
  803.   #--------------------------------------------------------------------------
  804.   # ● 推定経路の配列を生成
  805.   #--------------------------------------------------------------------------
  806.   def create_estimate_list
  807.     open_node, open_coordinate = get_best_node(@open_list, :estimate_node_a_better?)
  808.     close_node, close_coordinate = get_best_node(@close_list, :estimate_node_a_better?)
  809.     if estimate_node_a_better?(open_node, close_node)
  810.       return create_route_list(open_node, open_coordinate)
  811.     else
  812.       return create_route_list(close_node, close_coordinate)
  813.     end
  814.   end
  815.   #--------------------------------------------------------------------------
  816.   # ● ノードの優劣判定(推定経路用)
  817.   #--------------------------------------------------------------------------
  818.   def estimate_node_a_better?(node_a, node_b)
  819.     return true  if node_a[RANK_B] < node_b[RANK_B]
  820.     return false if node_a[RANK_B] > node_b[RANK_B]
  821.     return true  if node_a[RANK_C] < node_b[RANK_C]
  822.     return false if node_a[RANK_C] > node_b[RANK_C]
  823.     return true
  824.   end
  825.   #--------------------------------------------------------------------------
  826.   # ● 探索結果を再利用
  827.   #--------------------------------------------------------------------------
  828.   def reuse_route_list(route_list, reuse_distance, gx, gy, gz=0)
  829.     return false unless route_list
  830.     @sx, @sy, @sz = character_x, character_y, character_z
  831.     return false unless index = route_list.index([@sx, @sy, @sz]) # 始点を含んでいるか判定
  832.     (route_list.size - index).times { route_list.pop }
  833.     return false if route_list.empty?
  834.     @gx, @gy, @gz = gx, gy, gz
  835.     if index = route_list.index([@gx, @gy, @gz])                  # 終点を含んでいるか判定
  836.       index.times { route_list.shift }
  837.       return false unless route_list_valid?(route_list)           # 経路を使用可能か判定
  838.       return route_list
  839.     else
  840.       return false unless ending_distance?(*route_list[0], reuse_distance)
  841.       return false unless route_list_valid?(route_list)           # 経路を使用可能か判定
  842.       reuse_search(route_list)                                    # 以前の探索結果を使用して経路探索
  843.     end
  844.   end
  845.   #--------------------------------------------------------------------------
  846.   # ● 経路を使用可能か判定
  847.   #--------------------------------------------------------------------------
  848.   def route_list_valid?(route_list)
  849.     @x, @y, @z = @sx, @sy, @sz
  850.     route_list.reverse.each do |coordinate|
  851.       nx, ny, nz = *coordinate
  852.       result = exception_decision?(nx, ny, nz)
  853.       return false if result == false                             # 通行禁止の場合
  854.       if result == nil                                            # 通行可能判定に委ねる場合
  855.         @collide_through = collide_through?(nx, ny, nz)
  856.         if nx == @x
  857.           return false unless ny == @y ? nil          : (ny > @y ? passable?(2)             : passable?(8)            )
  858.         elsif nx > @x
  859.           return false unless ny == @y ? passable?(6) : (ny > @y ? diagonal_passable?(6, 2) : diagonal_passable?(6, 8))
  860.         else
  861.           return false unless ny == @y ? passable?(4) : (ny > @y ? diagonal_passable?(4, 2) : diagonal_passable?(4, 8))
  862.         end
  863.       end
  864.       @x , @y , @z  = nx, ny, nz
  865.     end
  866.     return true
  867.   end
  868.   #--------------------------------------------------------------------------
  869.   # ● 以前の探索結果を使用して経路探索
  870.   #--------------------------------------------------------------------------
  871.   def reuse_search(route_list)
  872.     init_process(@gx, @gy, @gz)
  873.     parent = [@sx, @sy, @sz]
  874.     route_list.reverse.each do |coordinate|
  875.       @open_list[coordinate] = create_node(*coordinate, parent, 0)  # 移動距離に細工をして追加
  876.       parent = coordinate
  877.     end
  878.     @close_list = @open_list.dup
  879.     return main_process
  880.   end
  881. end
  882.  
  883. #==============================================================================
  884. # ■ マルチレイヤーシステムとの競合回避 ■
  885. #==============================================================================
  886. if $imported[:CanariAlternate_Multilayer]
  887.   #==============================================================================
  888.   # ■ Game_CharacterBase
  889.   #------------------------------------------------------------------------------
  890.   #  キャラクターを扱う基本のクラスです。全てのキャラクターに共通する、座標やグ
  891.   # ラフィックなどの基本的な情報を保持します。
  892.   #==============================================================================
  893.   class Game_CharacterBase
  894.     #--------------------------------------------------------------------------
  895.     # ● z 座標の取得 [◆再定義]
  896.     #--------------------------------------------------------------------------
  897.     def z
  898.       return current_floor
  899.     end
  900.   end
  901.   #==============================================================================
  902.   # ■ Route_Search
  903.   #------------------------------------------------------------------------------
  904.   #  経路探索の処理を定義したクラスです。
  905.   #==============================================================================
  906.   class Route_Search
  907.     #--------------------------------------------------------------------------
  908.     # ● 定数
  909.     #--------------------------------------------------------------------------
  910.     DummyEvent = Game_CharacterBase.new     # ダミーのイベント
  911.     #--------------------------------------------------------------------------
  912.     # ● z 座標の変換 [◆再定義]
  913.     #--------------------------------------------------------------------------
  914.     def xyz_to_z(x, y, z)
  915.       return $game_map.floor_xy(x, y, z)
  916.     end
  917.     #--------------------------------------------------------------------------
  918.     # ● 進入禁止のリージョンIDの座標か判定 [◆再定義]
  919.     #--------------------------------------------------------------------------
  920.     def not_enter_coordinate?(x, y, z)
  921.       return not_enter_region_id.include?($game_map.region_id(x, y, z))
  922.     end
  923.     #--------------------------------------------------------------------------
  924.     # ● 通行可能判定の呼び出し [◆再定義]
  925.     #--------------------------------------------------------------------------
  926.     def base_passable?(name, *d)
  927.       DummyEvent.current_floor = @z
  928.       return $game_map.temp_execute(DummyEvent) { @character.send(name, @x, @y, *d) }
  929.     end
  930.   end
  931. end


点评

非常感激! ! 成功用出效果了! !  发表于 2013-10-22 17:09

评分

参与人数 2星屑 +70 收起 理由
3106345123 + 4 精品文章
熊喵酱 + 66 精品文章

查看全部评分

回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-9-25 07:18

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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