幻想森林

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 5571|回复: 12

[06.3.6更新]锥形视野系统,带有障碍判断

[复制链接]

50

主题

994

帖子

6699

积分

管理员

爱干啥干啥!

Rank: 9Rank: 9Rank: 9

积分
6699
发表于 2005-10-25 00:42:08 | 显示全部楼层 |阅读模式
[更新]2.0
感谢盗帅冬瓜的提醒,所以尝试重新安排了一下判断的方式。
并且改了设置视野的方式,觉得应该更自由了,具体方法请下载最后的范例工程,有说明。

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

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

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

使用方法在样本工程里面说明,下面是关键脚本[ViewRange 2.0]
  1. #==============================================================================
  2. # ☆★☆ 锥形视野 ☆★☆
  3. #------------------------------------------------------------------------------
  4. # - FantasyDR
  5. # - 2006.3.6
  6. #------------------------------------------------------------------------------
  7. # MSN: [email]FantasyDR_SJL@hotmail.com[/email]
  8. #------------------------------------------------------------------------------
  9. # Note:
  10. #   参考范例工程里面的说明,或者发e-mail询问
  11. #   或者前往[url]http://bbs.rpgchina.com[/url]发帖询问
  12. #------------------------------------------------------------------------------
  13. # 修改了设置方式,提高搜索效率(2006.3.6)
  14. # 第一版(2005.10.25)
  15. #==============================================================================
  16. #==============================================================================
  17. # ■ Table
  18. #------------------------------------------------------------------------------
  19. #  加入fill方法
  20. #==============================================================================
  21. class Table
  22.   def fill(c)
  23.     for y in 0..self.ysize
  24.       for x in 0..self.xsize
  25.         self[x,y] = c
  26.       end
  27.     end
  28.   end
  29. end
  30. #==============================================================================
  31. # ■ Spriteset_Map
  32. #------------------------------------------------------------------------------
  33. #    重载地图显示
  34. #==============================================================================
  35. class Spriteset_Map
  36.   attr_reader:tilemap
  37.   alias :fdr_ViewRange_Spriteset_Map_initialize :initialize
  38.   def initialize
  39.     fdr_ViewRange_Spriteset_Map_initialize
  40.     # 设置地图闪烁列表
  41.     @tilemap.flash_data=Table.new(@tilemap.map_data.xsize,@tilemap.map_data.ysize)
  42.   end  
  43. end
  44. #==============================================================================
  45. # ■ Scene_Map
  46. #------------------------------------------------------------------------------
  47. #    重载地图场景
  48. #==============================================================================
  49. class Scene_Map
  50.   alias :fdr_ViewRange_Scene_Map_update :update
  51.   attr_reader:spriteset
  52.   def update
  53.     @spriteset.tilemap.flash_data.fill(0)
  54.     fdr_ViewRange_Scene_Map_update
  55.   end
  56. end
  57. #==============================================================================
  58. # ■ Game_Event
  59. #------------------------------------------------------------------------------
  60. #  重载事件的类
  61. #==============================================================================
  62. class Game_Event < Game_Character
  63.   alias :fdr_ViewRange_Game_Event_initialize :initialize
  64.   alias :fdr_ViewRange_Game_Event_update :update
  65.   alias :fdr_ViewRange_Game_Event_refresh :refresh
  66.   #--------------------------------------------------------------------------
  67.   # 敌人朝向是2/4/6/8中的一个。
  68.   #          下左右上
  69.   # 建立Hash表,表示方向变量:
  70.   DX_lib ={2=>0,4=>-1,6=>1,8=>0}
  71.   DY_lib ={2=>1,4=>0,6=>0,8=>-1}
  72.   #--------------------------------------------------------------------------
  73.   attr_reader :switch_no  #控制开关号
  74.   attr_reader :deep       #视野深度
  75.   attr_reader :test_block #是否检测障碍
  76.   attr_reader :is_always  #是否一直跟随
  77.   attr_reader :show_grid  #是否显示范围
  78.   attr_accessor:flash_color #闪烁颜色
  79.   #--------------------------------------------------------------------------
  80.   # ●初始化
  81.   #--------------------------------------------------------------------------
  82.   def initialize(map_id, event)
  83.     fdr_ViewRange_Game_Event_initialize(map_id, event)
  84.     # 闪烁颜色
  85.     @flash_color=0xf0
  86.     @switch_no = 0
  87.     @deep = 4
  88.     @is_always = true
  89.     @test_block = true
  90.     @show_grid = true
  91.   end
  92.   #--------------------------------------------------------------------------
  93.   # ●初始化
  94.   #--------------------------------------------------------------------------
  95.   def refresh
  96.     fdr_ViewRange_Game_Event_refresh
  97.     return if @list == nil
  98.     for i in 0...@list.size
  99.       if @list[i].code == 108 and @list[i].parameters == ["FDR View Range"]
  100.         @switch_no = @list[i+1].parameters[0].split[1].to_i
  101.         break if @switch_no == 0
  102.         @deep = @list[i+2].parameters[0].split[1].to_i
  103.         @test_block = (@list[i+3].parameters[0].split[1].upcase == "TRUE")
  104.         @is_always = (@list[i+4].parameters[0].split[1].upcase == "TRUE")
  105.         @show_grid = (@list[i+5].parameters[0].split[1].upcase == "TRUE")
  106.         break
  107.       end
  108.     end
  109.   end
  110.   #--------------------------------------------------------------------------
  111.   # ●画面更新
  112.   #--------------------------------------------------------------------------
  113.   def update
  114.     fdr_ViewRange_Game_Event_update
  115.     self.test_view
  116.   end
  117.   #--------------------------------------------------------------------------
  118.   # ●判断是否被遮挡
  119.   # 参数:原点、障碍点、目标点、宽度
  120.   #--------------------------------------------------------------------------
  121.   def be_covered(sx,sy, cx,cy, px,py, width, x_fix,y_fix)
  122.     #坐标转换
  123.     sx = sx * width/1.0
  124.     sy = sy * width/1.0
  125.     cx = cx * width/1.0
  126.     cy = cy * width/1.0
  127.     px = px * width/1.0
  128.     py = py * width/1.0
  129.     #转换两个遮挡点
  130.     cx_a = cx - width*x_fix/2.0
  131.     cx_b = cx + width*x_fix/2.0
  132.     cy_a = cy - width*y_fix/2.0
  133.     cy_b = cy + width*y_fix/2.0
  134.     # 求斜率
  135.     kp = (py-sy)/(px-sx)  
  136.     if x_fix != 0 #横向遮挡
  137.       if px == sx #在垂直方向
  138.         tx = 0
  139.       else
  140.         tx = cy/kp
  141.       end
  142.       if (cy-sy).abs<(py-sy).abs and tx>=cx_a and tx<=cx_b
  143.         return true #被挡住
  144.       end
  145.     else #纵向遮挡,面向水平方向
  146.       ty = cx*kp
  147.       if (cx-sx).abs<(px-sx).abs and ty>=cy_a and ty<=cy_b
  148.         return true #被挡住
  149.       end
  150.     end
  151.     return false #没有被挡住
  152.   end
  153.   #--------------------------------------------------------------------------
  154.   # ● 保存数据
  155.   # x,y:
  156.   #   数据位置
  157.   #--------------------------------------------------------------------------
  158.   def pack(x,y)
  159.     if x == $game_player.x and  y == $game_player.y
  160.       $game_switches[@switch_no] = true
  161.     end
  162.     if self.passable?(x,y,0)
  163.       @view[@vp,0] = x
  164.       @view[@vp,1] = y
  165.       @vp += 1
  166.     else
  167.       @rock[@rp,0] = x
  168.       @rock[@rp,1] = y
  169.       @rp += 1
  170.     end
  171.   end
  172.   #--------------------------------------------------------------------------
  173.   # ● 移动类型 : 敌人视界判断
  174.   # @deep:
  175.   #   视野深度
  176.   # @test_block:
  177.   #   是否检测障碍
  178.   #--------------------------------------------------------------------------
  179.   def test_view
  180.     return if @switch_no == 0 or !$scene.is_a?(Scene_Map)
  181.     start = $game_switches[@switch_no]
  182.     # 求得与主角座标的差值
  183.     sx = @x - $game_player.x
  184.     sy = @y - $game_player.y
  185.     # 判定是否一直跟踪
  186.     if @is_always and $game_switches[@switch_no]
  187.       if (sx**2 + sy**2)>((@deep+2)**2)
  188.         $game_switches[@switch_no] = false
  189.       end
  190.     else
  191.       # 否则重置开关
  192.       $game_switches[@switch_no] = false
  193.     end
  194.     # 地图闪烁数组
  195.     flash = $scene.spriteset.tilemap.flash_data
  196.     # 求得方向变量参数
  197.     dx=DX_lib[@direction]
  198.     dy=DY_lib[@direction]
  199.     @view = Table.new(flash.xsize*flash.ysize,2)
  200.     @rock = Table.new(flash.xsize*flash.ysize,2)
  201.     @rp = 0
  202.     @vp = 0
  203.     # 站在NPC身旁会被发现
  204.     # 如果不需要此效果,去掉下面的内容
  205.     #=================================
  206.     if dy != 0 #纵向视野
  207.       pack(@x+1,@y)
  208.       pack(@x-1,@y)
  209.     else
  210.       pack(@x,@y+1)
  211.       pack(@x,@y-1)
  212.     end
  213.     #=================================
  214.     # 扫描所有视野上的点
  215.     for i in 1..@deep
  216.       for j in -i..i
  217.         if dy != 0
  218.           cy = @y + dy*i
  219.           cx = @x + j
  220.         else
  221.           cx = @x + dx*i
  222.           cy = @y + j
  223.         end
  224.         pack(cx,cy)
  225.       end
  226.     end
  227.     # 判断障碍
  228.     for i in 0..@vp-1
  229.       can_see = true
  230.       for j in 0..@rp-1
  231.         if @test_block and self.be_covered(0,0,
  232.                    @rock[j,0]-@x,@rock[j,1]-@y,
  233.                    @view[i,0]-@x,@view[i,1]-@y,
  234.                    32,dy.abs,dx.abs)
  235.           can_see = false
  236.           break
  237.         end
  238.       end
  239.       if can_see and @show_grid
  240.         flash[@view[i,0],@view[i,1]] = @flash_color
  241.       end
  242.     end
  243.     #探测玩家有没有被遮挡
  244.     if $game_switches[@switch_no] and @test_block and !(start and @is_always)
  245.       for j in 0..@rp-1
  246.         if (@rock[j,0] != $game_player.x or @rock[j,0] != $game_player.y) and
  247.           self.be_covered(0,0,
  248.               @rock[j,0]-@x,@rock[j,1]-@y,
  249.               $game_player.x-@x,$game_player.y-@y,
  250.               32,dy.abs,dx.abs)
  251.           $game_switches[@switch_no] = false
  252.           break
  253.         end
  254.       end
  255.     end
  256.     unless start == $game_switches[@switch_no]
  257.       $game_map.need_refresh = true
  258.     end
  259.   end
  260. end
