vxで経路探索スクリプト
vxで経路探索スクリプト
質問トピックでも書かせて頂いていますが、
Vxで経路探索スクリプトを作っていらっしゃる方はおられるでしょうか?
Vxaceではどうも動作が重たいようなので
止めておいた方が良いなら諦めます。。
Vxで経路探索スクリプトを作っていらっしゃる方はおられるでしょうか?
Vxaceではどうも動作が重たいようなので
止めておいた方が良いなら諦めます。。
Re: vxで経路探索スクリプト
以前作ったこれから必要な機能だけ引き出してきました。
VXBeteranだとどうも重たいなぁ……何か原因があるんだろうか?
VXBeteranだとどうも重たいなぁ……何か原因があるんだろうか?
コード: 全て選択
=begin
◆概要
経路探索のような動きができます。
◆機能
・移動ルートの設定のスクリプトで「move_toward_target($game_player)」とやると
プレイヤーに近づくかもしれません。
・移動ルートの設定のスクリプトで「move_toward_target($game_map.events[n])」
(nはID)とやると、そのイベントに近づくかもしれません。
・地点指定は「move_toward_point([x, y])」
◆仕様
・VXBeteranで作成したのでVXで動くかが分からない。
・必ず繰り返してください。
◆使用上の注意
・特になし。
=end
class Game_Map
#--------------------------------------------------------------------------
# ○ 地点からの距離計算
#--------------------------------------------------------------------------
def distance_points(point1, point2)
sx = point1[0] - point2[0]
sy = point1[1] - point2[1]
if $game_map.loop_horizontal? # 横にループしているとき
if sx.abs > $game_map.width / 2 # 絶対値がマップの半分より大きい?
sx -= $game_map.width # マップの幅を引く
end
end
if $game_map.loop_vertical? # 縦にループしているとき
if sy.abs > $game_map.height / 2 # 絶対値がマップの半分より大きい?
sy -= $game_map.height # マップの高さを引く
end
end
return sx.abs + sy.abs
end
#--------------------------------------------------------------------------
# ○ イベント含む通行可能?
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def passable_pef?(x, y)
return false if !passable?(x, y)
([$game_player] + events.values).all?{|c|!c.pos_nt?(x, y)}
end
#--------------------------------------------------------------------------
# ○ ある地点の周りでの通行可能な地点の取得
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def movable_points(x, y)
points = []
[[x,y+1],[x-1,y],[x+1,y],[x,y-1]].each{|point|
points.push(point) if passable_pef?(point[0], point[1])}
points
end
#--------------------------------------------------------------------------
# ○ ある地点の周りでのマップ上通行可能な地点の取得
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def passable_points(x, y)
points = []
[[x,y+1],[x-1,y],[x+1,y],[x,y-1]].each{|point|
points.push(point) if passable?(point[0], point[1])}
points
end
end
class Game_Character
#--------------------------------------------------------------------------
# ○ 地点からの X 距離計算
#--------------------------------------------------------------------------
def distance_x_from_point(x)
sx = @x - x
if $game_map.loop_horizontal? # 横にループしているとき
if sx.abs > $game_map.width / 2 # 絶対値がマップの半分より大きい?
sx -= $game_map.width # マップの幅を引く
end
end
return sx
end
#--------------------------------------------------------------------------
# ○ 地点からの Y 距離計算
#--------------------------------------------------------------------------
def distance_y_from_point(y)
sy = @y - y
if $game_map.loop_vertical? # 縦にループしているとき
if sy.abs > $game_map.height / 2 # 絶対値がマップの半分より大きい?
sy -= $game_map.height # マップの高さを引く
end
end
return sy
end
#--------------------------------------------------------------------------
# ○ 動ける箇所の取得
#--------------------------------------------------------------------------
def movable_points
points = [[x,y+1],[x-1,y],[x+1,y],[x,y-1]].select{|point|
$game_map.passable_pef?(point[0], point[1])
}
case @direction
when 2; points.sort{|a, b|a[1] <=> b[1]}
when 4; points.sort{|a, b|b[0] <=> a[0]}
when 6; points.sort{|a, b|a[0] <=> b[0]}
when 8; points.sort{|a, b|b[1] <=> a[1]}
end
end
#--------------------------------------------------------------------------
# ○ 地点に向かう
#--------------------------------------------------------------------------
def move_point(x, y)
sx = distance_x_from_point(x); sy = distance_y_from_point(y)
if sx != 0 or sy != 0
if sx.abs > sy.abs
sx > 0 ? move_left : move_right
sy > 0 ? move_up : move_down if @move_failed && sy != 0
elsif sx.abs < sy.abs
sy > 0 ? move_up : move_down
sx > 0 ? move_left : move_right if @move_failed && sx != 0
else
if rand(2).zero?
sx > 0 ? move_left : move_right
sy > 0 ? move_up : move_down if @move_failed && sy != 0
else
sy > 0 ? move_up : move_down
sx > 0 ? move_left : move_right if @move_failed && sx != 0
end
end
end
end
#--------------------------------------------------------------------------
# ○ 地点に近づく
#--------------------------------------------------------------------------
def move_toward_point(point)
return if moving?
if @route && !@route.empty?
if @target
d1 = $game_map.distance_points([self.x, self.y], [@target.x, @target.y])
d2 = $game_map.distance_points(@route[-1], [@target.x, @target.y])
if d1 < d2
route_set([@target.x, @target.y])
else
po = @route.shift
move_point(po[0], po[1])
end
else
po = @route.shift
move_point(po[0], po[1])
end
else
route_set(point)
end
end
#--------------------------------------------------------------------------
# ○ ルートの設定
#--------------------------------------------------------------------------
def route_set(point)
return if (self.x - point[0]).abs + (self.y - point[1]).abs <= 1
return if !map_passable?(point[0], point[1])
return if moving?
def_point = !movable_points.compact.empty? ? movable_points[0] : [0, 0]
mx = self.x; my = self.y; minip = nil; min = 32; route = []
fail_route = []; @loop_count = [0, 0]
loop do
min = 32
points = $game_map.movable_points(mx, my) - route - fail_route
points=$game_map.passable_points(mx,my)-route-fail_route if points.empty?
if points.empty?
fail_route.push([mx, my])
while ($game_map.passable_points(mx, my) - route - fail_route).empty?
route.delete_at(-1); return @route.clear if route.empty?
fp = route[-1]; mx = fp[0]; my = fp[1]
fail_route.push([mx, my])
@loop_count[1] += 1; return if @loop_count[1] > 10
end
@loop_count[1] = 0
mx = def_point[0]; my = def_point[1]; route = [def_point]; next
end
points.each{|point_a|minip = point_a if minip.nil?
if min >= (point[0] - point_a[0]).abs + (point[1] - point_a[1]).abs
minip = point_a
min = (point[0] - point_a[0]).abs + (point[1] - point_a[1]).abs
end}
mx, my = minip[0], minip[1]; route.push(minip); break if min <= 1
@loop_count[0] += 1; return if @loop_count[0] > 32
end
@route = route
end
#--------------------------------------------------------------------------
# ○ 目標に近づく(壁周り)
#--------------------------------------------------------------------------
def move_toward_target(target)
return if !target
@target = target
move_toward_point([target.x, target.y])
end
end
------------------------------------------------------------------
自作の(改造でない)スクリプト、プラグイン素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
自作の(改造でない)スクリプト、プラグイン素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
Re: vxで経路探索スクリプト
度々、ありがとうございます!
何度か試させて頂いたのですが
障害物のないマップなら成功したのですが、
目標地点xへの直線上に通行不可のタイルがあると
停止してしまうのですが、
どのように命令を組めば良いのでしょうか…?
質問ばかりで申し訳ありません。
何度か試させて頂いたのですが
障害物のないマップなら成功したのですが、
目標地点xへの直線上に通行不可のタイルがあると
停止してしまうのですが、
どのように命令を組めば良いのでしょうか…?
質問ばかりで申し訳ありません。
Re: vxで経路探索スクリプト
状況がよくわかりません。添付画像のA~Cならどれに当たりますでしょうか。
ちなみにこちらは自律移動の「カスタム」でのみ調査しています。
とりあえずちょっと改造してみましたがこんなんでどうでしょう。ちなみに、「def route_set(point)」の中にある「min = 32」「@loop_count[1] > 16」「@loop_count[0] > 32」の数値は
ループ限界値で、この数値を大きくすると遠くまで経路探索してくれるようになります。
当然、負荷も大きいです。
ちなみにこちらは自律移動の「カスタム」でのみ調査しています。
とりあえずちょっと改造してみましたがこんなんでどうでしょう。
コード: 全て選択
=begin
◆概要
経路探索のような動きができます。
◆機能
・移動ルートの設定のスクリプトで「move_toward_target($game_player)」とやると
プレイヤーに近づくかもしれません。
・移動ルートの設定のスクリプトで「move_toward_target($game_map.events[n])」
(nはID)とやると、そのイベントに近づくかもしれません。
・地点指定は「move_toward_point([x, y])」
◆仕様
・VXBeteranで作成したのでVXで動くかが分からない。
・必ず繰り返してください。
◆使用上の注意
・特になし。
=end
class Game_Map
#--------------------------------------------------------------------------
# ○ 地点からの距離計算
#--------------------------------------------------------------------------
def distance_points(point1, point2)
sx = point1[0] - point2[0]
sy = point1[1] - point2[1]
if $game_map.loop_horizontal? # 横にループしているとき
if sx.abs > $game_map.width / 2 # 絶対値がマップの半分より大きい?
sx -= $game_map.width # マップの幅を引く
end
end
if $game_map.loop_vertical? # 縦にループしているとき
if sy.abs > $game_map.height / 2 # 絶対値がマップの半分より大きい?
sy -= $game_map.height # マップの高さを引く
end
end
return sx.abs + sy.abs
end
#--------------------------------------------------------------------------
# ○ イベント含む通行可能?
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def passable_pef?(x, y)
return false if !passable?(x, y)
([$game_player] + events.values).all?{|c|!c.pos_nt?(x, y)}
end
#--------------------------------------------------------------------------
# ○ ある地点の周りでの通行可能な地点の取得
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def movable_points(x, y)
points = []
[[x,y+1],[x-1,y],[x+1,y],[x,y-1]].each{|point|
points.push(point) if passable_pef?(point[0], point[1])}
points
end
#--------------------------------------------------------------------------
# ○ ある地点の周りでのマップ上通行可能な地点の取得
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def passable_points(x, y)
points = []
[[x,y+1],[x-1,y],[x+1,y],[x,y-1]].each{|point|
points.push(point) if passable?(point[0], point[1])}
points
end
end
class Game_Character
#--------------------------------------------------------------------------
# ○ 地点からの X 距離計算
#--------------------------------------------------------------------------
def distance_x_from_point(x)
sx = @x - x
if $game_map.loop_horizontal? # 横にループしているとき
if sx.abs > $game_map.width / 2 # 絶対値がマップの半分より大きい?
sx -= $game_map.width # マップの幅を引く
end
end
return sx
end
#--------------------------------------------------------------------------
# ○ 地点からの Y 距離計算
#--------------------------------------------------------------------------
def distance_y_from_point(y)
sy = @y - y
if $game_map.loop_vertical? # 縦にループしているとき
if sy.abs > $game_map.height / 2 # 絶対値がマップの半分より大きい?
sy -= $game_map.height # マップの高さを引く
end
end
return sy
end
#--------------------------------------------------------------------------
# ○ 動ける箇所の取得
#--------------------------------------------------------------------------
def movable_points
points = [[x,y+1],[x-1,y],[x+1,y],[x,y-1]].select{|point|
$game_map.passable_pef?(point[0], point[1])
}
case @direction
when 2; points.sort{|a, b|a[1] <=> b[1]}
when 4; points.sort{|a, b|b[0] <=> a[0]}
when 6; points.sort{|a, b|a[0] <=> b[0]}
when 8; points.sort{|a, b|b[1] <=> a[1]}
end
end
#--------------------------------------------------------------------------
# ○ 地点に向かう
#--------------------------------------------------------------------------
def move_point(x, y)
sx = distance_x_from_point(x); sy = distance_y_from_point(y)
if sx != 0 or sy != 0
if sx.abs > sy.abs
sx > 0 ? move_left : move_right
sy > 0 ? move_up : move_down if @move_failed && sy != 0
elsif sx.abs < sy.abs
sy > 0 ? move_up : move_down
sx > 0 ? move_left : move_right if @move_failed && sx != 0
else
if rand(2).zero?
sx > 0 ? move_left : move_right
sy > 0 ? move_up : move_down if @move_failed && sy != 0
else
sy > 0 ? move_up : move_down
sx > 0 ? move_left : move_right if @move_failed && sx != 0
end
end
end
end
#--------------------------------------------------------------------------
# ○ 地点に近づく
#--------------------------------------------------------------------------
def move_toward_point(point)
return if moving?
if @route && !@route.empty?
#~ if @target
#~ d1 = $game_map.distance_points([self.x, self.y], [@target.x, @target.y])
#~ d2 = $game_map.distance_points(@route[-1], [@target.x, @target.y])
#~ if d1 < d2
#~ route_set([@target.x, @target.y])
#~ else
po = @route.shift
move_point(po[0], po[1])
#~ end
#~ else
#~ po = @route.shift
#~ move_point(po[0], po[1])
#~ end
else
route_set(point)
end
end
#--------------------------------------------------------------------------
# ○ ルートの設定
#--------------------------------------------------------------------------
def route_set(point)
return if (self.x - point[0]).abs + (self.y - point[1]).abs <= 1
return if !map_passable?(point[0], point[1])
return if moving?
def_point = !movable_points.compact.empty? ? movable_points[0] : [0, 0]
mx = self.x; my = self.y; minip = nil; min = 32; route = [[mx, my]]
fail_route = []; @loop_count = [0, 0]
loop do
min = 32
points = $game_map.movable_points(mx, my) - route - fail_route
points=$game_map.passable_points(mx,my)-route-fail_route if points.empty?
if points.empty?
begin
fail_route.push([mx, my])
route.delete_at(-1); return (@route || []).clear if route.empty?
fp = route[-1]; mx = fp[0]; my = fp[1]
@loop_count[1] += 1; return if @loop_count[1] > 16
end while ($game_map.passable_points(mx, my) - route - fail_route).empty?
@loop_count = [0, 0]
mx = def_point[0]; my = def_point[1]; route = [def_point]; next
end
points.each{|point_a|minip = point_a if minip.nil?
if min >= (point[0] - point_a[0]).abs + (point[1] - point_a[1]).abs
minip = point_a
min = (point[0] - point_a[0]).abs + (point[1] - point_a[1]).abs
end}
mx, my = minip[0], minip[1]; route.push(minip); break if min <= 1
@loop_count[0] += 1; return if @loop_count[0] > 32
end
@route = route
end
#--------------------------------------------------------------------------
# ○ 目標に近づく(壁周り)
#--------------------------------------------------------------------------
def move_toward_target(target)
return if !target
@target = target
move_toward_point([target.x, target.y])
end
end
ループ限界値で、この数値を大きくすると遠くまで経路探索してくれるようになります。
当然、負荷も大きいです。
------------------------------------------------------------------
自作の(改造でない)スクリプト、プラグイン素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
自作の(改造でない)スクリプト、プラグイン素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
Re: vxで経路探索スクリプト
ご丁寧にありがとうございます!
今回御作り頂いたスクリプトも試したのですが
画像Bの様に2,3歩上や下に迂回するだけで目的地に着ける場合は動くのですが
それ以上歩数があったり、ルートが複雑になると停止してしまいます。
目的地が近ければ迷路みたいな道でも動くようです。
そうするとやはり距離の問題でしょうか?
詳しくは分かりませんがループ限界値を大きくすれば出来そうですが不可も大きいのですよね?
それを複数設置するとなると…無理そうですよね。。
今回御作り頂いたスクリプトも試したのですが
画像Bの様に2,3歩上や下に迂回するだけで目的地に着ける場合は動くのですが
それ以上歩数があったり、ルートが複雑になると停止してしまいます。
目的地が近ければ迷路みたいな道でも動くようです。
そうするとやはり距離の問題でしょうか?
詳しくは分かりませんがループ限界値を大きくすれば出来そうですが不可も大きいのですよね?
それを複数設置するとなると…無理そうですよね。。
Re: vxで経路探索スクリプト
以前のものから大幅に変更した新作の試作版が出来上がりました。
・A*と呼ばれる方法のマネをしています。完全に再現できてるかは怪しい。
・負荷が大きくならないよう、経路探索を途中でやめて、近そうだなと思ったところに行きます。
・なのでよくわからないところに行ったりする。
・以前の経路探索情報を利用します。大した効果はない。
・(2つ前のヤツにもあったけど)目的地が動いたらルート途中で曲がったりします。
※このスクリプトは試作版なので正常かつ負荷なく動くかは知りません。負荷に関しては実際に確かめてみて、妥協するところは妥協したほうがよろしいかと。
※19:49 色々不備があったので流石に修正 Rubyのバージョンが古くて使えないメソッドは失念してた
・A*と呼ばれる方法のマネをしています。完全に再現できてるかは怪しい。
・負荷が大きくならないよう、経路探索を途中でやめて、近そうだなと思ったところに行きます。
・なのでよくわからないところに行ったりする。
・以前の経路探索情報を利用します。大した効果はない。
・(2つ前のヤツにもあったけど)目的地が動いたらルート途中で曲がったりします。
※このスクリプトは試作版なので正常かつ負荷なく動くかは知りません。
コード: 全て選択
# ◆作者:faida @faida3983
class A_star_Node
attr_reader :x
attr_reader :y
attr_accessor :real_cost
attr_reader :predict_cost
def initialize(x, y, parent = [])
@x, @y = x, y
@parent = parent
@real_cost = 0
@predict_cost = 0
@state = :none
end
def calc_predict_cost(goal)
@predict_cost = (goal[0] - x).abs + (goal[1] - y).abs
end
def score
@real_cost + @predict_cost
end
def open?
@state == :open
end
def closed?
@state == :closed
end
def open
@state = :open
end
def close
@state = :closed
end
def get_route
@parent + [[@x, @y]]
end
def pos?(x, y)
@x == x && @y == y
end
def movable_points
$game_map.movable_points(@x, @y)
end
def passable_points
$game_map.passable_points(@x, @y)
end
def check_node
[@x, @y, real_cost, score]
end
end
class A_star_Route
attr_reader :ended_route_search
def initialize(start, goal)
@start, @goal = start, goal
@x, @y = @start[0], @start[1]
@route = []
@open_node = [A_star_Node.new(@x, @y, [])]
@closed_node = []
@loop_count = 0
@ended_route_search = false
end
def route_search
start_route_search
loop do
s_node = get_standard_node
return end_route_search(s_node) if s_node.pos?(@goal[0], @goal[1])
return temp_end_route_search if @loop_count > 128
points = s_node.movable_points
points = s_node.passable_points if points.empty?
points.each{|point|
next if (@open_node + @closed_node).any?{|n|n.pos?(point[0], point[1])}
@open_node << A_star_Node.new(point[0], point[1], s_node.get_route)
@open_node[-1].real_cost = s_node.real_cost + 1
@open_node[-1].calc_predict_cost(@goal)
}
@open_node.delete(s_node)
@closed_node << s_node
@loop_count += 1
end
end
def start_route_search
end
def get_standard_node
score = @open_node.collect{|n|n.score}.min
arr = @open_node.select{|n|n.score == score}
real_cost = arr.collect{|n|n.real_cost}.min
arr.find{|n|n.real_cost}
end
def end_route_search(node)
route = node.get_route
$game_system.route_list.add_route_search(route)
@ended_route_search = true
route
end
def temp_end_route_search
get_standard_node.get_route
end
end
class A_star_RouteResult
attr_reader :start
attr_reader :route
attr_reader :goal
def initialize(route)
@start, @route, @goal = route[0], route, route[-1]
end
def concat(result)
if result.start == self.goal
@route.concat(result.route); return true
elsif self.start == result.goal
@route = result.route.concat(@route); return true
end
false
end
def include?(start, goal)
@route.include?(start) && @route.include?(goal)
end
def reuse_route(start, goal)
return nil if !include?(start, goal)
if @route.index(start) < @route.index(goal)
@route[@route.index(start), @route.index(goal) - @route.index(start) + 1]
else
@route[@route.index(goal), @route.index(start) - @route.index(goal) + 1]
end
end
end
class A_star_RouteList
def initialize(map_id)
@map_id = map_id
@list = []
end
def add_route_search(route)
@list.push(A_star_RouteResult.new(route))
end
def include?(start, goal)
@list.find{|result|result.include?(start, goal)}
end
end
class Game_System
attr_reader :route_list
alias fai_routesearch_initialize initialize
def initialize
fai_routesearch_initialize
@route_list = {}
end
def setup_route_list(map_id)
@route_list = {} if !@route_list
@route_list[map_id] = A_star_RouteList.new(map_id)
end
def add_route_list(map_id, route)
setup_route_list(map_id) if !@route_list || !@route_list[map_id]
@route_list[map_id].add_route_search(route)
end
def route_list
setup_route_list($game_map.map_id) if !@route_list || !@route_list[$game_map.map_id]
@route_list[$game_map.map_id]
end
end
class Game_Map
#--------------------------------------------------------------------------
# ○ 地点からの距離計算
#--------------------------------------------------------------------------
def distance_points(point1, point2)
sx = point1[0] - point2[0]
sy = point1[1] - point2[1]
if $game_map.loop_horizontal? # 横にループしているとき
if sx.abs > $game_map.width / 2 # 絶対値がマップの半分より大きい?
sx -= $game_map.width # マップの幅を引く
end
end
if $game_map.loop_vertical? # 縦にループしているとき
if sy.abs > $game_map.height / 2 # 絶対値がマップの半分より大きい?
sy -= $game_map.height # マップの高さを引く
end
end
return sx.abs + sy.abs
end
#--------------------------------------------------------------------------
# ○ イベント含む通行可能?
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def passable_pef?(x, y)
return false if !passable?(x, y)
(events.values).all?{|c|!c.pos_nt?(x, y)}
end
#--------------------------------------------------------------------------
# ○ ある地点の周りでの通行可能な地点の取得
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def movable_points(x, y)
points = []
[[x,y+1],[x-1,y],[x+1,y],[x,y-1]].each{|point|
points.push(point) if passable_pef?(point[0], point[1])}
points
end
#--------------------------------------------------------------------------
# ○ ある地点の周りでのマップ上通行可能な地点の取得
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def passable_points(x, y)
points = []
[[x,y+1],[x-1,y],[x+1,y],[x,y-1]].each{|point|
points.push(point) if passable?(point[0], point[1])}
points
end
end
class Game_Character
#--------------------------------------------------------------------------
# ○ 地点からの X 距離計算
#--------------------------------------------------------------------------
def distance_x_from_point(x)
sx = @x - x
if $game_map.loop_horizontal? # 横にループしているとき
if sx.abs > $game_map.width / 2 # 絶対値がマップの半分より大きい?
sx -= $game_map.width # マップの幅を引く
end
end
return sx
end
#--------------------------------------------------------------------------
# ○ 地点からの Y 距離計算
#--------------------------------------------------------------------------
def distance_y_from_point(y)
sy = @y - y
if $game_map.loop_vertical? # 縦にループしているとき
if sy.abs > $game_map.height / 2 # 絶対値がマップの半分より大きい?
sy -= $game_map.height # マップの高さを引く
end
end
return sy
end
#--------------------------------------------------------------------------
# ○ 地点に向かう
#--------------------------------------------------------------------------
def move_point(x, y)
sx = distance_x_from_point(x); sy = distance_y_from_point(y)
if sx != 0 or sy != 0
if sx.abs > sy.abs
sx > 0 ? move_left : move_right
sy > 0 ? move_up : move_down if @move_failed && sy != 0
elsif sx.abs < sy.abs
sy > 0 ? move_up : move_down
sx > 0 ? move_left : move_right if @move_failed && sx != 0
else
if rand(2).zero?
sx > 0 ? move_left : move_right
sy > 0 ? move_up : move_down if @move_failed && sy != 0
else
sy > 0 ? move_up : move_down
sx > 0 ? move_left : move_right if @move_failed && sx != 0
end
end
end
end
#--------------------------------------------------------------------------
# ○ 地点に近づく
#--------------------------------------------------------------------------
def move_toward_point(point)
return if moving?
if @route && !@route.empty?
if @target && @ended_route_search
d1 = $game_map.distance_points([self.x, self.y], [@target.x, @target.y])
d2 = $game_map.distance_points(@route[-1], [@target.x, @target.y])
if d1 < d2
route_set([@target.x, @target.y])
else
po = @route.shift
move_point(po[0], po[1])
end
else
po = @route.shift
move_point(po[0], po[1])
end
else
route_set(point)
end
end
#--------------------------------------------------------------------------
# ○ ルートの設定
#--------------------------------------------------------------------------
def route_set(point)
result = $game_system.route_list.include?([self.x, self.y], point)
if $game_system.route_list.include?([self.x, self.y], point)
@route = result.reuse_route([self.x, self.y], point)
else
a_star_route = A_star_Route.new([self.x, self.y], point)
@ended_route_search = a_star_route.ended_route_search
@route = a_star_route.route_search
end
end
#--------------------------------------------------------------------------
# ○ 目標に近づく(壁周り)
#--------------------------------------------------------------------------
def move_toward_target(target)
return if !target
@target = target
x_d = distance_x_from_point(target.x).abs
y_d = distance_y_from_point(target.y).abs
return if x_d + y_d <= 1
move_toward_point([target.x, target.y])
end
end
※19:49 色々不備があったので流石に修正 Rubyのバージョンが古くて使えないメソッドは失念してた
------------------------------------------------------------------
自作の(改造でない)スクリプト、プラグイン素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
自作の(改造でない)スクリプト、プラグイン素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
Re: vxで経路探索スクリプト
度々、本当にありがとうございます!
ルートに壁や障害物があっても停止しなくなりました!
何とか目的地へ進もうとしてくれているのが愛おしいくらいです(笑)
ただ、やはり目的地が遠すぎると途中で諦めてスタート地点とそこまでの地点を行ったり来たりしてしまいますが。
こればかりは仕様ですよね?
あと複数設置して作動させたら、たまに画像の様な警告が出てシャットダウンされますが、
何が原因なのでしょうか?
わざわざスクリプトを組んで頂いて、更に質問ばかり重ねて本当に申し訳ありません。。
ルートに壁や障害物があっても停止しなくなりました!
何とか目的地へ進もうとしてくれているのが愛おしいくらいです(笑)
ただ、やはり目的地が遠すぎると途中で諦めてスタート地点とそこまでの地点を行ったり来たりしてしまいますが。
こればかりは仕様ですよね?
あと複数設置して作動させたら、たまに画像の様な警告が出てシャットダウンされますが、
何が原因なのでしょうか?
わざわざスクリプトを組んで頂いて、更に質問ばかり重ねて本当に申し訳ありません。。
- 添付ファイル
-
- キャプチャs.PNG (27.72 KiB) 閲覧された回数 7966 回
Re: vxで経路探索スクリプト
とりあえずの修正版です。
次のルートが黒い線になったりします。回り込みすぎる場合は負荷を上げるしかないです。
一応設定項目で探査マス(距離や道のりではない)を設定できます。
あと、実は一度探査したルートを再使用していたりするので、(一度探査すれば)実際そこまで負荷が高い感じは
ありません。
コード: 全て選択
# ◆作者:faida @faida3983
module FAI_RouteSearch
# 経路探索するマスの個数。
# 小さいほど精度が下がるが、大きいと負荷が上がる。
SEARCH_AREA = 64
end
class A_star_Node
attr_reader :x
attr_reader :y
attr_accessor :real_cost
attr_reader :predict_cost
def initialize(x, y, parent = [])
@x, @y = x, y
@parent = parent
@real_cost = 0
@predict_cost = 0
@state = :none
end
def calc_predict_cost(goal)
@predict_cost = (goal[0] - x).abs + (goal[1] - y).abs
end
def score
@real_cost + @predict_cost
end
def open?
@state == :open
end
def closed?
@state == :closed
end
def open
@state = :open
end
def close
@state = :closed
end
def get_route
@parent + [[@x, @y]]
end
def pos?(x, y)
@x == x && @y == y
end
def movable_points
$game_map.movable_points(@x, @y)
end
def passable_points
$game_map.passable_points(@x, @y)
end
def check_node
[@x, @y, real_cost, score]
end
end
class A_star_Route
attr_reader :ended_route_search
def initialize(start, goal)
@start, @goal = start, goal
@x, @y = @start[0], @start[1]
@route = []
@open_node = [A_star_Node.new(@x, @y, [])]
@open_node[0].calc_predict_cost(goal)
@closed_node = []
@loop_count = 0
@ended_route_search = false
end
def route_search
start_route_search
loop do
s_node = get_standard_node
return stop_route_search if !s_node
return end_route_search(s_node) if s_node.pos?(@goal[0], @goal[1])
return temp_end_route_search if @loop_count > FAI_RouteSearch::SEARCH_AREA
points = s_node.movable_points
points = s_node.passable_points if points.empty?
points.each{|point|
next if (@open_node + @closed_node).any?{|n|n.pos?(point[0], point[1])}
@open_node << A_star_Node.new(point[0], point[1], s_node.get_route)
@open_node[-1].real_cost = s_node.real_cost + 1
@open_node[-1].calc_predict_cost(@goal)
}
@open_node.delete(s_node)
@closed_node << s_node
@loop_count += 1
end
end
def start_route_search
end
def get_standard_node
score = @open_node.collect{|n|n.score}.min
arr = @open_node.select{|n|n.score == score}
real_cost = arr.collect{|n|n.real_cost}.min
arr.find{|n|n.real_cost}
end
def end_route_search(node)
route = node.get_route
$game_system.route_list.add_route_search(route)
@ended_route_search = true
route
end
def temp_end_route_search
get_standard_node.get_route
end
def stop_route_search
@closed_node.delete_at(0)
if !@closed_node.empty?
score = @closed_node.collect{|n|n.score}.min
arr = @closed_node.select{|n|n.score == score}
real_cost = arr.collect{|n|n.real_cost}.min
arr.find{|n|n.real_cost}.get_route
elsif !$game_map.movable_points(@x, @y).empty?
index = rand($game_map.movable_points(@x, @y).size)
[$game_map.movable_points(@x, @y)[index]]
else
[]
end
end
end
class A_star_RouteResult
attr_reader :start
attr_reader :route
attr_reader :goal
def initialize(route)
@start, @route, @goal = route[0], route, route[-1]
end
def concat(result)
if result.start == self.goal
@route.concat(result.route); return true
elsif self.start == result.goal
@route = result.route.concat(@route); return true
end
false
end
def include?(start, goal)
@route.include?(start) && @route.include?(goal)
end
def reuse_route(start, goal)
return nil if !include?(start, goal)
if @route.index(start) < @route.index(goal)
@route[@route.index(start), @route.index(goal) - @route.index(start) + 1]
else
@route[@route.index(goal), @route.index(start) - @route.index(goal) + 1]
end
end
end
class A_star_RouteList
def initialize(map_id)
@map_id = map_id
@list = []
end
def add_route_search(route)
@list.push(A_star_RouteResult.new(route))
end
def include?(start, goal)
@list.find{|result|result.include?(start, goal)}
end
end
class Game_System
attr_reader :route_list
alias fai_routesearch_initialize initialize
def initialize
fai_routesearch_initialize
@route_list = {}
end
def setup_route_list(map_id)
@route_list = {} if !@route_list
@route_list[map_id] = A_star_RouteList.new(map_id)
end
def add_route_list(map_id, route)
setup_route_list(map_id) if !@route_list || !@route_list[map_id]
@route_list[map_id].add_route_search(route)
end
def route_list
setup_route_list($game_map.map_id) if !@route_list || !@route_list[$game_map.map_id]
@route_list[$game_map.map_id]
end
end
class Game_Map
#--------------------------------------------------------------------------
# ○ 地点からの距離計算
#--------------------------------------------------------------------------
def distance_points(point1, point2)
sx = point1[0] - point2[0]
sy = point1[1] - point2[1]
if $game_map.loop_horizontal? # 横にループしているとき
if sx.abs > $game_map.width / 2 # 絶対値がマップの半分より大きい?
sx -= $game_map.width # マップの幅を引く
end
end
if $game_map.loop_vertical? # 縦にループしているとき
if sy.abs > $game_map.height / 2 # 絶対値がマップの半分より大きい?
sy -= $game_map.height # マップの高さを引く
end
end
return sx.abs + sy.abs
end
#--------------------------------------------------------------------------
# ○ イベント含む通行可能?
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def passable_pef?(x, y)
return false if !passable?(x, y)
(events.values).all?{|c|!c.pos_nt?(x, y)}
end
#--------------------------------------------------------------------------
# ○ ある地点の周りでの通行可能な地点の取得
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def movable_points(x, y)
points = []
[[x,y+1],[x-1,y],[x+1,y],[x,y-1]].each{|point|
points.push(point) if passable_pef?(point[0], point[1])}
points
end
#--------------------------------------------------------------------------
# ○ ある地点の周りでのマップ上通行可能な地点の取得
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def passable_points(x, y)
points = []
[[x,y+1],[x-1,y],[x+1,y],[x,y-1]].each{|point|
points.push(point) if passable?(point[0], point[1])}
points
end
end
class Game_Character
#--------------------------------------------------------------------------
# ○ 地点からの X 距離計算
#--------------------------------------------------------------------------
def distance_x_from_point(x)
sx = @x - x
if $game_map.loop_horizontal? # 横にループしているとき
if sx.abs > $game_map.width / 2 # 絶対値がマップの半分より大きい?
sx -= $game_map.width # マップの幅を引く
end
end
return sx
end
#--------------------------------------------------------------------------
# ○ 地点からの Y 距離計算
#--------------------------------------------------------------------------
def distance_y_from_point(y)
sy = @y - y
if $game_map.loop_vertical? # 縦にループしているとき
if sy.abs > $game_map.height / 2 # 絶対値がマップの半分より大きい?
sy -= $game_map.height # マップの高さを引く
end
end
return sy
end
#--------------------------------------------------------------------------
# ○ 地点に向かう
#--------------------------------------------------------------------------
def move_point(x, y)
sx = distance_x_from_point(x); sy = distance_y_from_point(y)
if sx != 0 or sy != 0
if sx.abs > sy.abs
sx > 0 ? move_left : move_right
sy > 0 ? move_up : move_down if @move_failed && sy != 0
elsif sx.abs < sy.abs
sy > 0 ? move_up : move_down
sx > 0 ? move_left : move_right if @move_failed && sx != 0
else
if rand(2).zero?
sx > 0 ? move_left : move_right
sy > 0 ? move_up : move_down if @move_failed && sy != 0
else
sy > 0 ? move_up : move_down
sx > 0 ? move_left : move_right if @move_failed && sx != 0
end
end
end
end
#--------------------------------------------------------------------------
# ○ 地点に近づく
#--------------------------------------------------------------------------
def move_toward_point(point)
return if moving?
if @route && !@route.empty?
if @target && @ended_route_search
d1 = $game_map.distance_points([self.x, self.y], [@target.x, @target.y])
d2 = $game_map.distance_points(@route[-1], [@target.x, @target.y])
if d1 < d2
route_set([@target.x, @target.y])
else
po = @route.shift
move_point(po[0], po[1])
end
else
po = @route.shift
move_point(po[0], po[1])
end
else
route_set(point)
end
end
#--------------------------------------------------------------------------
# ○ ルートの設定
#--------------------------------------------------------------------------
def route_set(point)
result = $game_system.route_list.include?([self.x, self.y], point)
if $game_system.route_list.include?([self.x, self.y], point)
@route = result.reuse_route([self.x, self.y], point)
else
a_star_route = A_star_Route.new([self.x, self.y], point)
@ended_route_search = a_star_route.ended_route_search
@route = a_star_route.route_search
end
end
#--------------------------------------------------------------------------
# ○ 目標に近づく(壁周り)
#--------------------------------------------------------------------------
def move_toward_target(target)
return if !target
@target = target
x_d = distance_x_from_point(target.x).abs
y_d = distance_y_from_point(target.y).abs
return if x_d + y_d <= 1
move_toward_point([target.x, target.y])
end
end
添付ファイルのようなマップを組むと特に顕著ですが、赤い線をたどったとしてもそこで止まるとただ、やはり目的地が遠すぎると途中で諦めてスタート地点とそこまでの地点を行ったり来たりしてしまいますが。
こればかりは仕様ですよね?
次のルートが黒い線になったりします。回り込みすぎる場合は負荷を上げるしかないです。
一応設定項目で探査マス(距離や道のりではない)を設定できます。
あと、実は一度探査したルートを再使用していたりするので、(一度探査すれば)実際そこまで負荷が高い感じは
ありません。
- 添付ファイル
-
- route_search_mapping.png (79.09 KiB) 閲覧された回数 7892 回
------------------------------------------------------------------
自作の(改造でない)スクリプト、プラグイン素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
自作の(改造でない)スクリプト、プラグイン素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
Re: vxで経路探索スクリプト
何度も修正してくださり、本当にありがとうございます!
大事に使わせて頂きます。。
現在、画像の様なマップで1~6を経路探索させて
目的地の☆の位置まで移動させていますが、たどり着くには1・2・4で
他の番号は初期位置と近辺をいったりきたりしています。
これはやはりマップが広く、目的地が遠くて複雑だからですよね?
もう少しマップを簡略化させるしかないか…
大事に使わせて頂きます。。
現在、画像の様なマップで1~6を経路探索させて
目的地の☆の位置まで移動させていますが、たどり着くには1・2・4で
他の番号は初期位置と近辺をいったりきたりしています。
これはやはりマップが広く、目的地が遠くて複雑だからですよね?
もう少しマップを簡略化させるしかないか…
- 添付ファイル
-
- bbb.PNG (8.01 KiB) 閲覧された回数 7845 回
Re: vxで経路探索スクリプト
少しだけ評価方法を変えた修正版です。ダイトウさんの提示したマップを実際に組んで確かめたところ、修正版ではSEARCH_AREAを150にすれば
全員が目標地点までたどり着けることが分かりました。
これ以外にイベントを置かなければあまり負荷がかからず達成できると思います(実際はあるんでしょうけれど)。
ちなみに経路探索の最大の敵はマップの幅です。
幅を1本にしたところ、SEARCH_AREAが96で足りました(ただし全員すり抜け)。
SEARCH_AREAの意味は「探索するマスの数」なので、探索するマスの数が多ければ多いほど精度が下がります。
コード: 全て選択
# ◆作者:faida @faida3983
module FAI_RouteSearch
# 経路探索するマスの個数。
# 小さいほど精度が下がるが、大きいと負荷が上がる。
SEARCH_AREA = 150
end
class A_star_Node
attr_reader :x
attr_reader :y
attr_accessor :real_cost
attr_reader :predict_cost
def initialize(x, y, parent = [])
@x, @y = x, y
@parent = parent
@real_cost = 0
@predict_cost = 0
@state = :none
end
def calc_predict_cost(goal)
@predict_cost = (goal[0] - x).abs + (goal[1] - y).abs
end
def score
@real_cost + @predict_cost
end
def open?
@state == :open
end
def closed?
@state == :closed
end
def open
@state = :open
end
def close
@state = :closed
end
def get_route
@parent + [[@x, @y]]
end
def pos?(x, y)
@x == x && @y == y
end
def movable_points
$game_map.movable_points(@x, @y)
end
def passable_points
$game_map.passable_points(@x, @y)
end
def check_node
[@x, @y, real_cost, score]
end
end
class A_star_Route
attr_reader :ended_route_search
def initialize(start, goal)
@start, @goal = start, goal
@x, @y = @start[0], @start[1]
@route = []
@open_node = [A_star_Node.new(@x, @y, [])]
@open_node[0].calc_predict_cost(goal)
@closed_node = []
@loop_count = 0
@ended_route_search = false
end
def route_search
start_route_search
loop do
s_node = get_standard_node
return stop_route_search if !s_node
return end_route_search(s_node) if s_node.pos?(@goal[0], @goal[1])
return temp_end_route_search if @loop_count > FAI_RouteSearch::SEARCH_AREA
points = s_node.movable_points
points = s_node.passable_points if points.empty?
points.each{|point|
next if (@open_node + @closed_node).any?{|n|n.pos?(point[0], point[1])}
@open_node << A_star_Node.new(point[0], point[1], s_node.get_route)
@open_node[-1].real_cost = s_node.real_cost + 1
@open_node[-1].calc_predict_cost(@goal)
}
@open_node.delete(s_node)
@closed_node << s_node
@loop_count += 1
end
end
def start_route_search
end
def get_standard_node
score = @open_node.collect{|n|n.score}.min
arr = @open_node.select{|n|n.score == score}
real_cost = arr.collect{|n|n.real_cost}.min
arr.find{|n|n.real_cost}
end
def get_closed_standard_node
score = @closed_node.collect{|n|n.score}.min
arr = @closed_node.select{|n|n.score == score}
real_cost = arr.collect{|n|n.real_cost}.min
arr.find{|n|n.real_cost}
end
def end_route_search(node)
route = node.get_route
$game_system.route_list.add_route_search(route)
@ended_route_search = true
route
end
def temp_end_route_search
o_node = get_standard_node
c_node = get_closed_standard_node
if o_node.score < c_node.score
get_closed_standard_node.get_route
else
get_standard_node.get_route
end
end
def stop_route_search
@closed_node.delete_at(0)
if !@closed_node.empty?
score = @closed_node.collect{|n|n.score}.min
arr = @closed_node.select{|n|n.score == score}
real_cost = arr.collect{|n|n.real_cost}.min
arr.find{|n|n.real_cost}.get_route
elsif !$game_map.movable_points(@x, @y).empty?
index = rand($game_map.movable_points(@x, @y).size)
[$game_map.movable_points(@x, @y)[index]]
else
[]
end
end
end
class A_star_RouteResult
attr_reader :start
attr_reader :route
attr_reader :goal
def initialize(route)
@start, @route, @goal = route[0], route, route[-1]
end
def concat(result)
if result.start == self.goal
@route.concat(result.route); return true
elsif self.start == result.goal
@route = result.route.concat(@route); return true
end
false
end
def include?(start, goal)
@route.include?(start) && @route.include?(goal)
end
def reuse_route(start, goal)
return nil if !include?(start, goal)
if @route.index(start) < @route.index(goal)
@route[@route.index(start), @route.index(goal) - @route.index(start) + 1]
else
@route[@route.index(goal), @route.index(start) - @route.index(goal) + 1]
end
end
end
class A_star_RouteList
def initialize(map_id)
@map_id = map_id
@list = []
end
def add_route_search(route)
@list.push(A_star_RouteResult.new(route))
end
def include?(start, goal)
@list.find{|result|result.include?(start, goal)}
end
end
class Game_System
attr_reader :route_list
alias fai_routesearch_initialize initialize
def initialize
fai_routesearch_initialize
@route_list = {}
end
def setup_route_list(map_id)
@route_list = {} if !@route_list
@route_list[map_id] = A_star_RouteList.new(map_id)
end
def add_route_list(map_id, route)
setup_route_list(map_id) if !@route_list || !@route_list[map_id]
@route_list[map_id].add_route_search(route)
end
def route_list
setup_route_list($game_map.map_id) if !@route_list || !@route_list[$game_map.map_id]
@route_list[$game_map.map_id]
end
end
class Game_Map
#--------------------------------------------------------------------------
# ○ 地点からの距離計算
#--------------------------------------------------------------------------
def distance_points(point1, point2)
sx = point1[0] - point2[0]
sy = point1[1] - point2[1]
if $game_map.loop_horizontal? # 横にループしているとき
if sx.abs > $game_map.width / 2 # 絶対値がマップの半分より大きい?
sx -= $game_map.width # マップの幅を引く
end
end
if $game_map.loop_vertical? # 縦にループしているとき
if sy.abs > $game_map.height / 2 # 絶対値がマップの半分より大きい?
sy -= $game_map.height # マップの高さを引く
end
end
return sx.abs + sy.abs
end
#--------------------------------------------------------------------------
# ○ イベント含む通行可能?
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def passable_pef?(x, y)
return false if !passable?(x, y)
(events.values).all?{|c|!c.pos_nt?(x, y)}
end
#--------------------------------------------------------------------------
# ○ ある地点の周りでの通行可能な地点の取得
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def movable_points(x, y)
points = []
[[x,y+1],[x-1,y],[x+1,y],[x,y-1]].each{|point|
points.push(point) if passable_pef?(point[0], point[1])}
points
end
#--------------------------------------------------------------------------
# ○ ある地点の周りでのマップ上通行可能な地点の取得
# x : X 座標
# y : Y 座標
#--------------------------------------------------------------------------
def passable_points(x, y)
points = []
[[x,y+1],[x-1,y],[x+1,y],[x,y-1]].each{|point|
points.push(point) if passable?(point[0], point[1])}
points
end
end
class Game_Character
#--------------------------------------------------------------------------
# ○ 地点からの X 距離計算
#--------------------------------------------------------------------------
def distance_x_from_point(x)
sx = @x - x
if $game_map.loop_horizontal? # 横にループしているとき
if sx.abs > $game_map.width / 2 # 絶対値がマップの半分より大きい?
sx -= $game_map.width # マップの幅を引く
end
end
return sx
end
#--------------------------------------------------------------------------
# ○ 地点からの Y 距離計算
#--------------------------------------------------------------------------
def distance_y_from_point(y)
sy = @y - y
if $game_map.loop_vertical? # 縦にループしているとき
if sy.abs > $game_map.height / 2 # 絶対値がマップの半分より大きい?
sy -= $game_map.height # マップの高さを引く
end
end
return sy
end
#--------------------------------------------------------------------------
# ○ 地点に向かう
#--------------------------------------------------------------------------
def move_point(x, y)
sx = distance_x_from_point(x); sy = distance_y_from_point(y)
if sx != 0 or sy != 0
if sx.abs > sy.abs
sx > 0 ? move_left : move_right
sy > 0 ? move_up : move_down if @move_failed && sy != 0
elsif sx.abs < sy.abs
sy > 0 ? move_up : move_down
sx > 0 ? move_left : move_right if @move_failed && sx != 0
else
if rand(2).zero?
sx > 0 ? move_left : move_right
sy > 0 ? move_up : move_down if @move_failed && sy != 0
else
sy > 0 ? move_up : move_down
sx > 0 ? move_left : move_right if @move_failed && sx != 0
end
end
end
end
#--------------------------------------------------------------------------
# ○ 地点に近づく
#--------------------------------------------------------------------------
def move_toward_point(point)
return if moving?
if @route && !@route.empty?
if @target && @ended_route_search
d1 = $game_map.distance_points([self.x, self.y], [@target.x, @target.y])
d2 = $game_map.distance_points(@route[-1], [@target.x, @target.y])
if d1 < d2
route_set([@target.x, @target.y])
else
po = @route.shift
move_point(po[0], po[1])
end
else
po = @route.shift
move_point(po[0], po[1])
end
else
route_set(point)
end
end
#--------------------------------------------------------------------------
# ○ ルートの設定
#--------------------------------------------------------------------------
def route_set(point)
result = $game_system.route_list.include?([self.x, self.y], point)
if $game_system.route_list.include?([self.x, self.y], point)
@route = result.reuse_route([self.x, self.y], point)
else
a_star_route = A_star_Route.new([self.x, self.y], point)
@ended_route_search = a_star_route.ended_route_search
@route = a_star_route.route_search
end
end
#--------------------------------------------------------------------------
# ○ 目標に近づく(壁周り)
#--------------------------------------------------------------------------
def move_toward_target(target)
return if !target
@target = target
x_d = distance_x_from_point(target.x).abs
y_d = distance_y_from_point(target.y).abs
return if x_d + y_d <= 1
move_toward_point([target.x, target.y])
end
end
全員が目標地点までたどり着けることが分かりました。
これ以外にイベントを置かなければあまり負荷がかからず達成できると思います(実際はあるんでしょうけれど)。
ちなみに経路探索の最大の敵はマップの幅です。
幅を1本にしたところ、SEARCH_AREAが96で足りました(ただし全員すり抜け)。
SEARCH_AREAの意味は「探索するマスの数」なので、探索するマスの数が多ければ多いほど精度が下がります。
------------------------------------------------------------------
自作の(改造でない)スクリプト、プラグイン素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
自作の(改造でない)スクリプト、プラグイン素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。