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

Project1

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

[原创发布] [发布]锥形视野系统,带有障碍判断

 关闭 [复制链接]
头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
跳转到指定楼层
1
发表于 2005-10-25 09:04:08 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式

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

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

x


这个想法来源于不久前一位朋友发的脚本,不过好像换论坛后不见了。有人问能不能加入障碍判断,于是研究了下,目前实现了这个功能,测试了下还好用。

这个系统不是以人为中心,半径某个距离的视野,而是和人物面向方向有关的一个锥形视野,并且可以设定是否被障碍遮挡,可以设定是否显示视野范围。

喜欢的朋友可以拿去研究使用。

----这里下载样本工程----

使用方法在样本工程里面说明,下面是关键脚本[ViewRange]

  1. #==============================================================================
  2. # 作者: FantasyDR
  3. #
  4. # 版本: v1.0
  5. #
  6. # 2005.10.25
  7. #==============================================================================

  8. #==============================================================================
  9. # ■ Table
  10. #------------------------------------------------------------------------------
  11. #  加入fill方法
  12. #==============================================================================
  13. class Table
  14.   def fill(c)
  15.     for y in 0..self.ysize
  16.       for x in 0..self.xsize
  17.          self[x,y] = c
  18.       end
  19.     end
  20.   end
  21. end

  22. #==============================================================================
  23. # ■ Spriteset_Map
  24. #------------------------------------------------------------------------------
  25. #    重载地图显示
  26. #==============================================================================
  27. class Spriteset_Map
  28.   attr_reader:tilemap
  29.   alias :original_ini :initialize
  30.   def initialize
  31.     original_ini
  32.     # 设置地图闪烁列表
  33.     @tilemap.flash_data=Table.new(@tilemap.map_data.xsize,@tilemap.map_data.ysize)
  34.   end  
  35. end
  36. #==============================================================================
  37. # ■ Scene_Map
  38. #------------------------------------------------------------------------------
  39. #    重载地图场景
  40. #==============================================================================
  41. class Scene_Map
  42.   attr_reader:spriteset
  43. end
  44. #==============================================================================
  45. # ■ Game_Event
  46. #------------------------------------------------------------------------------
  47. #  重载事件的类
  48. #==============================================================================
  49. class Game_Event < Game_Character
  50. alias :origin_initialize :initialize
  51. alias :origin_update :update

  52. attr_reader :switch_no  #控制开关号
  53. attr_reader :deep       #视野深度
  54. attr_reader :test_block #是否检测障碍
  55. attr_reader :is_always  #是否一直跟随
  56. attr_reader :show_grid  #是否显示范围
  57. attr_accessor:flash_color #闪烁颜色
  58. #--------------------------------------------------------------------------
  59. # ●初始化
  60. #--------------------------------------------------------------------------
  61. def initialize(map_id, event)
  62.    origin_initialize(map_id, event)
  63.    # 敌人朝向是2/4/6/8中的一个。
  64.    #          下左右上
  65.    # 建立Hash表,表示方向变量:
  66.    @dx_lib ={2=>0,4=>-1,6=>1,8=>0}
  67.    @dy_lib ={2=>1,4=>0,6=>0,8=>-1}
  68.    # 闪烁颜色
  69.    @flash_color=0xf0
  70. end
  71. #--------------------------------------------------------------------------
  72. # ●画面更新
  73. #--------------------------------------------------------------------------
  74. def update
  75.    if moving? or @original_direction != @direction
  76.       $scene.spriteset.tilemap.flash_data.fill(0)
  77.       @original_direction = @direction
  78.    end
  79.    self.test_view
  80.    origin_update
  81. end
  82. #--------------------------------------------------------------------------
  83. # ●判断是否被遮挡
  84. # 参数:原点、障碍点、目标点、宽度
  85. #--------------------------------------------------------------------------
  86. def be_covered(sx,sy, cx,cy, px,py, width, x_fix,y_fix)
  87.   #坐标转换
  88.   sx = sx * width/1.0
  89.   sy = sy * width/1.0
  90.   cx = cx * width/1.0
  91.   cy = cy * width/1.0
  92.   px = px * width/1.0
  93.   py = py * width/1.0
  94.   #转换两个遮挡点
  95.   cx_a = cx - width*x_fix/2.0
  96.   cx_b = cx + width*x_fix/2.0
  97.   cy_a = cy - width*y_fix/2.0
  98.   cy_b = cy + width*y_fix/2.0
  99.   
  100.   
  101.   # 求斜率
  102.   kp = (py-sy)/(px-sx)  
  103.   if x_fix != 0 #横向遮挡
  104.     if px == sx #在垂直方向
  105.       tx = 0
  106.     else
  107.       tx = cy/kp
  108.     end
  109.     if (cy-sy).abs<(py-sy).abs and tx>=cx_a and tx<=cx_b
  110.       return true #被挡住
  111.     end
  112.   else #纵向遮挡,面向水平方向
  113.     ty = cx*kp
  114.     if (cx-sx).abs<(px-sx).abs and ty>=cy_a and ty<=cy_b
  115.       return true #被挡住
  116.     end
  117.   end
  118.   return false #没有被挡住
  119. end

  120. #--------------------------------------------------------------------------
  121. # ● 保存数据
  122. # x,y:
  123. #   数据位置
  124. #--------------------------------------------------------------------------
  125. def pack(x,y,test)
  126.    if x == $game_player.x and  y == $game_player.y
  127.        $game_switches[@switch_no] = true
  128.    end
  129.    if self.passable?(x,y,0)
  130.      @view[@vp,0] = x
  131.      @view[@vp,1] = y
  132.      @vp += 1
  133.    else
  134.      @rock[@rp,0] = x
  135.      @rock[@rp,1] = y
  136.      @rp += 1
  137.    end
  138. end
  139. #--------------------------------------------------------------------------
  140. # ● 移动类型 : 敌人视界判断
  141. # @deep:
  142. #   视野深度
  143. # @test_block:
  144. #   是否检测障碍
  145. #--------------------------------------------------------------------------
  146. def test_view
  147.   return if @deep == nil
  148.   flash = $scene.spriteset.tilemap.flash_data
  149.   # 求得方向变量参数
  150.   dx=@dx_lib[@direction]
  151.   dy=@dy_lib[@direction]

  152.   # 求得与主角座标的差值
  153.   sx = @x - $game_player.x
  154.   sy = @y - $game_player.y
  155.   
  156.   # 判定是否一直跟踪
  157.   if @is_always and $game_switches[@switch_no]
  158.     if (sx**2 + sy**2)>((@deep+1)**2)
  159.      $game_switches[@switch_no]=false
  160.     end
  161.   else
  162.     $game_switches[@switch_no]=false
  163.   end
  164.   
  165.   @view = Table.new(flash.xsize*flash.ysize,2)
  166.   @rock = Table.new(flash.xsize*flash.ysize,2)
  167.   @rp = 0
  168.   @vp = 0
  169.   # 设置周围视野
  170.   if dy != 0 #纵向视野
  171.    pack(@x+1,@y,false)
  172.    pack(@x-1,@y,false)
  173.   else
  174.    pack(@x,@y+1,false)
  175.    pack(@x,@y-1,false)
  176.   end
  177.   # 扫描所有视野上的点
  178.   for i in 1..@deep
  179.    for j in -i..i
  180.      if dy != 0
  181.       cy = @y + dy*i
  182.       cx = @x + j
  183.      else
  184.       cx = @x + dx*i
  185.       cy = @y + j
  186.      end
  187.      pack(cx,cy,true)
  188.    end
  189.   end
  190.   
  191.   # 判断障碍
  192.   for i in 0..@vp-1
  193.     can_see = true
  194.     for j in 0..@rp-1
  195.       if @test_block and self.be_covered(0,0, @rock[j,0]-@x,@rock[j,1]-@y,@view[i,0]-@x,@view[i,1]-@y,32,dy.abs,dx.abs)
  196.         can_see = false
  197.         break
  198.       end
  199.     end
  200.     flash[@view[i,0],@view[i,1]] = @flash_color if can_see and @show_grid
  201.   end
  202.   #探测玩家有没有被遮挡
  203.   if $game_switches[@switch_no] and @test_block
  204.    for j in 0..@rp-1
  205.     if (@rock[j,0] != $game_player.x or @rock[j,0] != $game_player.y) and
  206.        self.be_covered(0,0, @rock[j,0]-@x,@rock[j,1]-@y,\
  207.        $game_player.x-@x,$game_player.y-@y,32,dy.abs,dx.abs)
  208.         $game_switches[@switch_no]=false
  209.         break
  210.     end
  211.    end
  212.   end
  213. end
  214. #--------------------------------------------------------------------------
  215. # ●移动类型
  216. #--------------------------------------------------------------------------
  217. def em_view(switch_no,deep=4,test_block=true,is_always=true,show_grid=true)
  218.   @switch_no = switch_no
  219.   @deep = deep
  220.   @test_block = test_block
  221.   @is_always = is_always
  222.   @show_grid = show_grid
  223.   # 根据$game_switches[@switch_no]移动
  224.   if $game_switches[@switch_no]
  225.     # 被发现的情况,跟随主角
  226.     move_toward_player
  227.   else
  228.     # 没有被发现的情况,随机转向
  229.     turn_random
  230.   end
  231. end

  232. end
