| 
				
				
累计送礼:0 个
 累计收礼:0 个
 TA的每日心情|  | 开心 2025-10-18 22:41
 | 
|---|
 签到天数: 165 天 连续签到: 1 天 [LV.7]常住居民III 
 管理员   
 
    
        VIP6  
        卡币14601  
        OK点16  
    推广点0  
    同能卷0  
	积分17721 
 
  | 
 
|   
这个想法来源于不久前一位朋友发的脚本,不过好像换论坛后不见了。有人问能不能加入障碍判断,于是研究了下,目前实现了这个功能,测试了下还好用。
 
这个系统不是以人为中心,半径某个距离的视野,而是和人物面向方向有关的一个锥形视野,并且可以设定是否被障碍遮挡,可以设定是否显示视野范围。
 
喜欢的朋友可以拿去研究使用。
----这里下载样本工程---- 
使用方法在样本工程里面说明,下面是关键脚本[ViewRange]
 [Ruby] 纯文本查看 复制代码 #==============================================================================
# 作者: FantasyDR
#
# 版本: v1.0
#
# 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 :original_ini :initialize
  def initialize
    original_ini
    # 设置地图闪烁列表
    @tilemap.flash_data=Table.new(@tilemap.map_data.xsize,@tilemap.map_data.ysize)
  end  
end
#==============================================================================
# ■ Scene_Map
#------------------------------------------------------------------------------
#    重载地图场景
#==============================================================================
class Scene_Map
  attr_reader:spriteset
end
#==============================================================================
# ■ Game_Event
#------------------------------------------------------------------------------
#  重载事件的类
#==============================================================================
class Game_Event < Game_Character
alias :origin_initialize :initialize
alias :origin_update :update
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)
   origin_initialize(map_id, event)
   # 敌人朝向是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}
   # 闪烁颜色
   @flash_color=0xf0
end
#--------------------------------------------------------------------------
# ●画面更新
#--------------------------------------------------------------------------
def update
   if moving? or @original_direction != @direction
      $scene.spriteset.tilemap.flash_data.fill(0)
      @original_direction = @direction
   end
   self.test_view
   origin_update
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,test)
   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 @deep == nil
  flash = $scene.spriteset.tilemap.flash_data
  # 求得方向变量参数
  dx=@dx_lib[@direction]
  dy=@dy_lib[@direction]
  # 求得与主角座标的差值
  sx = @x - $game_player.x
  sy = @y - $game_player.y
  
  # 判定是否一直跟踪
  if @is_always and $game_switches[@switch_no]
    if (sx**2 + sy**2)>((@deep+1)**2)
     $game_switches[@switch_no]=false
    end
  else
    $game_switches[@switch_no]=false
  end
  
  @view = Table.new(flash.xsize*flash.ysize,2)
  @rock = Table.new(flash.xsize*flash.ysize,2)
  @rp = 0
  @vp = 0
  # 设置周围视野
  if dy != 0 #纵向视野
   pack(@x+1,@y,false)
   pack(@x-1,@y,false)
  else
   pack(@x,@y+1,false)
   pack(@x,@y-1,false)
  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,true)
   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
    flash[@view[i,0],@view[i,1]] = @flash_color if can_see and @show_grid
  end
  #探测玩家有没有被遮挡
  if $game_switches[@switch_no] and @test_block
   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
end
#--------------------------------------------------------------------------
# ●移动类型
#--------------------------------------------------------------------------
def em_view(switch_no,deep=4,test_block=true,is_always=true,show_grid=true)
  @switch_no = switch_no
  @deep = deep
  @test_block = test_block
  @is_always = is_always
  @show_grid = show_grid
  # 根据$game_switches[@switch_no]移动
  if $game_switches[@switch_no]
    # 被发现的情况,跟随主角
    move_toward_player
  else
    # 没有被发现的情况,随机转向
    turn_random
  end
end
end | 
 |