查看: 4756|回复: 5

[原创发布] Sprite_Vision 地图视野

[复制链接]
梦石
0
星屑
4761
在线时间
285 小时
注册时间
2013-10-13
回帖
580
发表于 2015-7-13 22:43:37 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 hys111111 于 2017-8-22 19:07 编辑

[pre lang="Ruby"]
#======================================   
# Sprite_Vision 地图视野   
# 作者: viktor   
# 原创脚本。仅供讨论使用,不可以用于商用。转载请注明出处/暂时不对脚本进行更多的解释了。   
# 设置视野方法:使用地图标记,原则是地图标记越大,高度越高。   
#   
# 最低的地面:0   
# 墙:比下方的地面高1   
# 竖直墙的顶部:比下方的墙高1   
# 高地:与在高地下侧的竖直墙顶部高度相同。这样在高地上可以看到下面的东西   
# 背后可通行的障碍物(如树木):可通行的部分与周围地面相同,底部+1   
#   
# 例如:   
# 样例中的地面(浅绿草地):0   
# 石头墙:1   
# 石头墙顶部:2   
# 高地(绿草地):2   
# 高地上的树:树根3 树冠2   
# 山顶的草:3   
#======================================   
#$Call_fillshadow = Win32API.new("bmp", "fill_shadow", 'lllli', 'i')   
$width = 640 if $width == nil  
$height = 480 if $height == nil  
  
class Sprite_Vision < Sprite  
# 配置   
# 脚本开关   
SWITCH = 30  
# 渐变速率   
STEP = 0.1  
# 平滑开关   
SMOOTH = true  
# 可变配置   
def init_param  
    # directional lighting   
    # [前 侧 后]方向的最大亮度   
    @lighting=[255, 160, 64]  
    @directional = [[0, 1, 1, 2],  
                    [1, 0, 2, 1],  
                    [1, 2, 0, 1],  
                    [2, 1, 1, 0]]  
    # 由近到远的亮度变化率。1表示不改变(可以看到前方无限远)   
    @rate = 1.0  
    # 阈值:小于此亮度的格子不可见   
    @threshold = 0  
    # 视野阴影的z值。如果遮挡了窗口需要调整这个。   
    self.z=10  
end  
# 直接修改init_param中的参数的方法。每秒至多调用一次因为有refresh   
def set_param(param, value)  
  self.instance_variable_set(param, value)  
  refresh  
end  
# 经验公式。设置视野范围 0..1 为近..远 每秒至多调用一次因为有refresh   
def set_range(param)  
  @threshold = (64 * (1.0 - param)).to_i  
  @rate = 0.4 + 0.6 * param  
  refresh  