复制代码

本帖子中包含更多资源

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

x

“放下屠刀,立地成佛” 故应先杀生,然后再成佛。

(\\_/) (-_-) ()+() this is bunny priest.
回复

使用道具 举报

5

主题

61

帖子

1285

积分

⑥精研

积分
1285
发表于 2005-10-25 09:38:39 | 显示全部楼层
好东西,多谢.
回复 支持 反对

使用道具 举报

5

主题

12

帖子

1329

积分

⑥精研

积分
1329
发表于 2005-10-25 10:17:10 | 显示全部楼层
自从66换论坛后一直没成功进入过,

视野的问题一直困扰我

多谢大大分享~
回复 支持 反对

使用道具 举报

14

主题

375

帖子

5760

积分

⑦老手

科学大迫力研究所

积分
5760
发表于 2005-10-25 12:07:14 | 显示全部楼层
恩,看到了战棋rpg的希望......
继续荒野与渡鸟的那场梦......
回复 支持 反对

使用道具 举报

50

主题

994

帖子

6699

积分

管理员

爱干啥干啥!

Rank: 9Rank: 9Rank: 9

积分
6699
 楼主| 发表于 2005-10-25 17:15:18 | 显示全部楼层
汗……这个不是战棋的说……
离战棋的需要还有一段距离*_*b

