赞 | 2 |
VIP | 0 |
好人卡 | 0 |
积分 | 42 |
经验 | 13328 |
最后登录 | 2024-8-10 |
在线时间 | 258 小时 |
Lv3.寻梦者
- 梦石
- 0
- 星屑
- 4169
- 在线时间
- 258 小时
- 注册时间
- 2013-10-13
- 帖子
- 815
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 hys111111 于 2017-8-22 19:07 编辑
#====================================== # 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; [url=home.php?mod=space&uid=15507]@Gray[/url] = [] # 颜色对象 (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 [email]0...@tags.xsize[/email] for y in [email]0...@tags.ysize[/email] @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 [url=home.php?mod=space&uid=94117]@current[/url] = 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[i]; y = @ylist[i] 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
#======================================
# 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; [url=home.php?mod=space&uid=15507]@Gray[/url] = []
# 颜色对象
(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 [email]0...@tags.xsize[/email]
for y in [email]0...@tags.ysize[/email]
@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
[url=home.php?mod=space&uid=94117]@current[/url] = 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[i]; y = @ylist[i]
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
|
|