=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ツクールシステム研究室
[url]http://suppy1632.hp.infoseek.co.jp/[/url]
=end
#============================================================================
# カスタマイズポイント
#============================================================================
module DAI_Move
# 指定位置へ最短距離移動時の再計算間隔歩数。
# 少ないほど精度は高いが重くなる。
P = 2
# ランダム移動イベントがプレイヤーから遠ざかる機能を使用。
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 = m_passable?(x, y + 1, d)
when 4 ; a = m_passable?(x - 1, y, d)
when 6 ; a = m_passable?(x + 1, y, d)
when 8 ; a = m_passable?(x, y - 1, d)
end
return a
end
#--------------------------------------------------------------------------
# ● キャラクターとの衝突を考えない指定方向への通行可能判定
#--------------------------------------------------------------------------
def dir_e_passable?(x, y, d)
case d
when 2 ; a = e_passable?(x, y + 1, d)
when 4 ; a = e_passable?(x - 1, y, d)
when 6 ; a = e_passable?(x + 1, y, d)
when 8 ; a = e_passable?(x, y - 1, d)
end
return a
end
#--------------------------------------------------------------------------
# ● 通行可能判定
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def m_passable?(x, y, d)
x = $game_map.round_x(x) # 横方向ループ補正
y = $game_map.round_y(y) # 縦方向ループ補正
org_x = x
org_y = y
case d
when 2 ; org_y -= 1
when 4 ; org_x +=1
when 6 ; org_x -= 1
when 8 ; org_y += 1
end
return false unless $game_map.valid?(x, y) # マップ外?
return true if @through or debug_through? # すり抜け ON?
return false unless map_passable?(x, y, d) # マップが通行不能?
return false if collide_with_characters?(x, y) # キャラクターに衝突?
return true # 通行可
end
#--------------------------------------------------------------------------
# ● キャラクターとの衝突を考えない通行可能判定
#--------------------------------------------------------------------------
def e_passable?(x, y, d)
x = $game_map.round_x(x)
y = $game_map.round_y(y)
org_x = x
org_y = y
case d
when 2 ; org_y -= 1
when 4 ; org_x +=1
when 6 ; org_x -= 1
when 8 ; org_y += 1
end
return false unless $game_map.valid?(x, y)
return true if @through or debug_through?
return false unless map_passable?(x, y, d)
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]
move_route.wait = true
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
move_straight(@target_route[@route_count] * 2) if @target_route[@route_count]
@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)
move_straight(a[b])
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
end
class Game_Event < Game_Character
#--------------------------------------------------------------------------
# ● 移動タイプ : カスタム
#--------------------------------------------------------------------------
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