整体还是很鸡肋,效果基本没变化,懒得做gif示意图了。
烛火可以自定义颜色,支持不透明度变化实现明暗变化,API效率提升,代码是关于灯光效果的实现,关于交互自行修改添加吧。
Light.dll VS2017 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[i] = Game_Event.new(@map_id, @map.events[i])
- end
- @light_switch = !@light_data.empty?
- # 设置公共事件数据
- @common_events = {}
- for i in1...$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
- includeLIGHT::Macro
- includeLIGHT::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 XP) 脚本 tktk_bitmap.dll 替换成 Light.dll,原工程自行下载。
- RUBY 代码
- [code]=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
- 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[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 = 1if(@cells < 1or@cells > @bitmap.width)
- @zoom = light[2].to_f
- @zoom = 1.0if@zoom 0)
- @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[light_type] = HN_Light::Light.new(light_type, @zoom)
- end
- light = @light_cache[light_type]
- # 画面外什麽都不做
- 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[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.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[HN_Light::DARK_SWITCH])
- @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在线咨询功能删除,谢谢。