重写“半生烛光”
整体还是很鸡肋,效果基本没变化,懒得做gif示意图了。烛火可以自定义颜色,支持不透明度变化实现明暗变化,API效率提升,代码是关于灯光效果的实现,关于交互自行修改添加吧。
Light.dllVS2017 C语言编写
RUBY 代码
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 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
returnif@alpha == 0
dx = (@event.real_x - $game_map.display_x + 3) / 4 + @off_x
returnif dx >= target_bitmap.width #left
returnif dx + @src_rect.width - 1 = target_bitmap.height #top
returnif dy + @src_rect.height - 1@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 = 0if@src_rect.x >= @bitmap.width
end
end
def bitmap_dispose
@bitmap.dispose
end
end
class LightRenderTarget
def initialize(viewport)
@alpha = -1
self.alpha = 128
returnif$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)
returnif@alpha == new_alpha
@alpha = new_alpha < 0 ? 0 : (new_alpha > 255 ? 255 : new_alpha)
end
def update
returnif$game_map.light_switch == false
returnif@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
includeLIGHT::Macro
end
class Game_Player
includeLIGHT::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 = Game_Event.new(@map_id, @map.events)
end
@light_switch = !@light_data.empty?
# 设置公共事件数据
@common_events = {}
for i in1...$data_common_events.size
@common_events = 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
includeLIGHT::Macro
includeLIGHT::Interface
# !!注释即代码,不能乱写!!
# 只在“第一个指令块”有效。
# 标志:事件当前页的第一条指令set_light(...);
def refresh_light
if@list
if@list.code == 108
if(params = @list.parameters).include?(LIGHT::Flag)
i, scripts = 1, params.dup
while(@list.code == 408)
scriptsXP) 脚本 tktk_bitmap.dll 替换成 Light.dll,原工程自行下载。
RUBY 代码
=begin
HN_Light version 1.0.1.0 for VX Ace
by 半生
http://www.tktkgame.com
要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
returnif@list.nil?
@list.eachdo |command|
breakif@light_type > 0
if command.code == 108or command.code == 408
command.parameters.eachdo |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
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)
#@bitmap.invert()
@cells = light.to_i
@cells = 1if(@cells < 1or@cells > @bitmap.width)
@zoom = light.to_f
@zoom = 1.0if@zoom0)
@light_events.push(event)
end
end
end
alias:_hn_light__setup_events:setupunless 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:refreshunless 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
caseHN_Light::SIMPLIFY
when1
@zoom = 2
when2
@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)
returnif charactor.nil?
light_type = charactor.light_type
returnif(light_type < 1or light_type > HN_Light::LIGHTS.size)
unless@light_cache.key?(light_type)
@light_cache = HN_Light::Light.new(light_type, @zoom)
end
light = @light_cache
# 画面外什麽都不做
if@zoom == 1
returnif(charactor.screen_x < 0- light.width + light.ox)
returnif(charactor.screen_x > @width + light.ox)
returnif(charactor.screen_y < 0 - light.height + light.oy)
returnif(charactor.screen_y > @height + light.oy)
else
returnif(charactor.screen_x < 0- (light.width + light.ox) * @zoom)
returnif(charactor.screen_x > (@width + light.ox)* @zoom)
returnif(charactor.screen_y < 0 - (light.height + light.oy) * @zoom)
returnif(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.eachdo |event|
nextifHN_Light::LIGHTS.nil?
add_light(event)
end
add_light($game_player)
end
# 更新
def update
super
#@@base_color = Color.new(255, 255, 255, $game_variables)
@@base_color.alpha = $game_variables
refresh()
end
#--------------------------------------------------------------------------
# ● 解放
#--------------------------------------------------------------------------
def dispose
self.bitmap.dispose
@light_cache.values.eachdo |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)
@dark_sprite.update
end
end
# 破弃黑暗Sprite
def dispose_dark
@dark_sprite.dispose
end
# 初期化
alias:_dark__initialize:initializeunless private_method_defined?(:_dark__initialize)
def initialize
_dark__initialize()
create_dark()
update_dark()
end
# 更新
alias:_dark__update:updateunless method_defined?(:_dark__update)
def update
_dark__update()
update_dark()if !@dark_sprite.nil? and !@dark_sprite.disposed?
end
# 结束处理
alias:_dark__dispose:disposeunless method_defined?(:_dark__dispose)
def dispose
dispose_dark()
_dark__dispose()
end
end
本帖来自P1论坛作者RPGzh500223,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:https://rpg.blue/forum.php?mod=viewthread&tid=491685若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。
页:
[1]