查看: 77|回复: 0

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

[复制链接]
  • TA的每日心情
    开心
    2024-5-10 09:55
  • 签到天数: 37 天

    连续签到: 3 天

    [LV.5]常住居民I

    2028

    主题

    32

    回帖

    7260

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    0
    卡币
    5184
    OK点
    16
    积分
    7260
    发表于 同元一千年七月二十八日(秋) | 显示全部楼层 |阅读模式


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

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

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

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

    使用方法在样本工程里面说明,下面是关键脚本[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
    end, if, for, in
    天天去同能,天天有童年!
    回复 论坛版权

    使用道具 举报

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

    本版积分规则

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2024-5-18 01:07 , Processed in 0.069340 second(s), 46 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

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