=begin ■移動ルート機能ぱわーあっぷ RGSS2 DAIpage■ v0.6 ●機能と使い方●  移動ルートの設定に   ・最短距離移動(障害物も考慮)   ・指定エリア内ランダム移動(マップ機能のエリアを使用)  などを追加します。  また、移動タイプが「ランダム」でトリガーが「決定ボタン」、プライオリティが  「通常キャラと同じ」のイベントがプレイヤーに押されていると、  押された方向に動きます。町中など、狭いところでプレイヤーの通行を邪魔している  場合などに使えます。  移動ルートの設定、または自律移動の「カスタム」内のスクリプトで指定します。 【指定位置に向けて最短移動ルートで一歩移動】  ※ x, yに目標座標を指定。 target_p_move_auto(x, y) 【指定エリア内ランダム移動】お前ここから出てくるなって時に。  ※ idでエリアを指定。 move_type_area_random(id) 【指定キャラクターに近づく】  ※ idに目標キャラクターIDを指定。0でプレイヤー。 target_c_move_auto(id) 【通行可能な限り前進、通行不可でランダムに方向転換】 search_front ●再定義している箇所● Game_Character、Game_Playerをエイリアス。  ※同じ箇所を変更するスクリプトと併用した場合は競合する可能性があります。 ●参考● このスクリプトの一部の機能は以下のサイト様のものを参考にVX用に再構築しております。 RPGツクールシステム研究室 http://suppy1632.hp.infoseek.co.jp/ =end #============================================================================ # カスタマイズポイント #============================================================================ module DAI_Move # 指定位置へ最短距離移動時の再計算間隔歩数。 # 少ないほど精度は高いが重くなる。 P = 10 # ランダム移動イベントがプレイヤーから遠ざかる機能を使用。 E = true end #============================================================================== # ■ Game_Character #============================================================================== class Game_Character #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_reader :move_type attr_reader :stop_count attr_reader :move_frequency #-------------------------------------------------------------------------- # ● 目的地までの最短経路を作成 #-------------------------------------------------------------------------- def search_route(target_x, target_y, type = 0) @route_count = 0 @target_route = [] return false if target_x == @x and target_y == @y @openlist = [@x * 1000 + @y, target_x * 1000 + target_y] @closelist = {@x * 1000 + @y=>0, target_x * 1000 + target_y=>1} @lootlist = [[],[]] @pointer = 0 while @pointer < @openlist.length for i in 1..4 a = way(i) b = @openlist[@pointer] c = @lootlist[@pointer] if @closelist.include?(a) if @closelist[a] != @closelist[b] if @closelist[a] == 0 half_route = c half_route.push 5 - i perfect_route = @lootlist[@openlist.index(a)] else half_route = @lootlist[@openlist.index(a)] perfect_route = c perfect_route.push i end half_route.reverse! perfect_route += half_route @target_route = perfect_route return @target_route end else if type == 0 newloot(a, b, c, i) if dir_passable?(b / 1000, b % 1000, i * 2) else newloot(a, b, c, i) if dir_e_passable?(b / 1000, b % 1000, i * 2) end end end @pointer += 1 end return false end #-------------------------------------------------------------------------- # ● 座標変換 #-------------------------------------------------------------------------- def way(i) case i when 1 ; a = @openlist[@pointer] + 1 when 2 ; a = @openlist[@pointer] - 1000 when 3 ; a = @openlist[@pointer] + 1000 when 4 ; a = @openlist[@pointer] - 1 end return a end #-------------------------------------------------------------------------- # ● 経路追加 #-------------------------------------------------------------------------- def newloot(a, b, c, i) @openlist.push a @closelist[a] = @closelist[b] loot = c.dup if @closelist[a] == 0 loot.push i else loot.push 5 - i end @lootlist.push loot end #-------------------------------------------------------------------------- # ● 指定座標から指定方向への通行可能判定 #-------------------------------------------------------------------------- def dir_passable?(x, y, d) case d when 2 ; a = passable?(x, y + 1) when 4 ; a = passable?(x - 1, y) when 6 ; a = passable?(x + 1, y) when 8 ; a = passable?(x, y - 1) end return a end #-------------------------------------------------------------------------- # ● キャラクターとの衝突を考えない指定方向への通行可能判定 #-------------------------------------------------------------------------- def dir_e_passable?(x, y, d) case d when 2 ; a = e_passable?(x, y + 1) when 4 ; a = e_passable?(x - 1, y) when 6 ; a = e_passable?(x + 1, y) when 8 ; a = e_passable?(x, y - 1) end return a end #-------------------------------------------------------------------------- # ● キャラクターとの衝突を考えない通行可能判定 #-------------------------------------------------------------------------- def e_passable?(x, y) x = $game_map.round_x(x) y = $game_map.round_y(y) return false unless $game_map.valid?(x, y) return true if @through or debug_through? return false unless map_passable?(x, y) return true end #-------------------------------------------------------------------------- # ● 最短移動ルートの配列に従い移動(イベントコマンド:スクリプト専用) #-------------------------------------------------------------------------- def target_route_move(x, y) if search_route(x, y, 0) == false search_route(x, y, 1) else search_route(x, y) end move_route = RPG::MoveRoute.new for i in 0...@target_route.length move_route.list[i] = RPG::MoveCommand.new move_route.list[i].code = @target_route[i] end force_move_route(move_route) @target_route = [] return end #-------------------------------------------------------------------------- # ● 最短移動ルートの配列に従い一歩だけ移動(移動ルートの指定専用) #-------------------------------------------------------------------------- def target_p_move_auto(x, y) if @route_count == DAI_Move::P or @target_route == nil if search_route(x, y, 0) == false search_route(x, y, 1) else search_route(x, y) end end case @target_route[@route_count] when 1 ; move_down when 2 ; move_left when 3 ; move_right when 4 ; move_up end @route_count += 1 return end #-------------------------------------------------------------------------- # ● 指定キャラクターに近づく(移動ルートの指定専用) #-------------------------------------------------------------------------- def target_c_move_auto(id) if id == 0 target = $game_player else target = $game_map.events[id] end return if target == nil target_p_move_auto(target.x, target.y) end #-------------------------------------------------------------------------- # ● 通行可能な限り前進、通行不可でランダムに方向転換 #-------------------------------------------------------------------------- def search_front unless moving? if dir_passable?(@x, @y, @direction) move_forward else turn_random end end end #-------------------------------------------------------------------------- # ● 移動タイプ : エリア内ランダム #-------------------------------------------------------------------------- def move_type_area_random(id) case rand(6) when 0..1; move_area_random(id) when 2..4; move_forward if dir_passable_in_area?(@direction, id) when 5; @stop_count = 0 end end #-------------------------------------------------------------------------- # ● エリア内をランダムに移動 #-------------------------------------------------------------------------- def move_area_random(id) a = in_area_passable?(id) return if a.empty? b = rand(a.size) case a[b] when 2 ; move_down(false) when 4 ; move_left(false) when 6 ; move_right(false) when 8 ; move_up(false) end end #-------------------------------------------------------------------------- # ● エリア内の通行可能な方向を取得 #-------------------------------------------------------------------------- def in_area_passable?(id) a = [] a.push 2 if dir_passable_in_area?(2, id) a.push 4 if dir_passable_in_area?(4, id) a.push 6 if dir_passable_in_area?(6, id) a.push 8 if dir_passable_in_area?(8, id) return a end #-------------------------------------------------------------------------- # ● 指定方向がエリア内で通行可能か? #-------------------------------------------------------------------------- def dir_passable_in_area?(d, id) case d when 2 return $game_map.in_area?(id, @x, @y + 1) && dir_passable?(@x, @y, 2) when 4 return $game_map.in_area?(id, @x - 1, @y) && dir_passable?(@x, @y, 4) when 6 return $game_map.in_area?(id, @x + 1, @y) && dir_passable?(@x, @y, 4) when 8 return $game_map.in_area?(id, @x, @y - 1) && dir_passable?(@x, @y, 8) end end #-------------------------------------------------------------------------- # ● 移動タイプ : カスタム #-------------------------------------------------------------------------- alias dai_custom_move_move_type_custom move_type_custom def move_type_custom return if @move_route.list[@move_route_index] == nil dai_custom_move_move_type_custom end end #============================================================================== # ■ Game_Player #============================================================================== class Game_Player < Game_Character #-------------------------------------------------------------------------- # ● 接触イベントの起動判定 #-------------------------------------------------------------------------- alias dai_custom_move_check_event_trigger_touch check_event_trigger_touch def check_event_trigger_touch(x, y) for event in $game_map.events_xy(x, y) if event.trigger == 0 && event.priority_type == 1 && DAI_Move::E && event.move_type == 1 && event.stop_count > 30 * (4 - event.move_frequency) event.move_away_from_player end end dai_custom_move_check_event_trigger_touch(x, y) end end #============================================================================== # ■ Game_Map #============================================================================== class Game_Map #-------------------------------------------------------------------------- # ● エリア内判定 #-------------------------------------------------------------------------- def in_area?(id, x, y) area = $data_areas[id] return false if area == nil return false if $game_map.map_id != area.map_id return false if x < area.rect.x return false if y < area.rect.y return false if x >= area.rect.x + area.rect.width return false if y >= area.rect.y + area.rect.height return true end end