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

Project1

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

[讨论] 用鼠标点击自寻路改成NPC追玩家

[复制链接]

Lv4.逐梦者

梦石
0
星屑
14048
在线时间
2070 小时
注册时间
2016-9-20
帖子
844
跳转到指定楼层
1
发表于 2023-10-28 22:45:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 ppspssss 于 2023-10-30 17:42 编辑

用芯☆淡茹水  的 〓 鼠标点击自寻路 〓 改成 NPC追 玩家(NPC追自己) , 但我不知是什么寻路算法来 ,如果知道的人能告诉一下我
只是用于实验,原来是宋乱贼狂的QQT探险游戏没有NPC寻路, 我就想找下有没寻路脚本,找到这个脚本,本来这个是带有鼠标功能,下列的是已去掉无鼠标功能

距离有限, 大慨两目标相距20格, 若有些复杂的距离再短就不能寻到
脚本经过改了只保留单独寻路,有兴趣的看,脚本中有些变量未列出来需自己进行声明
自己坐标是指$game_player.x和$game_player.y
寻路频率是每30帧进行一次, 过于频繁会无法应付而掉帧 , 因此会占用大量算力
除了追玩家想过如果在地图放置一些多个固定点进行寻路或许可以长距离移动 , 不过或许应该要找更好的解决方案

https://rpg.blue/thread-408715-1-1.html  脚本原贴地址
https://www.bilibili.com/video/B ... d2adeb1a2b4281add78  效果视频(NPC追自己
寻路
RUBY 代码复制
  1. class Game_Map
  2.   #--------------------------------------------------------------------------
  3.   def distance(x1, y1, x2, y2)
  4.     return delta_x(x1, x2).abs + delta_y(y1, y2).abs
  5.   end
  6.   #--------------------------------------------------------------------------
  7.   def loop_horizontal?
  8.     return false
  9.   end
  10.   #--------------------------------------------------------------------------
  11.   def loop_vertical?
  12.     return false
  13.   end
  14.   #--------------------------------------------------------------------------
  15.   def delta_x(x1, x2)
  16.     result = x1 - x2
  17.     if loop_horizontal? && result.abs > width / 2
  18.       result += result < 0 ? width : -width
  19.     end
  20.     return result
  21.   end
  22.   #--------------------------------------------------------------------------
  23.   def delta_y(y1, y2)
  24.     result = y1 - y2
  25.     if loop_vertical? && result.abs > height / 2
  26.       result += result < 0 ? height : -height
  27.     end
  28.     return result
  29.   end
  30. end #class
  31.  
  32.  
  33. class Game_Character
  34.  
  35.   alias xr_mv_initialize initialize
  36.   def initialize
  37.     xr_mv_initialize
  38.     @search_limit = 15
  39.   end
  40.   #--------------------------------------------------------------------------
  41.   def delta_x_from(x)
  42.     return $game_map.delta_x(@x, x)
  43.   end
  44.   #--------------------------------------------------------------------------
  45.   def delta_y_from(y)
  46.     return $game_map.delta_y(@y, y)
  47.   end
  48.   #--------------------------------------------------------------------------
  49.  
  50.  
  51.   def find_direction(x, y)
  52.  
  53.     $hi = $hi + 1
  54.     #貌似$hi是测试用
  55.    # pst"#{$hi}"
  56.  
  57.  
  58.     return 0 if @x == x && @y == y
  59.     goal_x = x; goal_y = y
  60.     map_width = $game_map.width
  61.     node_list = []; open_list = []; closed_list = []
  62.     start = {}; best = start
  63.     start[:parent] = nil; start[:x] = @x; start[:y] = @y; start[:g] = 0
  64.     #start[:xr] = $game_map.distance(start[:x], start[:y], goal_x, goal_y);
  65.     start[:xr] = $game_map.distance(@x, @y, goal_x, goal_y);
  66.     node_list.push(start)
  67.     open_list.push(start[:y] * map_width + start[:x])
  68.     t = 0 #t若大于1则可寻路到达目标,因此用来判断用
  69.     while node_list.size > 0
  70.  
  71.       best_index = 0
  72.       node_list.size.times do |i|
  73.         best_index = i if node_list[i][:xr] < node_list[best_index][:xr]
  74.       end
  75.       current = node_list[best_index]
  76.       x1 = current[:x]; y1 = current[:y]
  77.       pos1 = y1 * map_width + x1
  78.       g1 = current[:g]
  79.       node_list.delete(current)
  80.       open_list.delete(pos1)
  81.       closed_list << pos1
  82.       if current[:x] == goal_x && current[:y] == goal_y
  83.         #到达了目的地返回
  84.         #补充:t若大于1则可寻路到达目标,因此用来判断用
  85.         t += 1
  86.         best = current
  87.         #pst"no"
  88.         break
  89.       else
  90.         #注:会运行多次, 即使到达目标也要运行,因些不要返回,若返回只會运行一次
  91.         #return
  92.       end
  93.       next if g1 >= @search_limit
  94.       4.times do |j|
  95.         direction = 2 + j * 2
  96.         x2 = x1 + (direction == 6 ? 1 : direction == 4 ? -1 : 0)
  97.         y2 = y1 + (direction == 2 ? 1 : direction == 8 ? -1 : 0)
  98.         pos2 = y2 * map_width + x2
  99.         next if closed_list.include?(pos2) || !passable?(x1, y1, direction)
  100.         g2 = g1 + 1
  101.         index2 = open_list.index(pos2)
  102.         if index2 == nil || g2 < node_list[index2][:g]
  103.           if index2 != nil
  104.             neighbor = node_list[index2]
  105.           else
  106.             neighbor = {}; node_list << neighbor; open_list << pos2
  107.           end
  108.           neighbor[:parent] = current
  109.           neighbor[:x] = x2
  110.           neighbor[:y] = y2
  111.           neighbor[:g] = g2
  112.           neighbor[:xr] = g2 + $game_map.distance(x2, y2, goal_x, goal_y)
  113.           if !best || neighbor[:xr] - neighbor[:g] < best[:xr] - best[:g]
  114.              best = neighbor
  115.           end
  116.         end
  117.       end
  118.     end
  119.     node = best
  120.     while node[:parent] && node[:parent] != start
  121.       node = node[:parent]
  122.     end
  123.     delta_x1 = $game_map.delta_x(node[:x], start[:x])
  124.     delta_y1 = $game_map.delta_y(node[:y], start[:y])
  125.     if delta_y1 > 0
  126.       #以下像之前测试用的,无视,
  127.       #貌似当初始为下了泡后让怪不移动返回333,但后来好像不用
  128.       #因该游戏作者使用了泡泡以地形标志为七实际也是地形,站在泡泡上面就怪寻不到自己
  129.       #if @泡泡禁止通行方向 == "下"
  130.         #@对泡原地思考时间_v = 30
  131.         #return 0,333
  132.       #end #if
  133.       return 2 ,t
  134.       #返回方向以及是否移动,t若大于1则可寻路到达目标,因此用来判断用
  135.       #分别为:2下,4左,6右,8上
  136.       #(一次只移动一格)
  137.     elsif delta_x1 < 0
  138.       #if @泡泡禁止通行方向 == "左"
  139.         #@对泡原地思考时间_v = 30
  140.         #return 0,333
  141.       #end #if
  142.       return 4 ,t
  143.     elsif delta_x1 > 0
  144.      # if @泡泡禁止通行方向 == "右"
  145.         #@对泡原地思考时间_v = 30
  146.        # return 0,333
  147.      # end #if
  148.       return 6 ,t
  149.     elsif delta_y1 < 0
  150.      # if @泡泡禁止通行方向 == "上"
  151.         #@对泡原地思考时间_v = 30
  152.         #return 0,333
  153.      # end #if
  154.       return 8 ,t
  155.     end
  156.     delta_x2 = delta_x_from(goal_x)
  157.     delta_y2 = delta_y_from(goal_y)
  158.     if delta_x2.abs > delta_y2.abs
  159.  
  160.       return delta_x2 > 0 ? 4 : 6 ,t
  161.     elsif delta_y2 != 0
  162.  
  163.       return delta_y2 > 0 ? 8 : 2 ,t
  164.     end
  165.     return 0
  166.   end
  167.  
  168.  
  169. end #class Game_Character