复制代码


              [本贴由 柳柳 于 2005-10-28 7:26:49 最后编辑]
签名被屏蔽
头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
2
 楼主| 发表于 2005-10-25 09:04:08 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式

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

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

x


这个想法来源于不久前一位朋友发的脚本,不过好像换论坛后不见了。有人问能不能加入障碍判断,于是研究了下,目前实现了这个功能,测试了下还好用。

这个系统不是以人为中心,半径某个距离的视野,而是和人物面向方向有关的一个锥形视野,并且可以设定是否被障碍遮挡,可以设定是否显示视野范围。

喜欢的朋友可以拿去研究使用。

----这里下载样本工程----

使用方法在样本工程里面说明,下面是关键脚本[ViewRange]

  1. #==============================================================================
  2. # 作者: FantasyDR
  3. #
  4. # 版本: v1.0
  5. #
  6. # 2005.10.25
  7. #==============================================================================

  8. #==============================================================================
  9. # ■ Table
  10. #------------------------------------------------------------------------------
  11. #  加入fill方法
  12. #==============================================================================
  13. class Table
  14.   def fill(c)
  15.     for y in 0..self.ysize
  16.       for x in 0..self.xsize
  17.          self[x,y] = c
  18.       end
  19.     end
  20.   end
  21. end

  22. #==============================================================================
  23. # ■ Spriteset_Map
  24. #------------------------------------------------------------------------------
  25. #    重载地图显示
  26. #==============================================================================
  27. class Spriteset_Map
  28.   attr_reader:tilemap
  29.   alias :original_ini :initialize
  30.   def initialize
  31.     original_ini
  32.     # 设置地图闪烁列表
  33.     @tilemap.flash_data=Table.new(@tilemap.map_data.xsize,@tilemap.map_data.ysize)
  34.   end  
  35. end
  36. #==============================================================================
  37. # ■ Scene_Map
  38. #------------------------------------------------------------------------------
  39. #    重载地图场景
  40. #==============================================================================
  41. class Scene_Map
  42.   attr_reader:spriteset
  43. end
  44. #==============================================================================
  45. # ■ Game_Event
  46. #------------------------------------------------------------------------------
  47. #  重载事件的类
  48. #==============================================================================
  49. class Game_Event < Game_Character
  50. alias :origin_initialize :initialize
  51. alias :origin_update :update

  52. attr_reader :switch_no  #控制开关号
  53. attr_reader :deep       #视野深度
  54. attr_reader :test_block #是否检测障碍
  55. attr_reader :is_always  #是否一直跟随
  56. attr_reader :show_grid  #是否显示范围
  57. attr_accessor:flash_color #闪烁颜色
  58. #--------------------------------------------------------------------------
  59. # ●初始化
  60. #--------------------------------------------------------------------------
  61. def initialize(map_id, event)
  62.    origin_initialize(map_id, event)
  63.    # 敌人朝向是2/4/6/8中的一个。
  64.    #          下左右上
  65.    # 建立Hash表,表示方向变量:
  66.    @dx_lib ={2=>0,4=>-1,6=>1,8=>0}
  67.    @dy_lib ={2=>1,4=>0,6=>0,8=>-1}
  68.    # 闪烁颜色
  69.    @flash_color=0xf0
  70. end
  71. #--------------------------------------------------------------------------
  72. # ●画面更新
  73. #--------------------------------------------------------------------------
  74. def update
  75.    if moving? or @original_direction != @direction
  76.       $scene.spriteset.tilemap.flash_data.fill(0)
  77.       @original_direction = @direction
  78.    end
  79.    self.test_view
  80.    origin_update
  81. end
  82. #--------------------------------------------------------------------------
  83. # ●判断是否被遮挡
  84. # 参数:原点、障碍点、目标点、宽度
  85. #--------------------------------------------------------------------------
  86. def be_covered(sx,sy, cx,cy, px,py, width, x_fix,y_fix)
  87.   #坐标转换
  88.   sx = sx * width/1.0
  89.   sy = sy * width/1.0
  90.   cx = cx * width/1.0
  91.   cy = cy * width/1.0
  92.   px = px * width/1.0
  93.   py = py * width/1.0
  94.   #转换两个遮挡点
  95.   cx_a = cx - width*x_fix/2.0
  96.   cx_b = cx + width*x_fix/2.0
  97.   cy_a = cy - width*y_fix/2.0
  98.   cy_b = cy + width*y_fix/2.0
  99.   
  100.   
  101.   # 求斜率
  102.   kp = (py-sy)/(px-sx)  
  103.   if x_fix != 0 #横向遮挡
  104.     if px == sx #在垂直方向
  105.       tx = 0
  106.     else
  107.       tx = cy/kp
  108.     end
  109.     if (cy-sy).abs<(py-sy).abs and tx>=cx_a and tx<=cx_b
  110.       return true #被挡住
  111.     end
  112.   else #纵向遮挡,面向水平方向
  113.     ty = cx*kp
  114.     if (cx-sx).abs<(px-sx).abs and ty>=cy_a and ty<=cy_b
  115.       return true #被挡住
  116.     end
  117.   end
  118.   return false #没有被挡住
  119. end

  120. #--------------------------------------------------------------------------
  121. # ● 保存数据
  122. # x,y:
  123. #   数据位置
  124. #--------------------------------------------------------------------------
  125. def pack(x,y,test)
  126.    if x == $game_player.x and  y == $game_player.y
  127.        $game_switches[@switch_no] = true
  128.    end
  129.    if self.passable?(x,y,0)
  130.      @view[@vp,0] = x
  131.      @view[@vp,1] = y
  132.      @vp += 1
  133.    else
  134.      @rock[@rp,0] = x
  135.      @rock[@rp,1] = y
  136.      @rp += 1
  137.    end
  138. end
  139. #--------------------------------------------------------------------------
  140. # ● 移动类型 : 敌人视界判断
  141. # @deep:
  142. #   视野深度
  143. # @test_block:
  144. #   是否检测障碍
  145. #--------------------------------------------------------------------------
  146. def test_view
  147.   return if @deep == nil
  148.   flash = $scene.spriteset.tilemap.flash_data
  149.   # 求得方向变量参数
  150.   dx=@dx_lib[@direction]
  151.   dy=@dy_lib[@direction]

  152.   # 求得与主角座标的差值
  153.   sx = @x - $game_player.x
  154.   sy = @y - $game_player.y
  155.   
  156.   # 判定是否一直跟踪
  157.   if @is_always and $game_switches[@switch_no]
  158.     if (sx**2 + sy**2)>((@deep+1)**2)
  159.      $game_switches[@switch_no]=false
  160.     end
  161.   else
  162.     $game_switches[@switch_no]=false
  163.   end
  164.   
  165.   @view = Table.new(flash.xsize*flash.ysize,2)
  166.   @rock = Table.new(flash.xsize*flash.ysize,2)
  167.   @rp = 0
  168.   @vp = 0
  169.   # 设置周围视野
  170.   if dy != 0 #纵向视野
  171.    pack(@x+1,@y,false)
  172.    pack(@x-1,@y,false)
  173.   else
  174.    pack(@x,@y+1,false)
  175.    pack(@x,@y-1,false)
  176.   end
  177.   # 扫描所有视野上的点
  178.   for i in 1..@deep
  179.    for j in -i..i
  180.      if dy != 0
  181.       cy = @y + dy*i
  182.       cx = @x + j
  183.      else
  184.       cx = @x + dx*i
  185.       cy = @y + j
  186.      end
  187.      pack(cx,cy,true)
  188.    end
  189.   end
  190.   
  191.   # 判断障碍
  192.   for i in 0..@vp-1
  193.     can_see = true
  194.     for j in 0..@rp-1
  195.       if @test_block and self.be_covered(0,0, @rock[j,0]-@x,@rock[j,1]-@y,@view[i,0]-@x,@view[i,1]-@y,32,dy.abs,dx.abs)
  196.         can_see = false
  197.         break
  198.       end
  199.     end
  200.     flash[@view[i,0],@view[i,1]] = @flash_color if can_see and @show_grid
  201.   end
  202.   #探测玩家有没有被遮挡
  203.   if $game_switches[@switch_no] and @test_block
  204.    for j in 0..@rp-1
  205.     if (@rock[j,0] != $game_player.x or @rock[j,0] != $game_player.y) and
  206.        self.be_covered(0,0, @rock[j,0]-@x,@rock[j,1]-@y,\
  207.        $game_player.x-@x,$game_player.y-@y,32,dy.abs,dx.abs)
  208.         $game_switches[@switch_no]=false
  209.         break
  210.     end
  211.    end
  212.   end
  213. end
  214. #--------------------------------------------------------------------------
  215. # ●移动类型
  216. #--------------------------------------------------------------------------
  217. def em_view(switch_no,deep=4,test_block=true,is_always=true,show_grid=true)
  218.   @switch_no = switch_no
  219.   @deep = deep
  220.   @test_block = test_block
  221.   @is_always = is_always
  222.   @show_grid = show_grid
  223.   # 根据$game_switches[@switch_no]移动
  224.   if $game_switches[@switch_no]
  225.     # 被发现的情况,跟随主角
  226.     move_toward_player
  227.   else
  228.     # 没有被发现的情况,随机转向
  229.     turn_random
  230.   end
  231. end

  232. end
