- 注册时间
- 2004-5-22
- 最后登录
- 2023-11-24
管理员
爱干啥干啥!
- 积分
- 6699
|
[更新]2.0
感谢盗帅冬瓜的提醒,所以尝试重新安排了一下判断的方式。
并且改了设置视野的方式,觉得应该更自由了,具体方法请下载最后的范例工程,有说明。
================================================
这个想法来源于不久前一位朋友发的脚本,不过好像66换论坛后不见了。有人问能不能加入障碍判断,于是研究了下,目前实现了这个功能,测试了下还好用。
这个系统不是以人为中心,半径某个距离的视野,而是和人物面向方向有关的一个锥形视野,并且可以设定是否被障碍遮挡,可以设定是否显示视野范围。
喜欢的朋友可以拿去研究使用。
================================================
使用方法在样本工程里面说明,下面是关键脚本[ViewRange 2.0]- #==============================================================================
- # ☆★☆ 锥形视野 ☆★☆
- #------------------------------------------------------------------------------
- # - FantasyDR
- # - 2006.3.6
- #------------------------------------------------------------------------------
- # MSN: [email]FantasyDR_SJL@hotmail.com[/email]
- #------------------------------------------------------------------------------
- # Note:
- # 参考范例工程里面的说明,或者发e-mail询问
- # 或者前往[url]http://bbs.rpgchina.com[/url]发帖询问
- #------------------------------------------------------------------------------
- # 修改了设置方式,提高搜索效率(2006.3.6)
- # 第一版(2005.10.25)
- #==============================================================================
- #==============================================================================
- # ■ Table
- #------------------------------------------------------------------------------
- # 加入fill方法
- #==============================================================================
- class Table
- def fill(c)
- for y in 0..self.ysize
- for x in 0..self.xsize
- self[x,y] = c
- end
- end
- end
- end
- #==============================================================================
- # ■ Spriteset_Map
- #------------------------------------------------------------------------------
- # 重载地图显示
- #==============================================================================
- class Spriteset_Map
- attr_reader:tilemap
- alias :fdr_ViewRange_Spriteset_Map_initialize :initialize
- def initialize
- fdr_ViewRange_Spriteset_Map_initialize
- # 设置地图闪烁列表
- @tilemap.flash_data=Table.new(@tilemap.map_data.xsize,@tilemap.map_data.ysize)
- end
- end
- #==============================================================================
- # ■ Scene_Map
- #------------------------------------------------------------------------------
- # 重载地图场景
- #==============================================================================
- class Scene_Map
- alias :fdr_ViewRange_Scene_Map_update :update
- attr_reader:spriteset
- def update
- @spriteset.tilemap.flash_data.fill(0)
- fdr_ViewRange_Scene_Map_update
- end
- end
- #==============================================================================
- # ■ Game_Event
- #------------------------------------------------------------------------------
- # 重载事件的类
- #==============================================================================
- class Game_Event < Game_Character
- alias :fdr_ViewRange_Game_Event_initialize :initialize
- alias :fdr_ViewRange_Game_Event_update :update
- alias :fdr_ViewRange_Game_Event_refresh :refresh
- #--------------------------------------------------------------------------
- # 敌人朝向是2/4/6/8中的一个。
- # 下左右上
- # 建立Hash表,表示方向变量:
- DX_lib ={2=>0,4=>-1,6=>1,8=>0}
- DY_lib ={2=>1,4=>0,6=>0,8=>-1}
- #--------------------------------------------------------------------------
- attr_reader :switch_no #控制开关号
- attr_reader :deep #视野深度
- attr_reader :test_block #是否检测障碍
- attr_reader :is_always #是否一直跟随
- attr_reader :show_grid #是否显示范围
- attr_accessor:flash_color #闪烁颜色
- #--------------------------------------------------------------------------
- # ●初始化
- #--------------------------------------------------------------------------
- def initialize(map_id, event)
- fdr_ViewRange_Game_Event_initialize(map_id, event)
- # 闪烁颜色
- @flash_color=0xf0
- @switch_no = 0
- @deep = 4
- @is_always = true
- @test_block = true
- @show_grid = true
- end
- #--------------------------------------------------------------------------
- # ●初始化
- #--------------------------------------------------------------------------
- def refresh
- fdr_ViewRange_Game_Event_refresh
- return if @list == nil
- for i in 0...@list.size
- if @list[i].code == 108 and @list[i].parameters == ["FDR View Range"]
- @switch_no = @list[i+1].parameters[0].split[1].to_i
- break if @switch_no == 0
- @deep = @list[i+2].parameters[0].split[1].to_i
- @test_block = (@list[i+3].parameters[0].split[1].upcase == "TRUE")
- @is_always = (@list[i+4].parameters[0].split[1].upcase == "TRUE")
- @show_grid = (@list[i+5].parameters[0].split[1].upcase == "TRUE")
- break
- end
- end
- end
- #--------------------------------------------------------------------------
- # ●画面更新
- #--------------------------------------------------------------------------
- def update
- fdr_ViewRange_Game_Event_update
- self.test_view
- end
- #--------------------------------------------------------------------------
- # ●判断是否被遮挡
- # 参数:原点、障碍点、目标点、宽度
- #--------------------------------------------------------------------------
- def be_covered(sx,sy, cx,cy, px,py, width, x_fix,y_fix)
- #坐标转换
- sx = sx * width/1.0
- sy = sy * width/1.0
- cx = cx * width/1.0
- cy = cy * width/1.0
- px = px * width/1.0
- py = py * width/1.0
- #转换两个遮挡点
- cx_a = cx - width*x_fix/2.0
- cx_b = cx + width*x_fix/2.0
- cy_a = cy - width*y_fix/2.0
- cy_b = cy + width*y_fix/2.0
- # 求斜率
- kp = (py-sy)/(px-sx)
- if x_fix != 0 #横向遮挡
- if px == sx #在垂直方向
- tx = 0
- else
- tx = cy/kp
- end
- if (cy-sy).abs<(py-sy).abs and tx>=cx_a and tx<=cx_b
- return true #被挡住
- end
- else #纵向遮挡,面向水平方向
- ty = cx*kp
- if (cx-sx).abs<(px-sx).abs and ty>=cy_a and ty<=cy_b
- return true #被挡住
- end
- end
- return false #没有被挡住
- end
- #--------------------------------------------------------------------------
- # ● 保存数据
- # x,y:
- # 数据位置
- #--------------------------------------------------------------------------
- def pack(x,y)
- if x == $game_player.x and y == $game_player.y
- $game_switches[@switch_no] = true
- end
- if self.passable?(x,y,0)
- @view[@vp,0] = x
- @view[@vp,1] = y
- @vp += 1
- else
- @rock[@rp,0] = x
- @rock[@rp,1] = y
- @rp += 1
- end
- end
- #--------------------------------------------------------------------------
- # ● 移动类型 : 敌人视界判断
- # @deep:
- # 视野深度
- # @test_block:
- # 是否检测障碍
- #--------------------------------------------------------------------------
- def test_view
- return if @switch_no == 0 or !$scene.is_a?(Scene_Map)
- start = $game_switches[@switch_no]
- # 求得与主角座标的差值
- sx = @x - $game_player.x
- sy = @y - $game_player.y
- # 判定是否一直跟踪
- if @is_always and $game_switches[@switch_no]
- if (sx**2 + sy**2)>((@deep+2)**2)
- $game_switches[@switch_no] = false
- end
- else
- # 否则重置开关
- $game_switches[@switch_no] = false
- end
- # 地图闪烁数组
- flash = $scene.spriteset.tilemap.flash_data
- # 求得方向变量参数
- dx=DX_lib[@direction]
- dy=DY_lib[@direction]
- @view = Table.new(flash.xsize*flash.ysize,2)
- @rock = Table.new(flash.xsize*flash.ysize,2)
- @rp = 0
- @vp = 0
- # 站在NPC身旁会被发现
- # 如果不需要此效果,去掉下面的内容
- #=================================
- if dy != 0 #纵向视野
- pack(@x+1,@y)
- pack(@x-1,@y)
- else
- pack(@x,@y+1)
- pack(@x,@y-1)
- end
- #=================================
- # 扫描所有视野上的点
- for i in 1..@deep
- for j in -i..i
- if dy != 0
- cy = @y + dy*i
- cx = @x + j
- else
- cx = @x + dx*i
- cy = @y + j
- end
- pack(cx,cy)
- end
- end
- # 判断障碍
- for i in 0..@vp-1
- can_see = true
- for j in 0..@rp-1
- 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)
- can_see = false
- break
- end
- end
- if can_see and @show_grid
- flash[@view[i,0],@view[i,1]] = @flash_color
- end
- end
- #探测玩家有没有被遮挡
- if $game_switches[@switch_no] and @test_block and !(start and @is_always)
- for j in 0..@rp-1
- if (@rock[j,0] != $game_player.x or @rock[j,0] != $game_player.y) and
- self.be_covered(0,0,
- @rock[j,0]-@x,@rock[j,1]-@y,
- $game_player.x-@x,$game_player.y-@y,
- 32,dy.abs,dx.abs)
- $game_switches[@switch_no] = false
- break
- end
- end
- end
- unless start == $game_switches[@switch_no]
- $game_map.need_refresh = true
- end
- end
- end
复制代码 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|