□Game_Character怪物接近

RUBY 代码复制
  1. #==============================================================================
  2. # ■ Game_Character (分割定义 2)
  3. #------------------------------------------------------------------------------
  4. #  处理角色的类。本类作为 Game_Player 类与 Game_Event
  5. # 类的超级类使用。
  6. #==============================================================================
  7. $hi = 0 #测试用的变量,无视
  8. class Game_Character
  9.   #--------------------------------------------------------------------------
  10.   # ● 移动类型 : 接近
  11.   #--------------------------------------------------------------------------
  12.   def move_type_toward_player
  13.  
  14.  
  15.     # 求得与主角坐标的差
  16.     sx = @x - $game_player.x
  17.     sy = @y - $game_player.y
  18.     # 求得差的绝对值
  19.     abs_sx = sx > 0 ? sx : -sx
  20.     abs_sy = sy > 0 ? sy : -sy
  21.  
  22.     # 如果纵横共计离开 20 个元件
  23.  
  24.     if sx + sy >= 20 #只是人在怪上 (无效)
  25.       #pst "#{sx + sy}"
  26.       # 随机
  27.       #move_random
  28.       #return
  29.     end
  30.  
  31.     #return
  32.     if abs_sx + abs_sy <= 0
  33.     #pst "#{abs_sx + abs_sy}" #和主角相同位置 #不懂为什么是小於
  34.     return #(返回)
  35.     end
  36.     #if abs_sx + abs_sy >= 12
  37.       #move_random
  38.       #return
  39.     #end #if
  40.  
  41.     if (@原地思考时间_v > 0) and (abs_sx + abs_sy >= 12) #b 测试
  42.       @原地思考时间_v -= 1
  43.       move_random
  44.       return
  45.    #t elsif @对泡原地思考时间_v >0
  46.    elsif @原地思考时间_v >0
  47.    #  pst "#{@原地思考时间_v}"
  48.      @原地思考时间_v -= 1
  49.      #t @对泡原地思考时间_v -= 1
  50. #pst "#{@对泡原地思考时间_v},#{@泡泡禁止通行方向}"
  51. #t@泡泡禁止通行方向 == ""
  52.       return
  53.     end #if
  54.  
  55.  
  56.     # 随机 0~5 的分支
  57.     #case rand(6)
  58.     #when 0..3  # 接近主角
  59.       #move_toward_player
  60.       #$hi = $hi + 1
  61.     #pst"#{$hi}"
  62.       得到 = test_接近主角
  63.    # pst "#{得到}"
  64.  
  65.       if 得到 == "等待一段时间" #由于到达不到最终目标,
  66.         #等待30帧,再执行寻路,防止频繁寻路而造成运行效率低下
  67.         @原地思考时间_v = 30
  68.         #原地思考
  69.       end#
  70.  
  71.     #when 4  # 随机
  72.      # move_random
  73.     #when 5  # 前进一步
  74.      # move_forward
  75.     #end
  76.   end
  77.   #--------------------------------------------------------------------------
  78.   # ● 接近主角
  79.   #--------------------------------------------------------------------------
  80.   def test_接近主角
  81.     #让NPC靠近主角 (一次只移动一格)
  82.     #这里就是返回t的用处:得到是否行走,
  83.   direction, 得到是否行走  = find_direction($game_player.x, $game_player.y)
  84.   if 得到是否行走 == 0
  85.  
  86.     return "等待一段时间" #由于到达不到最终目标
  87.     #因此
  88. #  elsif 得到是否行走 == 333 #貌似测试用,没实际用途无视
  89.   #  pst "=3"
  90.   #  return "泡泡不可行走"
  91.   else
  92.     #不知为什么会返回这个? 又好像没有触发
  93.    #pst "#{得到是否行走}"
  94.   end #if
  95.  
  96.   if direction ==2
  97.    move_down
  98. elsif direction ==4
  99.   move_left
  100. elsif direction ==6
  101.    move_right
  102.    elsif direction ==8
  103.   move_up
  104.   end#if direction
  105.   end #def
  106.  
  107.   def move_toward_player
  108.     if $game_switches[9]#9号开关当2P隐藏了 #双人游戏,但没做双人寻路,无视
  109.       # 求得与主角的坐标差
  110.       sx = @x - $game_player.x
  111.       sy = @y - $game_player.y
  112.       # 求得差的绝对值
  113.       abs_sx  = sx.abs
  114.       abs_sy  = sy.abs
  115.     else
  116.       # 求得与主角的坐标差
  117.       sx = @x - $game_player.x
  118.       sy = @y - $game_player.y
  119.       sx2 = @x - $game_player2.x
  120.       sy2 = @y - $game_player2.y
  121.       # 求得差的绝对值
  122.       abs_sx  = sx.abs
  123.       abs_sy  = sy.abs
  124.       abs_sx2 = sx2.abs
  125.       abs_sy2 = sy2.abs
  126.       if (abs_sy2 + abs_sx2) < (abs_sy + abs_sx)
  127.         abs_sx = abs_sx2
  128.         abs_sy = abs_sy2
  129.         sx = sx2
  130.         sy = sy2
  131.       end
  132.     end
  133.  
  134.     # 坐标相等情况下
  135.     if sx == 0 and sy == 0
  136.       return
  137.     end
  138.     # 横距离与纵距离相等的情况下
  139.     if abs_sx == abs_sy
  140.       # 随机将边数增加 1
  141.       rand(2) == 0 ? abs_sx += 1 : abs_sy += 1
  142.     end
  143.     # 横侧距离长的情况下
  144.     if abs_sx > abs_sy
  145.       # 左右方向优先。向主角移动
  146.       sx > 0 ? move_left : move_right
  147.       if not moving? and sy != 0
  148.         sy > 0 ? move_up : move_down
  149.       end
  150.     # 竖侧距离长的情况下
  151.     else
  152.       # 上下方向优先。向主角移动
  153.       sy > 0 ? move_up : move_down
  154.       if not moving? and sx != 0
  155.         sx > 0 ? move_left : move_right
  156.       end
  157.     end
  158.   end
  159. end
内容仅供参考,
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

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

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

GMT+8, 2024-4-28 22:36

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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