复制代码


              [本贴由 柳柳 于 2005-10-28 7:26:49 最后编辑]
签名被屏蔽
头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
3
 楼主| 发表于 2005-10-25 19:49:14 | 显示全部楼层
更换1.01的rxproj就可以,我还以为大家都升级了的说-_-b

汗。
签名被屏蔽
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
4
 楼主| 发表于 2005-10-25 20:05:09 | 显示全部楼层
以下引用缺牙de兔子于2005-10-25 10:09:05的发言:

OH YE 是关于战棋的资料 我喜欢 还有没有??


这个不是为SLG做的脚本。
如果你要开发SLG,可以看看关于Tilemap的flash_data属性,这个属性可以让地图上面块按照要求闪烁,其实是为SLG的开发预留的^_^

其他方面么,还得自己动手了。
签名被屏蔽
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
5
 楼主| 发表于 2005-10-26 01:45:24 | 显示全部楼层
这个,不同的人有不同的需要。发现之后要做什么动作,是根据NPC所处的游戏具体设定来做,我这里只是随便弄了一个向主角靠近。

如果做发现就跟随的效果,可以把is_always为true,这样扫描会根据距离来判断,不会出现自己走着走着就跟丢了的情况。例子游戏里面两个人就是这里不相同……

至于其他需要,不可能一一满足。需要的自己来做相应的工作吧~
签名被屏蔽
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
6
 楼主| 发表于 2005-10-26 22:08:46 | 显示全部楼层