end  
  
    def initialize(viewport, tilemap)  
        super(viewport)  
        @tilemap = tilemap  
        init_param  
        init_cache  
  
        self.bitmap = Bitmap.new(@tilemap.map_data.xsize * 32,  
                                 @tilemap.map_data.ysize * 32)  
        self.bitmap.fill_rect(self.bitmap.rect, @gray[255])  
        # 内部亮度矩阵,存放各个角色看到的亮度的最大值   
        @brightness = Table.new(@tilemap.map_data.xsize, @tilemap.map_data.ysize)  
        # 显示亮度矩阵   
        @disp = Table.new(@tilemap.map_data.xsize, @tilemap.map_data.ysize)  
        # 玩家位置   
        @cx = -1; @cy = -1  
        # 跟随的玩家数量初始化为1   
        init_br(1)  
        # 设置绘制方法   
        @update_func = SMOOTH ? self.method(:smooth_update) :   
                                self.method(:rough_update)  
        # 刷新列表初始化   
        @xlist=[0]*1000  
        @ylist=[0]*1000  
        @blist=[0]*1000  # 亮度   
        @tlist=[1]*1000  # 是否要刷新。正数为需要   
        @list_size = 0  
  
        refresh  
    end  
  
    def dispose  
        self.bitmap.dispose if self.bitmap != nil  
        super  
    end  
  
    def init_cache  
        srand; @Gray = []  
        # 颜色对象           
        (0..255).each{|x|@gray.push(Color.new(46, 29, 27, x))}  
        # 测试用颜色对象   
        # (0..255).each{|a| @gray.push(Color.new(rand(255), rand(255), rand(255), 64))}   
  
        # 地图标记   
        @tags = Table.new(@tilemap.map_data.xsize, @tilemap.map_data.ysize)  
        for x in 0...@tags.xsize  
            for y in 0...@tags.ysize  
                @tags[x, y]=$game_map.terrain_tag(x, y)  
            end  
        end  
    end  
  
    def init_br(n)  
        # multiple lighting   
        # 初始化每个角色的亮度矩阵   
        @br=Table.new(@tilemap.map_data.xsize, @tilemap.map_data.ysize, n)  
        @nc = n  
        @current = 0  
    end  
  
    # 取某方向的最大亮度   
    def base_brightness(direction)  
        return @lighting[@directional[$game_player.direction/2-1][direction/2-1]]  
    end  
    # 计算刷新矩形   
    def count_refresh_rect  
        @min_x = $game_map.display_x / 128  
        @min_y = $game_map.display_y / 128  
        @max_x = @min_x + $width / 32  
        @max_y = @min_y + $height / 32  
        # 调整   
        case $game_player.direction  
        when 2  
            @max_y += 3  
        when 4  
            @min_x -= 3  
        when 6  
            @max_x += 3  
        when 8  
            @min_y -= 3  
        end  
        # 剪裁,规范化   
        @min_x = [@min_x, 0].max.to_i  
        @min_y = [@min_y, 0].max.to_i  
        @max_x = [@max_x, @tilemap.map_data.xsize].min.to_i  
        @max_y = [@max_y, @tilemap.map_data.ysize].min.to_i  
    end  
  
    def set_brightness(x, y)  
        # 设置内部亮度值   
        m=0  
        (0...@nc).each{|z|  
            m=[m, @br[x, y, z]].max  
        }  
        @brightness[x, y]=m  
        # 更新刷新列表   
        if m != @disp[x, y]  
            @xlist[@list_size] = x  
            @ylist[@list_size] = y  
            @list_size += 1  
        end  
    end  
  
    def refresh  
        @cx = $game_player.x  
        @cy = $game_player.y  
        @list_size = 0  
  
        count_refresh_rect  
        @br[@cx, @cy, @current] = 255  
        set_brightness(@cx, @cy)  
        @ctag = @tags[@cx, @cy]  
        # 四方向预处理   
        b=base_brightness(2)  
        (@cy+1...@max_y).to_a.each{|y|  
            @br[@cx, y, @current] = b  
            set_brightness(@cx, y)  
            b *= @rate  
            break if @tags[@cx, y] > @ctag  
        }  
  
        b=base_brightness(4)  
        (@min_x...@cx).to_a.reverse_each{|x|  
            @br[x, @cy, @current] = b  
            set_brightness(x, @cy)  
            b *= @rate  
            break if @tags[x, @cy] > @ctag  
        }  
  
        b=base_brightness(6)  
        (@cx+1...@max_x).to_a.each{|x|  
            @br[x, @cy, @current] = b  
            set_brightness(x, @cy)  
            b *= @rate  
            break if @tags[x, @cy] > @ctag  
        }  
  
        b=base_brightness(8)  
        ref_tag = @ctag + 1  
        (@min_y...@cy).to_a.reverse_each{|y|  
            @br[@cx, y, @current] = b  
            set_brightness(@cx, y)  
            b *= @rate  
            this_tag = @tags[@cx, y]  
            break if this_tag > ref_tag  
            # ref_tag = [this_tag, ref_tag].max   
        }  
  
        # 填充其他格子   
        # up-right   
        iterate_tiles(@cx+1...@max_x,  
                      (@min_y...@cy).to_a.reverse,  
                      1, -1) # rescue p @min_y, @cy   
        # up-left   
        iterate_tiles((@min_x...@cx).to_a.reverse,  
                      (@min_y...@cy).to_a.reverse,  
                      -1, -1)  
        # down-left   
        iterate_tiles((@min_x...@cx).to_a.reverse,  
                      @cy+1...@max_y,  
                      -1, 1)  
        # down-right   
        iterate_tiles(@cx+1...@max_x,   
                      @cy+1...@max_y,  
                      1, 1)  
         
        # 滚动   
        @current = (@current + 1) % @nc  
    end  
  
    def iterate_tiles(xarray, yarray, dx, dy)  
      ref_tag = @ctag  
      for y in yarray  
        for x in xarray  
          tag1 = @tags[x - dx, y]  
          tag2 = @tags[x, y - dy]  
            
          # 墙判定   
          br1 = tag1 > @ctag ? 0 : @br[x-dx, y, @current]  
          br2 = tag2 > ref_tag ? 0 : @br[x, y-dy, @current]  
   
          ref_tag = tag2 if dy==-1 and ref_tag < tag2  
            
          # 计算亮度   
          tmp = (br1 + br2) / 2  
          @br[x, y, @current] = (tmp>@threshold?tmp:0)  
          set_brightness(x, y)  
        end  
      end  
    end  
      
    def update_bitmap(step=STEP)  
        new_size=0  
        for i in 0...@list_size  
            x = @xlist; y = @ylist  
            diff = @brightness[x, y] - @disp[x, y]  
            if diff!=0  
              @disp[x, y] += [diff.abs*step, 1].max.to_i * (diff<=>0)  
              @xlist[new_size]=x; @ylist[new_size]=y;  
              @blist[new_size]=@disp[x, y]  
              self.bitmap.fill_rect(x*32, y*32, 32, 32, @gray[255-@blist[new_size]])  
              #self.bitmap.draw_text(x*32, y*32, 32, 32, @tags[x, y].to_s, 1)   
              new_size += 1  
            end  
        end  
         
        @list_size = new_size  
        # puts new_size   
        # 调用dll   
        #$Call_fillshadow.call(self.bitmap.object_id,   
        #            @xlist.object_id, @ylist.object_id, @blist.object_id,   
        #            @list_size)   
    end  
  
    def smooth_update  
        # 移动时刷新视野数据   
        refresh if $game_player.x != @cx or $game_player.y != @cy  
        # 每一帧平滑刷新视野图形   
        update_bitmap  
    end  
    def rough_update  
        # 移动时刷新视野数据   
        if $game_player.x != @cx or $game_player.y != @cy  
          refresh   
          update_bitmap  
        end  
    end      
    def update  
      @update_func.call  
      super  
    end  
