赞 | 68 |
VIP | 0 |
好人卡 | 0 |
积分 | 65 |
经验 | 0 |
最后登录 | 2023-7-2 |
在线时间 | 119 小时 |
Lv4.逐梦者
- 梦石
- 0
- 星屑
- 6483
- 在线时间
- 119 小时
- 注册时间
- 2020-1-8
- 帖子
- 234
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 RPGzh500223 于 2022-11-25 12:08 编辑
整体还是很鸡肋,效果基本没变化,懒得做gif示意图了。
烛火可以自定义颜色,支持不透明度变化实现明暗变化,API效率提升,代码是关于灯光效果的实现,关于交互自行修改添加吧。
Light.dll VS2017 C语言编写
class Rect def to_int self.__id__ end end class Bitmap def to_int self.__id__ end end module LIGHT # 并不严谨的标志,但是方便 Flag = "set_light" Pic_Dir = "Graphics/Light_Textures" # 透明通道图片,有效值为alpha,填充的颜色能看清图形就好,建议黑色 Light_Type_Pic_Name = { 0 => "round.png" } Light_Effect_Rect_Frame = 10 dll = "Light.dll" # 源位图双线性插值缩放至目标位图(无混合) # dst_bitmap_obj_id, src_bitmap_obj_id Stretch = Win32API.new(dll, 'bitmap_stretch_move', 'LL', 'L') # ————灯光专用方法———— # 以纹理的alpha值进行颜色填充,再与黑色(0xFF000000)进行混合(Bitmap#blt) # alpha: 0 <= threshold[0..7] < threshold[8..15] <= 255 # 颜色 :low_rgb24 |阈值下限| HSL_gradient |阈值上限| high_rgb24 # textutre_bitmap_obj_id # high_rgb24 0..23位有效值 # low_rgb24 0..23位有效值 # 该值为-1的话,单色(high_rgb24)填充,阈值无效 # alpha_threshold16 0..7位 阈值下限 (须小于) 8..15位 阈值上限 Frgb2 = Win32API.new(dll, 'bitmap_full_rgb2_blt_black', 'LLLL', 'L') # 源位图区域与目标位图指定位置进行乘算叠加 # 计算:源RGB预乘opacity,反相后再与目标RGB乘算叠加,参数基本类似Btimap#blt # dst_bitmap_obj_id, dx, dy, # src_bitmap_obj_id, src_bitmap_rect_obj_id, opacity Mul = Win32API.new(dll, 'bitmap_light_mul', 'LLLLLL', 'L') # 以指定alpha的白色对位图进行填充 # dst_bitmap_obj_id # alpha8 0..7位有效值 Full = Win32API.new(dll, 'bitmap_full_white_alpha', 'LL', 'L') @@cache = {} def self.cache(type) @@cache[type] ||= Bitmap.new( File.join(Pic_Dir, Light_Type_Pic_Name[type] || Light_Type_Pic_Name[0])) end def self.cache_clear @@cache.values.each {|bitmap| bitmap.dispose} @@cache.clear end module Macro def rgb2int(r, g, b) r << 16 | g << 8 | b end alias RGB rgb2int alias IXY rgb2int def argb2int(a, r, g, b) a << 24 | r << 16 | g << 8 | b end alias DINX argb2int end module Interface def light_erase @light_data ||= [] @light_data.each do |i| $game_map.light_data.delete(i) i.bitmap_dispose end @light_data.clear end # type 纹理样式,参见 Light_Type_Pic_Name # rgb24_high/low/threshold 颜色值相关参数,参见 Frgb2 # zoom_x/y 缩放系数 # off_x/y 偏移 # center_type 对齐中心位置,参考小键盘数字的位置 # alpha_delta/ini/min/max 不透明度相关参数,“一个参数” # cell_idx/xsize/ysize 帧动画的参数,“一个参数” # 效果参考 RMXP人物【停止动画】 # 单元序列,自左向右,从上到下,4 * 4如下所示 # 0 —— (xsize-1) # 0 0 1 2 3 # | 4 5 6 7 # | 8 9 A B # ysize-1 C D E F def set_light(type = 0, high_rgb24 = 0xFFFFFF, low_rgb24 = -1, rgb_threshold = 0xFF00, zoom_x = 1, zoom_y = 1, off_x = 0, off_y = 0, center_type = 5, alpha_dinx = 0x00FFFFFF, cell_ixy = 0x000101) texture = LIGHT.cache(type) w, h = (texture.width * zoom_x).to_i, (texture.height * zoom_y).to_i return if w < 2 || h < 2 if w == texture.width && h == texture.height bitmap = texture.clone else bitmap = Bitmap.new(w, h) LIGHT::Stretch.call(bitmap, texture) end LIGHT::Frgb2.call(bitmap, high_rgb24, low_rgb24, rgb_threshold) light = LightEffect.new(self, bitmap, off_x, off_y, center_type, alpha_dinx, cell_ixy) @light_data << light $game_map.light_data << light end end end class LightEffect def initialize(event, bitmap, offX, offY, center_type, alpha_dinx, cell_ixy) @event, @bitmap = event, bitmap cell_idx = (cell_ixy & 0xFF0000) >> 16 cell_xsize = (cell_ixy & 0xFF00) >> 8 cell_ysize = cell_ixy & 0xFF cell_x, cell_y = cell_idx % cell_xsize, cell_idx / cell_xsize cell_w, cell_h = bitmap.width / cell_xsize, bitmap.height / cell_ysize @src_rect = Rect.new(cell_x * cell_w, cell_y * cell_h, cell_w, cell_h) @off_x = offX + 16 - (center_type % 3 - 1) * cell_w / 2 @off_y = offY + 16 - (2 - center_type / 3) * cell_h / 2 @rect_active = cell_xsize > 1 @delta_alpha = alpha_dinx >> 24 @alpha = (alpha_dinx & 0xFF0000) >> 16 @min_alpha = (alpha_dinx & 0xFF00) >> 8 @max_alpha = alpha_dinx & 0xFF if @min_alpha > @max_alpha @min_alpha, @max_alpha = @max_alpha, @min_alpha end end def display_at(target_bitmap) self.alpha_update return if @alpha == 0 dx = (@event.real_x - $game_map.display_x + 3) / 4 + @off_x return if dx >= target_bitmap.width #left return if dx + @src_rect.width - 1 <= 0 #right dy = (@event.real_y - $game_map.display_y + 3) / 4 + @off_y return if dy >= target_bitmap.height #top return if dy + @src_rect.height - 1 <= 0 #bottom LIGHT::Mul.call(target_bitmap, dx, dy, @bitmap, @src_rect, @alpha) end def alpha_update if @delta_alpha != 0 @alpha += @delta_alpha if @alpha > @max_alpha @alpha, @delta_alpha = @max_alpha, -@delta_alpha end if @alpha < @min_alpha @alpha, @delta_alpha = @min_alpha, -@delta_alpha end end end def src_rect_update if @rect_active == true @src_rect.x += @src_rect.width @src_rect.x = 0 if @src_rect.x >= @bitmap.width end end def bitmap_dispose @bitmap.dispose end end class LightRenderTarget def initialize(viewport) @alpha = -1 self.alpha = 128 return if $game_map.light_switch == false @rt = Sprite.new(viewport) @target = Bitmap.new(viewport.rect.width, viewport.rect.height) @rt.bitmap = @target @rt.blend_type = 2 @rt.z = 1000 end def alpha=(new_alpha) return if @alpha == new_alpha @alpha = new_alpha < 0 ? 0 : (new_alpha > 255 ? 255 : new_alpha) end def update return if $game_map.light_switch == false return if @alpha == 0 if Graphics.frame_count % LIGHT::Light_Effect_Rect_Frame == 0 $game_map.light_data.each {|i| i.src_rect_update} end LIGHT::Full.call(@target, @alpha) $game_map.light_data.each {|i| i.display_at(@target)} end def dispose if @target != nil @target.dispose @rt.dispose @target = nil end LIGHT.cache_clear end end class Interpreter include LIGHT::Macro end class Game_Player include LIGHT::Interface def light_on(*args) @light_data ||= [] self.set_light(*args) end # 其实类似手电筒,根据方向调整 center_type, off_x, off_y, cell_idx就可以实现 end #———以下代码有大部分RMXP原代码,建议直接添加至原代码——— class Game_Map attr_reader :light_data attr_reader :light_switch #-------------------------------------------------------------------------- # ● 初始化条件 #-------------------------------------------------------------------------- def initialize @map_id = 0 @display_x = 0 @display_y = 0 @light_data = [] @light_switch = false end #-------------------------------------------------------------------------- # ● 设置 # map_id : 地图 ID #-------------------------------------------------------------------------- def setup(map_id) # 地图 ID 记录到 @map_id @map_id = map_id # 地图文件装载后、设置到 @map @map = load_data(sprintf("Data/Map%03d.rxdata", @map_id)) # 定义实例变量设置地图元件信息 tileset = $data_tilesets[@map.tileset_id] @tileset_name = tileset.tileset_name @autotile_names = tileset.autotile_names @panorama_name = tileset.panorama_name @panorama_hue = tileset.panorama_hue @fog_name = tileset.fog_name @fog_hue = tileset.fog_hue @fog_opacity = tileset.fog_opacity @fog_blend_type = tileset.fog_blend_type @fog_zoom = tileset.fog_zoom @fog_sx = tileset.fog_sx @fog_sy = tileset.fog_sy @battleback_name = tileset.battleback_name @passages = tileset.passages @priorities = tileset.priorities @terrain_tags = tileset.terrain_tags # 初始化显示坐标 @display_x = 0 @display_y = 0 # 清除刷新要求标志 @need_refresh = false # 释放上一地图的灯光对象 @light_data.each{|i| i.bitmap_dispose} @light_data.clear # 设置地图事件数据 @events = {} for i in @map.events.keys @events[i] = Game_Event.new(@map_id, @map.events[i]) end @light_switch = !@light_data.empty? # 设置公共事件数据 @common_events = {} for i in 1...$data_common_events.size @common_events[i] = Game_CommonEvent.new(i) end # 初始化雾的各种信息 @fog_ox = 0 @fog_oy = 0 @fog_tone = Tone.new(0, 0, 0, 0) @fog_tone_target = Tone.new(0, 0, 0, 0) @fog_tone_duration = 0 @fog_opacity_duration = 0 @fog_opacity_target = 0 # 初始化滚动信息 @scroll_direction = 2 @scroll_rest = 0 @scroll_speed = 4 end end class Game_Event include LIGHT::Macro include LIGHT::Interface # !!注释即代码,不能乱写!! # 只在“第一个指令块”有效。 # 标志:事件当前页的第一条指令set_light(...); def refresh_light if @list if @list[0].code == 108 if (params = @list[0].parameters[0]).include?(LIGHT::Flag) i, scripts = 1, params.dup while (@list[i].code == 408) scripts << @list[i].parameters[0] i += 1 end self.light_erase eval(scripts) end end end end #-------------------------------------------------------------------------- # ● 刷新 #-------------------------------------------------------------------------- def refresh # 初始化本地变量 new_page new_page = nil # 无法暂时消失的情况下 unless @erased # 从编号大的事件页按顺序调查 for page in @event.pages.reverse # 可以参考事件条件 c c = page.condition # 确认开关条件 1 if c.switch1_valid if $game_switches[c.switch1_id] == false next end end # 确认开关条件 2 if c.switch2_valid if $game_switches[c.switch2_id] == false next end end # 确认变量条件 if c.variable_valid if $game_variables[c.variable_id] < c.variable_value next end end # 确认独立开关条件 if c.self_switch_valid key = [@map_id, @event.id, c.self_switch_ch] if $game_self_switches[key] != true next end end # 设置本地变量 new_page new_page = page # 跳出循环 break end end # 与上次同一事件页的情况下 if new_page == @page # 过程结束 return end # @page 设置为现在的事件页 @page = new_page # 清除启动中标志 clear_starting # 没有满足条件的页面的时候 if @page == nil # 设置各实例变量 @tile_id = 0 @character_name = "" @character_hue = 0 @move_type = 0 @through = true @trigger = nil @list = nil @interpreter = nil # 过程结束 return end # 设置各实例变量 @tile_id = @page.graphic.tile_id @character_name = @page.graphic.character_name @character_hue = @page.graphic.character_hue if @original_direction != @page.graphic.direction @direction = @page.graphic.direction @original_direction = @direction @prelock_direction = 0 end if @original_pattern != @page.graphic.pattern @pattern = @page.graphic.pattern @original_pattern = @pattern end @opacity = @page.graphic.opacity @blend_type = @page.graphic.blend_type @move_type = @page.move_type @move_speed = @page.move_speed @move_frequency = @page.move_frequency @move_route = @page.move_route @move_route_index = 0 @move_route_forcing = false @walk_anime = @page.walk_anime @step_anime = @page.step_anime @direction_fix = @page.direction_fix @through = @page.through @always_on_top = @page.always_on_top @trigger = @page.trigger @list = @page.list @interpreter = nil self.refresh_light # 目标是 [并行处理] 的情况下 if @trigger == 4 # 生成并行处理用解释器 @interpreter = Interpreter.new end # 自动事件启动判定 check_event_trigger_auto end end class Spriteset_Map #-------------------------------------------------------------------------- # ● 初始化对像 #-------------------------------------------------------------------------- def initialize # 生成显示端口 @viewport1 = Viewport.new(0, 0, 640, 480) @viewport2 = Viewport.new(0, 0, 640, 480) @viewport3 = Viewport.new(0, 0, 640, 480) @viewport2.z = 200 @viewport3.z = 5000 # 生成元件地图 @tilemap = Tilemap.new(@viewport1) @tilemap.tileset = RPG::Cache.tileset($game_map.tileset_name) for i in 0..6 autotile_name = $game_map.autotile_names[i] @tilemap.autotiles[i] = RPG::Cache.autotile(autotile_name) end @tilemap.map_data = $game_map.data @tilemap.priorities = $game_map.priorities # 生成远景平面 @panorama = Plane.new(@viewport1) @panorama.z = -1000 # 生成雾平面 @fog = Plane.new(@viewport1) @fog.z = 3000 # 生成角色活动块 @character_sprites = [] for i in $game_map.events.keys.sort sprite = Sprite_Character.new(@viewport1, $game_map.events[i]) @character_sprites.push(sprite) end @character_sprites.push(Sprite_Character.new(@viewport1, $game_player)) # 生成天气 @weather = RPG::Weather.new(@viewport1) @lights = LightRenderTarget.new(@viewport1) # 生成图片 @picture_sprites = [] for i in 1..50 @picture_sprites.push(Sprite_Picture.new(@viewport2, $game_screen.pictures[i])) end # 生成计时器块 @timer_sprite = Sprite_Timer.new # 刷新画面 update end #-------------------------------------------------------------------------- # ● 释放 #-------------------------------------------------------------------------- def dispose # 释放元件地图 @tilemap.tileset.dispose for i in 0..6 @tilemap.autotiles[i].dispose end @tilemap.dispose # 释放远景平面 @panorama.dispose # 释放雾平面 @fog.dispose # 释放角色活动块 for sprite in @character_sprites sprite.dispose end @lights.dispose # 释放天候 @weather.dispose # 释放图片 for sprite in @picture_sprites sprite.dispose end # 释放计时器块 @timer_sprite.dispose # 释放显示端口 @viewport1.dispose @viewport2.dispose @viewport3.dispose end #-------------------------------------------------------------------------- # ● 刷新画面 #-------------------------------------------------------------------------- def update # 远景与现在的情况有差异发生的情况下 if @panorama_name != $game_map.panorama_name or @panorama_hue != $game_map.panorama_hue @panorama_name = $game_map.panorama_name @panorama_hue = $game_map.panorama_hue if @panorama.bitmap != nil @panorama.bitmap.dispose @panorama.bitmap = nil end if @panorama_name != "" @panorama.bitmap = RPG::Cache.panorama(@panorama_name, @panorama_hue) end Graphics.frame_reset end # 雾与现在的情况有差异的情况下 if @fog_name != $game_map.fog_name or @fog_hue != $game_map.fog_hue @fog_name = $game_map.fog_name @fog_hue = $game_map.fog_hue if @fog.bitmap != nil @fog.bitmap.dispose @fog.bitmap = nil end if @fog_name != "" @fog.bitmap = RPG::Cache.fog(@fog_name, @fog_hue) end Graphics.frame_reset end # 刷新元件地图 @tilemap.ox = $game_map.display_x / 4 @tilemap.oy = $game_map.display_y / 4 @tilemap.update # 刷新远景平面 @panorama.ox = $game_map.display_x / 8 @panorama.oy = $game_map.display_y / 8 # 刷新雾平面 @fog.zoom_x = $game_map.fog_zoom / 100.0 @fog.zoom_y = $game_map.fog_zoom / 100.0 @fog.opacity = $game_map.fog_opacity @fog.blend_type = $game_map.fog_blend_type @fog.ox = $game_map.display_x / 4 + $game_map.fog_ox @fog.oy = $game_map.display_y / 4 + $game_map.fog_oy @fog.tone = $game_map.fog_tone # 刷新角色活动块 for sprite in @character_sprites sprite.update end # 刷新天候图形 @weather.type = $game_screen.weather_type @weather.max = $game_screen.weather_max @weather.ox = $game_map.display_x / 4 @weather.oy = $game_map.display_y / 4 @weather.update @lights.update # 刷新图片 for sprite in @picture_sprites sprite.update end # 刷新计时器块 @timer_sprite.update # 设置画面的色调与震动位置 @viewport1.tone = $game_screen.tone @viewport1.ox = $game_screen.shake # 设置画面的闪烁色 @viewport3.color = $game_screen.flash_color # 刷新显示端口 @viewport1.update @viewport3.update end end
class Rect
def to_int
self.__id__
end
end
class Bitmap
def to_int
self.__id__
end
end
module LIGHT
# 并不严谨的标志,但是方便
Flag = "set_light"
Pic_Dir = "Graphics/Light_Textures"
# 透明通道图片,有效值为alpha,填充的颜色能看清图形就好,建议黑色
Light_Type_Pic_Name = {
0 => "round.png"
}
Light_Effect_Rect_Frame = 10
dll = "Light.dll"
# 源位图双线性插值缩放至目标位图(无混合)
# dst_bitmap_obj_id, src_bitmap_obj_id
Stretch = Win32API.new(dll, 'bitmap_stretch_move', 'LL', 'L')
# ————灯光专用方法————
# 以纹理的alpha值进行颜色填充,再与黑色(0xFF000000)进行混合(Bitmap#blt)
# alpha: 0 <= threshold[0..7] < threshold[8..15] <= 255
# 颜色 :low_rgb24 |阈值下限| HSL_gradient |阈值上限| high_rgb24
# textutre_bitmap_obj_id
# high_rgb24 0..23位有效值
# low_rgb24 0..23位有效值
# 该值为-1的话,单色(high_rgb24)填充,阈值无效
# alpha_threshold16 0..7位 阈值下限 (须小于) 8..15位 阈值上限
Frgb2 = Win32API.new(dll, 'bitmap_full_rgb2_blt_black', 'LLLL', 'L')
# 源位图区域与目标位图指定位置进行乘算叠加
# 计算:源RGB预乘opacity,反相后再与目标RGB乘算叠加,参数基本类似Btimap#blt
# dst_bitmap_obj_id, dx, dy,
# src_bitmap_obj_id, src_bitmap_rect_obj_id, opacity
Mul = Win32API.new(dll, 'bitmap_light_mul', 'LLLLLL', 'L')
# 以指定alpha的白色对位图进行填充
# dst_bitmap_obj_id
# alpha8 0..7位有效值
Full = Win32API.new(dll, 'bitmap_full_white_alpha', 'LL', 'L')
@@cache = {}
def self.cache(type)
@@cache[type] ||= Bitmap.new(
File.join(Pic_Dir, Light_Type_Pic_Name[type] || Light_Type_Pic_Name[0]))
end
def self.cache_clear
@@cache.values.each {|bitmap| bitmap.dispose}
@@cache.clear
end
module Macro
def rgb2int(r, g, b)
r << 16 | g << 8 | b
end
alias RGB rgb2int
alias IXY rgb2int
def argb2int(a, r, g, b)
a << 24 | r << 16 | g << 8 | b
end
alias DINX argb2int
end
module Interface
def light_erase
@light_data ||= []
@light_data.each do |i|
$game_map.light_data.delete(i)
i.bitmap_dispose
end
@light_data.clear
end
# type 纹理样式,参见 Light_Type_Pic_Name
# rgb24_high/low/threshold 颜色值相关参数,参见 Frgb2
# zoom_x/y 缩放系数
# off_x/y 偏移
# center_type 对齐中心位置,参考小键盘数字的位置
# alpha_delta/ini/min/max 不透明度相关参数,“一个参数”
# cell_idx/xsize/ysize 帧动画的参数,“一个参数”
# 效果参考 RMXP人物【停止动画】
# 单元序列,自左向右,从上到下,4 * 4如下所示
# 0 —— (xsize-1)
# 0 0 1 2 3
# | 4 5 6 7
# | 8 9 A B
# ysize-1 C D E F
def set_light(type = 0, high_rgb24 = 0xFFFFFF, low_rgb24 = -1,
rgb_threshold = 0xFF00, zoom_x = 1, zoom_y = 1, off_x = 0, off_y = 0,
center_type = 5, alpha_dinx = 0x00FFFFFF, cell_ixy = 0x000101)
texture = LIGHT.cache(type)
w, h = (texture.width * zoom_x).to_i, (texture.height * zoom_y).to_i
return if w < 2 || h < 2
if w == texture.width && h == texture.height
bitmap = texture.clone
else
bitmap = Bitmap.new(w, h)
LIGHT::Stretch.call(bitmap, texture)
end
LIGHT::Frgb2.call(bitmap, high_rgb24, low_rgb24, rgb_threshold)
light = LightEffect.new(self, bitmap, off_x, off_y, center_type,
alpha_dinx, cell_ixy)
@light_data << light
$game_map.light_data << light
end
end
end
class LightEffect
def initialize(event, bitmap, offX, offY, center_type, alpha_dinx, cell_ixy)
@event, @bitmap = event, bitmap
cell_idx = (cell_ixy & 0xFF0000) >> 16
cell_xsize = (cell_ixy & 0xFF00) >> 8
cell_ysize = cell_ixy & 0xFF
cell_x, cell_y = cell_idx % cell_xsize, cell_idx / cell_xsize
cell_w, cell_h = bitmap.width / cell_xsize, bitmap.height / cell_ysize
@src_rect = Rect.new(cell_x * cell_w, cell_y * cell_h, cell_w, cell_h)
@off_x = offX + 16 - (center_type % 3 - 1) * cell_w / 2
@off_y = offY + 16 - (2 - center_type / 3) * cell_h / 2
@rect_active = cell_xsize > 1
@delta_alpha = alpha_dinx >> 24
@alpha = (alpha_dinx & 0xFF0000) >> 16
@min_alpha = (alpha_dinx & 0xFF00) >> 8
@max_alpha = alpha_dinx & 0xFF
if @min_alpha > @max_alpha
@min_alpha, @max_alpha = @max_alpha, @min_alpha
end
end
def display_at(target_bitmap)
self.alpha_update
return if @alpha == 0
dx = (@event.real_x - $game_map.display_x + 3) / 4 + @off_x
return if dx >= target_bitmap.width #left
return if dx + @src_rect.width - 1 <= 0 #right
dy = (@event.real_y - $game_map.display_y + 3) / 4 + @off_y
return if dy >= target_bitmap.height #top
return if dy + @src_rect.height - 1 <= 0 #bottom
LIGHT::Mul.call(target_bitmap, dx, dy, @bitmap, @src_rect, @alpha)
end
def alpha_update
if @delta_alpha != 0
@alpha += @delta_alpha
if @alpha > @max_alpha
@alpha, @delta_alpha = @max_alpha, -@delta_alpha
end
if @alpha < @min_alpha
@alpha, @delta_alpha = @min_alpha, -@delta_alpha
end
end
end
def src_rect_update
if @rect_active == true
@src_rect.x += @src_rect.width
@src_rect.x = 0 if @src_rect.x >= @bitmap.width
end
end
def bitmap_dispose
@bitmap.dispose
end
end
class LightRenderTarget
def initialize(viewport)
@alpha = -1
self.alpha = 128
return if $game_map.light_switch == false
@rt = Sprite.new(viewport)
@target = Bitmap.new(viewport.rect.width, viewport.rect.height)
@rt.bitmap = @target
@rt.blend_type = 2
@rt.z = 1000
end
def alpha=(new_alpha)
return if @alpha == new_alpha
@alpha = new_alpha < 0 ? 0 : (new_alpha > 255 ? 255 : new_alpha)
end
def update
return if $game_map.light_switch == false
return if @alpha == 0
if Graphics.frame_count % LIGHT::Light_Effect_Rect_Frame == 0
$game_map.light_data.each {|i| i.src_rect_update}
end
LIGHT::Full.call(@target, @alpha)
$game_map.light_data.each {|i| i.display_at(@target)}
end
def dispose
if @target != nil
@target.dispose
@rt.dispose
@target = nil
end
LIGHT.cache_clear
end
end
class Interpreter
include LIGHT::Macro
end
class Game_Player
include LIGHT::Interface
def light_on(*args)
@light_data ||= []
self.set_light(*args)
end
# 其实类似手电筒,根据方向调整 center_type, off_x, off_y, cell_idx就可以实现
end
#———以下代码有大部分RMXP原代码,建议直接添加至原代码———
class Game_Map
attr_reader :light_data
attr_reader :light_switch
#--------------------------------------------------------------------------
# ● 初始化条件
#--------------------------------------------------------------------------
def initialize
@map_id = 0
@display_x = 0
@display_y = 0
@light_data = []
@light_switch = false
end
#--------------------------------------------------------------------------
# ● 设置
# map_id : 地图 ID
#--------------------------------------------------------------------------
def setup(map_id)
# 地图 ID 记录到 @map_id
@map_id = map_id
# 地图文件装载后、设置到 @map
@map = load_data(sprintf("Data/Map%03d.rxdata", @map_id))
# 定义实例变量设置地图元件信息
tileset = $data_tilesets[@map.tileset_id]
@tileset_name = tileset.tileset_name
@autotile_names = tileset.autotile_names
@panorama_name = tileset.panorama_name
@panorama_hue = tileset.panorama_hue
@fog_name = tileset.fog_name
@fog_hue = tileset.fog_hue
@fog_opacity = tileset.fog_opacity
@fog_blend_type = tileset.fog_blend_type
@fog_zoom = tileset.fog_zoom
@fog_sx = tileset.fog_sx
@fog_sy = tileset.fog_sy
@battleback_name = tileset.battleback_name
@passages = tileset.passages
@priorities = tileset.priorities
@terrain_tags = tileset.terrain_tags
# 初始化显示坐标
@display_x = 0
@display_y = 0
# 清除刷新要求标志
@need_refresh = false
# 释放上一地图的灯光对象
@light_data.each{|i| i.bitmap_dispose}
@light_data.clear
# 设置地图事件数据
@events = {}
for i in @map.events.keys
@events[i] = Game_Event.new(@map_id, @map.events[i])
end
@light_switch = !@light_data.empty?
# 设置公共事件数据
@common_events = {}
for i in 1...$data_common_events.size
@common_events[i] = Game_CommonEvent.new(i)
end
# 初始化雾的各种信息
@fog_ox = 0
@fog_oy = 0
@fog_tone = Tone.new(0, 0, 0, 0)
@fog_tone_target = Tone.new(0, 0, 0, 0)
@fog_tone_duration = 0
@fog_opacity_duration = 0
@fog_opacity_target = 0
# 初始化滚动信息
@scroll_direction = 2
@scroll_rest = 0
@scroll_speed = 4
end
end
class Game_Event
include LIGHT::Macro
include LIGHT::Interface
# !!注释即代码,不能乱写!!
# 只在“第一个指令块”有效。
# 标志:事件当前页的第一条指令set_light(...);
def refresh_light
if @list
if @list[0].code == 108
if (params = @list[0].parameters[0]).include?(LIGHT::Flag)
i, scripts = 1, params.dup
while (@list[i].code == 408)
scripts << @list[i].parameters[0]
i += 1
end
self.light_erase
eval(scripts)
end
end
end
end
#--------------------------------------------------------------------------
# ● 刷新
#--------------------------------------------------------------------------
def refresh
# 初始化本地变量 new_page
new_page = nil
# 无法暂时消失的情况下
unless @erased
# 从编号大的事件页按顺序调查
for page in @event.pages.reverse
# 可以参考事件条件 c
c = page.condition
# 确认开关条件 1
if c.switch1_valid
if $game_switches[c.switch1_id] == false
next
end
end
# 确认开关条件 2
if c.switch2_valid
if $game_switches[c.switch2_id] == false
next
end
end
# 确认变量条件
if c.variable_valid
if $game_variables[c.variable_id] < c.variable_value
next
end
end
# 确认独立开关条件
if c.self_switch_valid
key = [@map_id, @event.id, c.self_switch_ch]
if $game_self_switches[key] != true
next
end
end
# 设置本地变量 new_page
new_page = page
# 跳出循环
break
end
end
# 与上次同一事件页的情况下
if new_page == @page
# 过程结束
return
end
# @page 设置为现在的事件页
@page = new_page
# 清除启动中标志
clear_starting
# 没有满足条件的页面的时候
if @page == nil
# 设置各实例变量
@tile_id = 0
@character_name = ""
@character_hue = 0
@move_type = 0
@through = true
@trigger = nil
@list = nil
@interpreter = nil
# 过程结束
return
end
# 设置各实例变量
@tile_id = @page.graphic.tile_id
@character_name = @page.graphic.character_name
@character_hue = @page.graphic.character_hue
if @original_direction != @page.graphic.direction
@direction = @page.graphic.direction
@original_direction = @direction
@prelock_direction = 0
end
if @original_pattern != @page.graphic.pattern
@pattern = @page.graphic.pattern
@original_pattern = @pattern
end
@opacity = @page.graphic.opacity
@blend_type = @page.graphic.blend_type
@move_type = @page.move_type
@move_speed = @page.move_speed
@move_frequency = @page.move_frequency
@move_route = @page.move_route
@move_route_index = 0
@move_route_forcing = false
@walk_anime = @page.walk_anime
@step_anime = @page.step_anime
@direction_fix = @page.direction_fix
@through = @page.through
@always_on_top = @page.always_on_top
@trigger = @page.trigger
@list = @page.list
@interpreter = nil
self.refresh_light
# 目标是 [并行处理] 的情况下
if @trigger == 4
# 生成并行处理用解释器
@interpreter = Interpreter.new
end
# 自动事件启动判定
check_event_trigger_auto
end
end
class Spriteset_Map
#--------------------------------------------------------------------------
# ● 初始化对像
#--------------------------------------------------------------------------
def initialize
# 生成显示端口
@viewport1 = Viewport.new(0, 0, 640, 480)
@viewport2 = Viewport.new(0, 0, 640, 480)
@viewport3 = Viewport.new(0, 0, 640, 480)
@viewport2.z = 200
@viewport3.z = 5000
# 生成元件地图
@tilemap = Tilemap.new(@viewport1)
@tilemap.tileset = RPG::Cache.tileset($game_map.tileset_name)
for i in 0..6
autotile_name = $game_map.autotile_names[i]
@tilemap.autotiles[i] = RPG::Cache.autotile(autotile_name)
end
@tilemap.map_data = $game_map.data
@tilemap.priorities = $game_map.priorities
# 生成远景平面
@panorama = Plane.new(@viewport1)
@panorama.z = -1000
# 生成雾平面
@fog = Plane.new(@viewport1)
@fog.z = 3000
# 生成角色活动块
@character_sprites = []
for i in $game_map.events.keys.sort
sprite = Sprite_Character.new(@viewport1, $game_map.events[i])
@character_sprites.push(sprite)
end
@character_sprites.push(Sprite_Character.new(@viewport1, $game_player))
# 生成天气
@weather = RPG::Weather.new(@viewport1)
@lights = LightRenderTarget.new(@viewport1)
# 生成图片
@picture_sprites = []
for i in 1..50
@picture_sprites.push(Sprite_Picture.new(@viewport2,
$game_screen.pictures[i]))
end
# 生成计时器块
@timer_sprite = Sprite_Timer.new
# 刷新画面
update
end
#--------------------------------------------------------------------------
# ● 释放
#--------------------------------------------------------------------------
def dispose
# 释放元件地图
@tilemap.tileset.dispose
for i in 0..6
@tilemap.autotiles[i].dispose
end
@tilemap.dispose
# 释放远景平面
@panorama.dispose
# 释放雾平面
@fog.dispose
# 释放角色活动块
for sprite in @character_sprites
sprite.dispose
end
@lights.dispose
# 释放天候
@weather.dispose
# 释放图片
for sprite in @picture_sprites
sprite.dispose
end
# 释放计时器块
@timer_sprite.dispose
# 释放显示端口
@viewport1.dispose
@viewport2.dispose
@viewport3.dispose
end
#--------------------------------------------------------------------------
# ● 刷新画面
#--------------------------------------------------------------------------
def update
# 远景与现在的情况有差异发生的情况下
if @panorama_name != $game_map.panorama_name or
@panorama_hue != $game_map.panorama_hue
@panorama_name = $game_map.panorama_name
@panorama_hue = $game_map.panorama_hue
if @panorama.bitmap != nil
@panorama.bitmap.dispose
@panorama.bitmap = nil
end
if @panorama_name != ""
@panorama.bitmap = RPG::Cache.panorama(@panorama_name, @panorama_hue)
end
Graphics.frame_reset
end
# 雾与现在的情况有差异的情况下
if @fog_name != $game_map.fog_name or @fog_hue != $game_map.fog_hue
@fog_name = $game_map.fog_name
@fog_hue = $game_map.fog_hue
if @fog.bitmap != nil
@fog.bitmap.dispose
@fog.bitmap = nil
end
if @fog_name != ""
@fog.bitmap = RPG::Cache.fog(@fog_name, @fog_hue)
end
Graphics.frame_reset
end
# 刷新元件地图
@tilemap.ox = $game_map.display_x / 4
@tilemap.oy = $game_map.display_y / 4
@tilemap.update
# 刷新远景平面
@panorama.ox = $game_map.display_x / 8
@panorama.oy = $game_map.display_y / 8
# 刷新雾平面
@fog.zoom_x = $game_map.fog_zoom / 100.0
@fog.zoom_y = $game_map.fog_zoom / 100.0
@fog.opacity = $game_map.fog_opacity
@fog.blend_type = $game_map.fog_blend_type
@fog.ox = $game_map.display_x / 4 + $game_map.fog_ox
@fog.oy = $game_map.display_y / 4 + $game_map.fog_oy
@fog.tone = $game_map.fog_tone
# 刷新角色活动块
for sprite in @character_sprites
sprite.update
end
# 刷新天候图形
@weather.type = $game_screen.weather_type
@weather.max = $game_screen.weather_max
@weather.ox = $game_map.display_x / 4
@weather.oy = $game_map.display_y / 4
@weather.update
@lights.update
# 刷新图片
for sprite in @picture_sprites
sprite.update
end
# 刷新计时器块
@timer_sprite.update
# 设置画面的色调与震动位置
@viewport1.tone = $game_screen.tone
@viewport1.ox = $game_screen.shake
# 设置画面的闪烁色
@viewport3.color = $game_screen.flash_color
# 刷新显示端口
@viewport1.update
@viewport3.update
end
end
更新:bitmap_light_mul 优化计算精度,效率较之前损失10%左右,目前是tktk_bitmap.dll 类似效果API的 13-15倍。
新增 RMXP图书馆 【移植】烛光系统(VA -> XP) 脚本 tktk_bitmap.dll 替换成 Light.dll,原工程自行下载。
=begin HN_Light version 1.0.1.0 for VX Ace by 半生 [url]http://www.tktkgame.com[/url] 要HN_RG_BITMAP(ver 0.1.2.1以降) 2012/01/08 ver 1.0.1.2 队列歩行の仲间に対応 2015/04/25 Xp移植(ver 1.0) By RyanBern 2015/12/20 ver 1.1 Z 坐标修正 && 战斗测试 BUG 修复 2018/02/11 ver 1.2 增加控制黑暗不透明度的变量 =end # 注释掉的为原代码,替换代码都比原代码快 class Bitmap; def to_int; self.__id__; end; end class Rect; def to_int; self.__id__; end; end # ----- 在这里设定----- module HN_Light # 简略化0:(精细)~2:(粗暴,负荷轻) SIMPLIFY = 2 # 表示黑暗处的不透明度的变量号码 # 变量的数值为0-255,越大则不可见度越高 DARK_OPACITY_VAR = 11 # 玩家的烛光类型使用的变量号码 PLAYER_LIGHT_TYPE = 12 # 黑暗判断上使用的开关 DARK_SWITCH = 11 # 烛光事件识别用的正规表达式 REGEX_LIGHT = /@LIGHT(\d+)/ # 烛光图像的目录 LIGHT_IMG_DIR = "Graphics/Pictures/" # 烛光Bitmap设定 LIGHTS = [ # [文件名 ,单元数, 放大率, Y偏移值, 色相] ["light1", 1, 2.0, 0, 0], ["light2", 1, 1.0, 0, 0], ["light3", 1, 0.8, 0, 0], ["light4", 1, 1.0, -16, 0], ["light5", 1, 2.0, 0, 0], ["light6", 1, 1.0, 0, 0], ["light7", 1, 3.0, -16, 0], ["light1", 1, 0.5, 0, 0], ["light6", 1, 2.0, 0, 0], ] dll = "Light.dll" Stretch = Win32API.new(dll, 'bitmap_stretch_move', 'LL', 'L') Mul = Win32API.new(dll, 'bitmap_light_mul', 'LLLLLL', 'L') Full = Win32API.new(dll, 'bitmap_full_white_alpha', 'LL', 'L') end # ----- 在这里设定 ----- module HN_Light # 事件mix-in用 module LightEvent attr_reader :light_type def initialize super() @light_type = 0 end def check_light @light_type = 0 return if @list.nil? @list.each do |command| break if @light_type > 0 if command.code == 108 or command.code == 408 command.parameters.each do |line| if line =~ REGEX_LIGHT @light_type = $1.to_i break end end end end # END @list.each end end # END module LightEvent class Light attr_reader :bitmap attr_reader :cells attr_reader :width attr_reader :height attr_reader :ox attr_reader :oy def initialize(light_type, s_zoom = 1) light = LIGHTS[light_type - 1] if light.nil? # 本来不应该来这里 @bitmap = Bitmap.new(32, 32) @cells = 1 @zoom = 1.0 @oy = 16 @ox = 16 @width = 32 @height = 32 else @bitmap = Bitmap.new(LIGHT_IMG_DIR + light[0]) #@bitmap.invert() @cells = light[1].to_i @cells = 1 if (@cells < 1 or @cells > @bitmap.width) @zoom = light[2].to_f @zoom = 1.0 if @zoom <= 0.0 @zoom /= s_zoom @width = @bitmap.width / @cells @height = @bitmap.height # 缩放处理 if @zoom != 1.0 new_width = (@width * @zoom).round new_height = (@height * @zoom).round if new_width * new_height < 1 @zoom = 1.0 else @width = new_width @height = new_height new_bitmap = Bitmap.new(@width * @cells, @height) #new_bitmap.stretch_blt(new_bitmap.rect,@bitmap, @bitmap.rect) HN_Light::Stretch.call(new_bitmap, @bitmap) @bitmap.dispose @bitmap = new_bitmap end end @ox = @width / 2 @oy = @height / 2 - light[3].to_i / s_zoom # 色相変换 if ( (hue = light[4].to_i) != 0) @bitmap.hue_change(hue) end end end # End def initialize # 色调转换 def dispose @bitmap.dispose @bitmap = nil end end end class Game_Event include HN_Light::LightEvent alias :_hn_light__setup :refresh unless method_defined?(:_hn_light__setup) def refresh _hn_light__setup check_light() end end class Game_Player def light_type return $game_variables[HN_Light::PLAYER_LIGHT_TYPE] end end class Game_Map attr_reader :light_events # 更新烛光事件列表 def refresh_lights @light_events = [] @events.values.each do |event| if (event.light_type > 0) @light_events.push(event) end end end alias :_hn_light__setup_events :setup unless method_defined?(:_hn_light__setup_events) def setup(map_id) _hn_light__setup_events(map_id) refresh_lights() if @map_id > 0 end alias :_hn_light__refresh :refresh unless method_defined?(:_hn_light__refresh) def refresh _hn_light__refresh() refresh_lights() if @map_id > 0 end end class Sprite_Dark < Sprite @@base_color = Color.new(255,255,255,192) def initialize(viewport = nil) super(viewport) @width = 640 @height = 480 case HN_Light::SIMPLIFY when 1 @zoom = 2 when 2 @zoom = 4 else @zoom = 1 end @width /= @zoom @height /= @zoom self.zoom_x = @zoom.to_f self.zoom_y = @zoom.to_f self.bitmap = Bitmap.new(@width, @height) self.bitmap.fill_rect(self.bitmap.rect, @@base_color) self.blend_type = 2 # 混合型(减算) self.z = 800 self.visible = false @light_cache = {} end # 追加烛光 def add_light(charactor) return if charactor.nil? light_type = charactor.light_type return if (light_type < 1 or light_type > HN_Light::LIGHTS.size) unless @light_cache.key?(light_type) @light_cache[light_type] = HN_Light::Light.new(light_type, @zoom) end light = @light_cache[light_type] # 画面外什麽都不做 if @zoom == 1 return if (charactor.screen_x < 0 - light.width + light.ox) return if (charactor.screen_x > @width + light.ox) return if (charactor.screen_y < 0 - light.height + light.oy) return if (charactor.screen_y > @height + light.oy) else return if (charactor.screen_x < 0 - (light.width + light.ox) * @zoom) return if (charactor.screen_x > (@width + light.ox) * @zoom) return if (charactor.screen_y < 0 - (light.height + light.oy) * @zoom) return if (charactor.screen_y > (@height + light.oy) * @zoom) end # 动画判定 if light.cells > 1 index = (Graphics.frame_count / 4) % light.cells rect = Rect.new(index * light.width , 0, light.width, light.height) else rect = light.bitmap.rect end if @zoom != 1 p_x = charactor.screen_x / @zoom - light.ox p_y = (charactor.screen_y - 16) / @zoom - light.oy else p_x = charactor.screen_x - light.ox p_y = charactor.screen_y - 16 - light.oy end # 乗算合成(3) #self.bitmap.blend_blt(p_x, p_y, light.bitmap, rect, 3) HN_Light::Mul.call(self.bitmap, p_x, p_y, light.bitmap, rect, 255) end def refresh #self.bitmap.fill_rect(self.bitmap.rect, @@base_color) HN_Light::Full.call(self.bitmap, @@base_color.alpha.to_i) $game_map.light_events.each do |event| next if HN_Light::LIGHTS[event.light_type - 1].nil? add_light(event) end add_light($game_player) end # 更新 def update super #@@base_color = Color.new(255, 255, 255, $game_variables[HN_Light::DARK_OPACITY_VAR]) @@base_color.alpha = $game_variables[HN_Light::DARK_OPACITY_VAR] refresh() end #-------------------------------------------------------------------------- # ● 解放 #-------------------------------------------------------------------------- def dispose self.bitmap.dispose @light_cache.values.each do |light| light.dispose end super end end class Spriteset_Map # 动画判定 def create_dark @dark_sprite = Sprite_Dark.new(@viewport1) end # 更新黑暗Sprite def update_dark if (@dark_sprite.visible = $game_switches[HN_Light::DARK_SWITCH]) @dark_sprite.update end end # 破弃黑暗Sprite def dispose_dark @dark_sprite.dispose end # 初期化 alias :_dark__initialize :initialize unless private_method_defined?(:_dark__initialize) def initialize _dark__initialize() create_dark() update_dark() end # 更新 alias :_dark__update :update unless method_defined?(:_dark__update) def update _dark__update() update_dark() if !@dark_sprite.nil? and !@dark_sprite.disposed? end # 结束处理 alias :_dark__dispose :dispose unless method_defined?(:_dark__dispose) def dispose dispose_dark() _dark__dispose() end end
=begin
HN_Light version 1.0.1.0 for VX Ace
by 半生
[url]http://www.tktkgame.com[/url]
要HN_RG_BITMAP(ver 0.1.2.1以降)
2012/01/08 ver 1.0.1.2
队列歩行の仲间に対応
2015/04/25 Xp移植(ver 1.0)
By RyanBern
2015/12/20 ver 1.1
Z 坐标修正 && 战斗测试 BUG 修复
2018/02/11 ver 1.2
增加控制黑暗不透明度的变量
=end
# 注释掉的为原代码,替换代码都比原代码快
class Bitmap; def to_int; self.__id__; end; end
class Rect; def to_int; self.__id__; end; end
# ----- 在这里设定-----
module HN_Light
# 简略化0:(精细)~2:(粗暴,负荷轻)
SIMPLIFY = 2
# 表示黑暗处的不透明度的变量号码
# 变量的数值为0-255,越大则不可见度越高
DARK_OPACITY_VAR = 11
# 玩家的烛光类型使用的变量号码
PLAYER_LIGHT_TYPE = 12
# 黑暗判断上使用的开关
DARK_SWITCH = 11
# 烛光事件识别用的正规表达式
REGEX_LIGHT = /@LIGHT(\d+)/
# 烛光图像的目录
LIGHT_IMG_DIR = "Graphics/Pictures/"
# 烛光Bitmap设定
LIGHTS = [
# [文件名 ,单元数, 放大率, Y偏移值, 色相]
["light1", 1, 2.0, 0, 0],
["light2", 1, 1.0, 0, 0],
["light3", 1, 0.8, 0, 0],
["light4", 1, 1.0, -16, 0],
["light5", 1, 2.0, 0, 0],
["light6", 1, 1.0, 0, 0],
["light7", 1, 3.0, -16, 0],
["light1", 1, 0.5, 0, 0],
["light6", 1, 2.0, 0, 0],
]
dll = "Light.dll"
Stretch = Win32API.new(dll, 'bitmap_stretch_move', 'LL', 'L')
Mul = Win32API.new(dll, 'bitmap_light_mul', 'LLLLLL', 'L')
Full = Win32API.new(dll, 'bitmap_full_white_alpha', 'LL', 'L')
end
# ----- 在这里设定 -----
module HN_Light
# 事件mix-in用
module LightEvent
attr_reader :light_type
def initialize
super()
@light_type = 0
end
def check_light
@light_type = 0
return if @list.nil?
@list.each do |command|
break if @light_type > 0
if command.code == 108 or command.code == 408
command.parameters.each do |line|
if line =~ REGEX_LIGHT
@light_type = $1.to_i
break
end
end
end
end # END @list.each
end
end # END module LightEvent
class Light
attr_reader :bitmap
attr_reader :cells
attr_reader :width
attr_reader :height
attr_reader :ox
attr_reader :oy
def initialize(light_type, s_zoom = 1)
light = LIGHTS[light_type - 1]
if light.nil?
# 本来不应该来这里
@bitmap = Bitmap.new(32, 32)
@cells = 1
@zoom = 1.0
@oy = 16
@ox = 16
@width = 32
@height = 32
else
@bitmap = Bitmap.new(LIGHT_IMG_DIR + light[0])
#@bitmap.invert()
@cells = light[1].to_i
@cells = 1 if (@cells < 1 or @cells > @bitmap.width)
@zoom = light[2].to_f
@zoom = 1.0 if @zoom <= 0.0
@zoom /= s_zoom
@width = @bitmap.width / @cells
@height = @bitmap.height
# 缩放处理
if @zoom != 1.0
new_width = (@width * @zoom).round
new_height = (@height * @zoom).round
if new_width * new_height < 1
@zoom = 1.0
else
@width = new_width
@height = new_height
new_bitmap = Bitmap.new(@width * @cells, @height)
#new_bitmap.stretch_blt(new_bitmap.rect,@bitmap, @bitmap.rect)
HN_Light::Stretch.call(new_bitmap, @bitmap)
@bitmap.dispose
@bitmap = new_bitmap
end
end
@ox = @width / 2
@oy = @height / 2 - light[3].to_i / s_zoom
# 色相変换
if ( (hue = light[4].to_i) != 0)
@bitmap.hue_change(hue)
end
end
end # End def initialize
# 色调转换
def dispose
@bitmap.dispose
@bitmap = nil
end
end
end
class Game_Event
include HN_Light::LightEvent
alias :_hn_light__setup :refresh unless method_defined?(:_hn_light__setup)
def refresh
_hn_light__setup
check_light()
end
end
class Game_Player
def light_type
return $game_variables[HN_Light::PLAYER_LIGHT_TYPE]
end
end
class Game_Map
attr_reader :light_events
# 更新烛光事件列表
def refresh_lights
@light_events = []
@events.values.each do |event|
if (event.light_type > 0)
@light_events.push(event)
end
end
end
alias :_hn_light__setup_events :setup unless method_defined?(:_hn_light__setup_events)
def setup(map_id)
_hn_light__setup_events(map_id)
refresh_lights() if @map_id > 0
end
alias :_hn_light__refresh :refresh unless method_defined?(:_hn_light__refresh)
def refresh
_hn_light__refresh()
refresh_lights() if @map_id > 0
end
end
class Sprite_Dark < Sprite
@@base_color = Color.new(255,255,255,192)
def initialize(viewport = nil)
super(viewport)
@width = 640
@height = 480
case HN_Light::SIMPLIFY
when 1
@zoom = 2
when 2
@zoom = 4
else
@zoom = 1
end
@width /= @zoom
@height /= @zoom
self.zoom_x = @zoom.to_f
self.zoom_y = @zoom.to_f
self.bitmap = Bitmap.new(@width, @height)
self.bitmap.fill_rect(self.bitmap.rect, @@base_color)
self.blend_type = 2 # 混合型(减算)
self.z = 800
self.visible = false
@light_cache = {}
end
# 追加烛光
def add_light(charactor)
return if charactor.nil?
light_type = charactor.light_type
return if (light_type < 1 or light_type > HN_Light::LIGHTS.size)
unless @light_cache.key?(light_type)
@light_cache[light_type] = HN_Light::Light.new(light_type, @zoom)
end
light = @light_cache[light_type]
# 画面外什麽都不做
if @zoom == 1
return if (charactor.screen_x < 0 - light.width + light.ox)
return if (charactor.screen_x > @width + light.ox)
return if (charactor.screen_y < 0 - light.height + light.oy)
return if (charactor.screen_y > @height + light.oy)
else
return if (charactor.screen_x < 0 - (light.width + light.ox) * @zoom)
return if (charactor.screen_x > (@width + light.ox) * @zoom)
return if (charactor.screen_y < 0 - (light.height + light.oy) * @zoom)
return if (charactor.screen_y > (@height + light.oy) * @zoom)
end
# 动画判定
if light.cells > 1
index = (Graphics.frame_count / 4) % light.cells
rect = Rect.new(index * light.width , 0, light.width, light.height)
else
rect = light.bitmap.rect
end
if @zoom != 1
p_x = charactor.screen_x / @zoom - light.ox
p_y = (charactor.screen_y - 16) / @zoom - light.oy
else
p_x = charactor.screen_x - light.ox
p_y = charactor.screen_y - 16 - light.oy
end
# 乗算合成(3)
#self.bitmap.blend_blt(p_x, p_y, light.bitmap, rect, 3)
HN_Light::Mul.call(self.bitmap, p_x, p_y, light.bitmap, rect, 255)
end
def refresh
#self.bitmap.fill_rect(self.bitmap.rect, @@base_color)
HN_Light::Full.call(self.bitmap, @@base_color.alpha.to_i)
$game_map.light_events.each do |event|
next if HN_Light::LIGHTS[event.light_type - 1].nil?
add_light(event)
end
add_light($game_player)
end
# 更新
def update
super
#@@base_color = Color.new(255, 255, 255, $game_variables[HN_Light::DARK_OPACITY_VAR])
@@base_color.alpha = $game_variables[HN_Light::DARK_OPACITY_VAR]
refresh()
end
#--------------------------------------------------------------------------
# ● 解放
#--------------------------------------------------------------------------
def dispose
self.bitmap.dispose
@light_cache.values.each do |light|
light.dispose
end
super
end
end
class Spriteset_Map
# 动画判定
def create_dark
@dark_sprite = Sprite_Dark.new(@viewport1)
end
# 更新黑暗Sprite
def update_dark
if (@dark_sprite.visible = $game_switches[HN_Light::DARK_SWITCH])
@dark_sprite.update
end
end
# 破弃黑暗Sprite
def dispose_dark
@dark_sprite.dispose
end
# 初期化
alias :_dark__initialize :initialize unless private_method_defined?(:_dark__initialize)
def initialize
_dark__initialize()
create_dark()
update_dark()
end
# 更新
alias :_dark__update :update unless method_defined?(:_dark__update)
def update
_dark__update()
update_dark() if !@dark_sprite.nil? and !@dark_sprite.disposed?
end
# 结束处理
alias :_dark__dispose :dispose unless method_defined?(:_dark__dispose)
def dispose
dispose_dark()
_dark__dispose()
end
end
|
|