以下引用缺牙de兔子于2005-10-26 2:22:09的发言:

行 还是可以要的


……那,那我还谢谢楼上的赏脸了^_^


PS:如果需要让这个人不要进行视野搜索,需要把这个事件的@deep属性设置为nil
签名被屏蔽
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
7
 楼主| 发表于 2005-11-3 01:50:05 | 显示全部楼层
楼上的问题:使用任何一个Game.rxproj覆盖原来的就可以打开~~

小歌的问题:
1、脚本控制已经在事件里面定义的变量?
使用
$game_variables[变量号码]=变量值
来控制。

2、独立开关的控制?(以前写的有错误,少了下面那个蓝色的语句)
key = [$game_map.map_id, @event_id, 开关名字比如"A"]
$game_self_switches[key] = ture或者false
$game_map.need_refresh = true
签名被屏蔽
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
8
 楼主| 发表于 2005-11-12 21:02:53 | 显示全部楼层
似乎我在前面写过……得设置@deep = nil
签名被屏蔽
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2005-10-22
帖子
81
9
 楼主| 发表于 2005-11-12 23:17:42 | 显示全部楼层
因为视野的控制变量和事件页码无关的。
只要被打开就一直激活……

移动事件如果一直被激发,那么就一直有视野,所以必须也在移动事件里面控制视野消失。

确实有点麻烦……^_^bb当初设计的时候失误了一下。
签名被屏蔽
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

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

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

GMT+8, 2024-5-7 04:28

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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