end  
  
# 接入部分   
class Spriteset_Map  
  attr_accessor :vision_sprite  
   
  def update_vision  
    if @vision_sprite==nil  
      @vision_sprite=Sprite_Vision.new(@viewport1, @tilemap)  
      @vision_sprite.init_br($game_party.actors.size)  
      @vision_sprite.opacity=0  
    end  
    if $game_switches[Sprite_Vision::SWITCH]  
      @vision_sprite.visible=true  
      @vision_sprite.opacity+=10 if @vision_sprite.opacity < 255  
      @vision_sprite.ox=$game_map.display_x / 4  
      @vision_sprite.oy=$game_map.display_y / 4  
      @vision_sprite.update  
    else  
      if @vision_sprite!=nil  
        @vision_sprite.opacity-=10  
        @vision_sprite.visible=false if @vision_sprite.opacity<30  
      end  
    end  
  end  
   
  alias viktor_vision_update update  
  def update  
    update_vision  
    viktor_vision_update  
  end  
   
  alias viktor_vision_dispose dispose  
  def dispose  
    @vision_sprite.dispose if @vision_sprite!=nil  
    viktor_vision_dispose  
  end  
end  
  
class Scene_Map  
  attr_accessor :spriteset  
end   
[/pre]

点评

不来个代码框吗?  发表于 2015-7-15 17:13
http://blog.csdn.net/xulai1001/article/details/8761416  发表于 2015-7-13 22:44
梦石
0
星屑
50
在线时间
15 小时
注册时间
2015-7-7
回帖
18
发表于 2015-7-14 13:41:23 | 显示全部楼层
顶  虽然还看不懂,但是必须支持
回复

使用道具 举报

头像被屏蔽
梦石
0
星屑
88
在线时间
631 小时
注册时间
2014-8-4
回帖
3243
发表于 2015-7-15 11:10:38 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
回复

使用道具 举报

梦石
0
星屑
50
在线时间
138 小时
注册时间
2015-6-9
回帖
27
发表于 2015-10-19 11:17:04 来自手机 | 显示全部楼层
没什么用啊,
回复

使用道具 举报

头像被屏蔽
梦石
0
星屑
653
在线时间
3774 小时
注册时间
2011-2-26
回帖
1577

开拓者

发表于 2015-10-19 13:27:17 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
回复

使用道具 举报

脚本白痴

梦石
0
星屑
422
在线时间
903 小时
注册时间
2007-7-9
回帖
1259
发表于 2015-10-20 18:43:16 | 显示全部楼层
啊,这个脚本要怎么使用呢?

正统向RPG-大雄的高井山奇谈
https://rpg.blue/thread-369758-1-1.html
哆啦A梦RTP风格素材
https://rpg.blue/forum.php?mod=viewthread&tid=394608
回复

使用道具 举报

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

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部