“放下屠刀,立地成佛” 故应先杀生,然后再成佛。

(\\_/) (-_-) ()+() this is bunny priest.
回复 支持 反对

使用道具 举报

9

主题

94

帖子

2622

积分

⑥精研

积分
2622
发表于 2005-10-25 21:32:13 | 显示全部楼层
强!!无敌了~~~~

不知道哪位大人也能好心的完善一下1024*768显示的脚本~~~~(哭~~~)
回复 支持 反对

使用道具 举报

18

主题

230

帖子

3055

积分

⑥精研

积分
3055
QQ
发表于 2005-10-26 20:39:13 | 显示全部楼层
下面是引用appleseed于2005-10-25 12:07发表的:
恩,看到了战棋rpg的希望......
你还想SRPG啊-_,-|||
回复 支持 反对

使用道具 举报

50

主题

994

帖子

6699

积分

管理员

爱干啥干啥!

Rank: 9Rank: 9Rank: 9

积分
6699
 楼主| 发表于 2005-10-26 20:46:28 | 显示全部楼层
不是有个SRPG制作大师来着么……?

“放下屠刀,立地成佛” 故应先杀生,然后再成佛。

(\\_/) (-_-) ()+() this is bunny priest.
回复 支持 反对

使用道具 举报

50

主题

994

帖子

6699

积分

管理员

爱干啥干啥!

Rank: 9Rank: 9Rank: 9

积分
6699
 楼主| 发表于 2006-3-6 20:54:19 | 显示全部楼层
更新了,自己顶一下下。

“放下屠刀,立地成佛” 故应先杀生,然后再成佛。

(\\_/) (-_-) ()+() this is bunny priest.
回复 支持 反对

使用道具 举报

91

主题

3188

帖子

83986万

积分

荣誉群

传说中的Bunny大神~!

积分
839861514
QQ
发表于 2006-3-6 20:59:03 | 显示全部楼层
好东西!狂顶! [s:1]
其他所有的Bunny神都素我的部下XD~ 小教程范例收集 Orz感谢邪恶萝卜联盟!!!(原因自己去猜)
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|幻想森林

GMT+8, 2024-3-29 04:06 , Processed in 0.026049 second(s), 22 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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