Project1
标题:
关于自动寻路的优化问题
[打印本页]
作者:
Wind2010
时间:
2012-8-19 00:11
标题:
关于自动寻路的优化问题
本帖最后由 Wind2010 于 2012-8-19 00:13 编辑
目前自己在用whbm的八方向寻路脚本,但是不知道为啥当距离有点远的时候会很卡……
本来还打算做个隐身靠近+被攻击后瞬移的敌人的,玩家现在一看帧率就知道敌人离自己的远近了……
于是求解有没有方法让这个寻路脚本卡的帧数低点(不大于10fps我想玩家是看不出的- -)
PS:我目前做的游戏里只有少部分敌人有自动寻路,其他敌人用的都是傻瓜式跟踪,因此应该不存在多次寻路导致变卡
悬赏什么的,发现关闭问题不返还,于是决定等有最佳答案后再加悬赏
附:自己增加的敌人追踪部分:
if event.item.is_a?(L_ARPG_boss)
if (event.screen_x-to.screen_x)**2+(event.screen_y-to.screen_y)**2 >= 32**2
t_array = $find_path.find_short_path(event.x.to_i,event.y.to_i,to.x.to_i,to.y.to_i)
event.move_dr(t_array[0])
else
event.move_toward(to)
end
else
event.move_toward(to)
end
#Game_Character
def move_dr(dr)
case dr
when 1
move_lower_left
when 2
move_down(true,false)
when 3
move_lower_right
when 4
move_left(true,false)
when 6
move_right(true,false)
when 7
move_upper_left
when 8
move_up(true,false)
when 9
move_upper_right
else
move_toward($game_player)
end
end
复制代码
像素行走脚本
寻路脚本:
#==============================================================================
# ■ Find_Path
#------------------------------------------------------------------------------
# 寻路算法
# By whbm
=begin
使用find_short_path过程则需要传递起始坐标和目标坐标
例:$find_path = Find_Path.new
path = $find_path.find_short_path(起始X坐标,起始Y坐标,目标X坐标,目标Y坐标)
=end
#==============================================================================
class Find_Path
#--------------------------------------------------------------------------
def initialize #初始化
@open_list = []
@close_lise = []
end #结束初始化
#--------------------------------------------------------------------------
def fp_passable?(x, y, d) #开始判定通行
if [2, 4, 6, 8].include?(d)
if $game_player.passable?(x, y, d)
return true
else
return false
end
else
case d
when 1
if ($game_player.passable?(x, y, 4) and
$game_player.passable?(x - 1, y, 2)) or
($game_player.passable?(x, y, 2) and
$game_player.passable?(x, y + 1, 4))
return true
else
return false
end
when 3
if ($game_player.passable?(x, y, 6) and
$game_player.passable?(x + 1, y, 2)) or
($game_player.passable?(x, y, 2) and
$game_player.passable?(x, y + 1, 6))
return true
else
return false
end
when 7
if ($game_player.passable?(x, y, 4) and
$game_player.passable?(x - 1, y, 8)) or
($game_player.passable?(x, y, 8) and
$game_player.passable?(x, y - 1, 4))
return true
else
return false
end
when 9
if ($game_player.passable?(x, y, 6) and
$game_player.passable?(x + 1, y, 8)) or
($game_player.passable?(x, y, 8) and
$game_player.passable?(x, y - 1, 6))
return true
else
return false
end
end
end
end #结束判定通行
#--------------------------------------------------------------------------
def get_g(now_point) #开始计算G值
d = now_point[2]
return 0 if d == 5
father_point = get_father_point(now_point)
g = father_point[3] + ((d == 1 or d == 3 or d == 7 or d == 9) ? 14 : 10)
return g
end #结束计算G值
#--------------------------------------------------------------------------
def get_h(now_point) #开始计算H值
now_x = now_point[0]
now_y = now_point[1]
h = (@trg_x - now_x).abs + (@trg_y - now_y).abs
return h
end #结束计算H值
#--------------------------------------------------------------------------
def get_f(now_point) #开始计算F值
return now_point[3] + now_point[4]
end #结束计算F值
#--------------------------------------------------------------------------
def get_point(x, y) #取已知坐标点
if @open_list.size != 0
@open_list.each do |point|
if point[0] == x and point[1] == y
return point
break
end
end
end
if @close_list.size != 0
@close_list.each do |point|
if point[0] == x and point[1] == y
return point
break
end
end
end
end #结束取已知坐标点
#--------------------------------------------------------------------------
def get_father_point(now_point) #取已知点的父节点
d = now_point[2]
return now_point if d == 5
x = now_point[0] + ((d == 9 or d == 6 or d == 3) ? 1 : ((d == 7 or d == 4 or d == 1) ? -1 : 0))
y = now_point[1] + ((d == 1 or d == 2 or d == 3) ? 1 : ((d == 7 or d == 8 or d == 9) ? -1 : 0))
return get_point(x, y)
end #结束取已知点的父节点
#--------------------------------------------------------------------------
def new_point(x, y, d) #开始建立新节点
#print x,y,d
point = [x, y, d]
point.push get_g(point)
point.push get_h(point)
point.push get_f(point)
return point
end #结束建立新节点
#--------------------------------------------------------------------------
def find_short_path(self_x, self_y, trg_x, trg_y) #开始搜索路径
return [] if not (fp_passable?(trg_x, trg_y, 8) or
fp_passable?(trg_x, trg_y, 4) or
fp_passable?(trg_x, trg_y, 6) or
fp_passable?(trg_x, trg_y, 2))
@self_x = self_x
@self_y = self_y
@now_x = self_x
@now_y = self_y
@trg_x = trg_x
@trg_y = trg_y
@open_list = []
@close_list = []
#准备搜索
#print @self_x,@self_y
@now_point = new_point(@self_x, @self_y, 5) #令起始点为当前点
@open_list.push @now_point #将当前点加入关闭列表
#开始搜索
loop do
check_trg = check_around_point(@now_point)
if check_trg == true
@path = get_path
break
end
@now_point = get_lowest_f_point
if @now_point == [] or @now_point == nil
@path = []
break
end
end
return @path
end #结束搜索路径
#--------------------------------------------------------------------------
def find_player_short_path(trg_x, trg_y) #寻找角色的最短路径
self_x = $game_player.x
self_y = $game_player.y
return find_short_path(self_x, self_y, trg_x, trg_y)
end #结束角色的寻找路径
#--------------------------------------------------------------------------
def get_path #取得最终的路径
path = []
now_point = @open_list[@open_list.size - 1]
path.push(10 - now_point[2])
last_point = now_point
loop do
now_point = get_father_point(now_point)
break if now_point[2] == 5
path.push(10 - now_point[2])
end
return path.reverse
end #结束取得最终的路径
#--------------------------------------------------------------------------
def get_lowest_f_point #开始取得最低F值的点
if @open_list == []
return []
end
last_lowest_f_point = @open_list[0]
@open_list.each do |point|
last_lowest_f_point = point if point[5] < last_lowest_f_point[5]
end
return last_lowest_f_point
end #结束取得最低F值点
#--------------------------------------------------------------------------
def check_around_point(point) #开始检查已知点的八方节点
for d in [1, 2, 3, 4, 6, 7, 8, 9]
x = point[0] + ((d == 9 or d == 6 or d == 3) ? 1 : ((d == 7 or d == 4 or d == 1) ? -1 : 0))
y = point[1] + ((d == 1 or d == 2 or d == 3) ? 1 : ((d == 7 or d == 8 or d == 9) ? -1 : 0))
if in_close_list?(x, y) #在关闭列表中
next
elsif in_open_list?(x, y) #在开启列表中
get_new_g_point = new_point(x, y, 10 - d)
get_last_g_point = get_point(x, y)
if get_new_g_point[3] >= get_last_g_point[3]
next
else
#如果改变父节点是新G值更小则确定改变
@open_list[@open_list.index(get_last_g_point)] = get_new_g_point
end
else
if fp_passable?(point[0], point[1], d)
# 如果不在开启列表中、且不在关闭列表中、且通行则添加它到新八周节点
@open_list.push new_point(x, y, 10 - d)
#如果将目标点添加到了开启列表中就返回true
return true if x == @trg_x and y == @trg_y
end
end
end
#此刻没有找到目标点并将当前点加入关闭列表并在开启列表中删除
@close_list.push point
@open_list.delete(point)
#此刻没找到目标点并返回false
return false
end #结束计算已知点的八方节点
#--------------------------------------------------------------------------
def in_open_list?(x, y) #开始检查谋点是否在开启列表中
@open_list.each do |point|
return true if point[0] == x and point[1] == y
end
return false
end #结束检查谋点是否在开启列表中
#--------------------------------------------------------------------------
def in_close_list?(x, y) #开始检查谋点是否在关闭列表中
@close_list.each do |point|
return true if point[0] == x and point[1] == y
end
return false
end #结束检查谋点是否在关闭列表中
#--------------------------------------------------------------------------
end
$find_path = Find_Path.new
复制代码
作者:
Wind2010
时间:
2012-8-19 22:19
ORZ或者求个不太卡的寻路脚本,只需要能够找到应该前进的方向就可以了……
欢迎光临 Project1 (https://rpg.blue/)
Powered by Discuz! X5.0