设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 1986|回复: 1
打印 上一主题 下一主题

[原创发布] 重写“半生烛光”

[复制链接]

Lv4.逐梦者

梦石
0
星屑
6483
在线时间
119 小时
注册时间
2020-1-8
帖子
234
跳转到指定楼层
1
发表于 2022-11-23 09:52:18 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 RPGzh500223 于 2022-11-25 12:08 编辑

整体还是很鸡肋,效果基本没变化,懒得做gif示意图了。
烛火可以自定义颜色,支持不透明度变化实现明暗变化,API效率提升,代码是关于灯光效果的实现,关于交互自行修改添加吧。
Light.dll  VS2017 C语言编写

RUBY 代码复制
  1. class Rect
  2.   def to_int
  3.     self.__id__
  4.   end
  5. end
  6.  
  7. class Bitmap
  8.   def to_int
  9.     self.__id__
  10.   end
  11. end
  12.  
  13.  
  14. module LIGHT
  15.   # 并不严谨的标志,但是方便
  16.   Flag = "set_light"
  17.  
  18.   Pic_Dir = "Graphics/Light_Textures"
  19.  
  20.   # 透明通道图片,有效值为alpha,填充的颜色能看清图形就好,建议黑色
  21.   Light_Type_Pic_Name = {
  22.     0 => "round.png"
  23.   }
  24.  
  25.   Light_Effect_Rect_Frame = 10
  26.  
  27.   dll = "Light.dll"
  28.  
  29.   # 源位图双线性插值缩放至目标位图(无混合)
  30.   # dst_bitmap_obj_id, src_bitmap_obj_id
  31.   Stretch = Win32API.new(dll, 'bitmap_stretch_move', 'LL', 'L')
  32.  
  33.   # ————灯光专用方法————
  34.   # 以纹理的alpha值进行颜色填充,再与黑色(0xFF000000)进行混合(Bitmap#blt)
  35.   # alpha: 0      <=   threshold[0..7]    <    threshold[8..15]     <=    255
  36.   # 颜色 :low_rgb24     |阈值下限|  HSL_gradient  |阈值上限|      high_rgb24  
  37.   # textutre_bitmap_obj_id
  38.   # high_rgb24    0..23位有效值
  39.   # low_rgb24     0..23位有效值   
  40.   #               该值为-1的话,单色(high_rgb24)填充,阈值无效
  41.   # alpha_threshold16   0..7位 阈值下限 (须小于) 8..15位 阈值上限  
  42.   Frgb2 = Win32API.new(dll, 'bitmap_full_rgb2_blt_black', 'LLLL', 'L')
  43.  
  44.   # 源位图区域与目标位图指定位置进行乘算叠加
  45.   # 计算:源RGB预乘opacity,反相后再与目标RGB乘算叠加,参数基本类似Btimap#blt
  46.   # dst_bitmap_obj_id, dx, dy,
  47.   # src_bitmap_obj_id, src_bitmap_rect_obj_id, opacity
  48.   Mul = Win32API.new(dll, 'bitmap_light_mul', 'LLLLLL', 'L')
  49.  
  50.   # 以指定alpha的白色对位图进行填充
  51.   # dst_bitmap_obj_id
  52.   # alpha8   0..7位有效值
  53.   Full = Win32API.new(dll, 'bitmap_full_white_alpha', 'LL', 'L')
  54.  
  55.  
  56.   @@cache = {}
  57.   def self.cache(type)
  58.     @@cache[type] ||= Bitmap.new(
  59.       File.join(Pic_Dir, Light_Type_Pic_Name[type] || Light_Type_Pic_Name[0]))   
  60.   end
  61.  
  62.   def self.cache_clear
  63.     @@cache.values.each {|bitmap| bitmap.dispose}
  64.     @@cache.clear
  65.   end
  66.  
  67.  
  68.   module Macro
  69.     def rgb2int(r, g, b)
  70.       r << 16 | g << 8 | b
  71.     end  
  72.     alias RGB rgb2int
  73.     alias IXY rgb2int
  74.  
  75.     def argb2int(a, r, g, b)
  76.       a << 24 | r << 16 | g << 8 | b
  77.     end
  78.     alias DINX argb2int
  79.   end
  80.  
  81.   module Interface
  82.     def light_erase
  83.       @light_data ||= []
  84.       @light_data.each do |i|
  85.         $game_map.light_data.delete(i)
  86.         i.bitmap_dispose
  87.       end
  88.       @light_data.clear
  89.     end
  90.  
  91.     # type          纹理样式,参见 Light_Type_Pic_Name
  92.     # rgb24_high/low/threshold   颜色值相关参数,参见 Frgb2
  93.  
  94.     # zoom_x/y      缩放系数
  95.     # off_x/y       偏移
  96.     # center_type   对齐中心位置,参考小键盘数字的位置
  97.  
  98.     # alpha_delta/ini/min/max   不透明度相关参数,“一个参数”
  99.  
  100.     # cell_idx/xsize/ysize      帧动画的参数,“一个参数”   
  101.     #               效果参考 RMXP人物【停止动画】
  102.     #               单元序列,自左向右,从上到下,4 * 4如下所示
  103.     #                    0 —— (xsize-1)
  104.     #                0     0  1  2  3
  105.     #                |     4  5  6  7
  106.     #                |     8  9  A  B
  107.     #             ysize-1  C  D  E  F
  108.  
  109.     def set_light(type = 0, high_rgb24 = 0xFFFFFF, low_rgb24 = -1,
  110.       rgb_threshold = 0xFF00, zoom_x = 1, zoom_y = 1, off_x = 0, off_y = 0,
  111.       center_type = 5, alpha_dinx = 0x00FFFFFF, cell_ixy = 0x000101)
  112.  
  113.       texture = LIGHT.cache(type)
  114.  
  115.       w, h = (texture.width * zoom_x).to_i, (texture.height * zoom_y).to_i
  116.       return if w < 2 || h < 2
  117.  
  118.       if w == texture.width && h == texture.height
  119.         bitmap = texture.clone
  120.       else
  121.         bitmap = Bitmap.new(w, h)
  122.         LIGHT::Stretch.call(bitmap, texture)
  123.       end
  124.  
  125.       LIGHT::Frgb2.call(bitmap, high_rgb24, low_rgb24, rgb_threshold)
  126.  
  127.       light = LightEffect.new(self, bitmap, off_x, off_y, center_type,
  128.         alpha_dinx, cell_ixy)
  129.  
  130.       @light_data << light
  131.       $game_map.light_data << light
  132.     end
  133.   end
  134. end
  135.  
  136.  
  137. class LightEffect
  138.  
  139.   def initialize(event, bitmap, offX, offY, center_type, alpha_dinx, cell_ixy)
  140.  
  141.     @event, @bitmap = event, bitmap
  142.  
  143.     cell_idx = (cell_ixy & 0xFF0000) >> 16
  144.     cell_xsize = (cell_ixy & 0xFF00) >> 8
  145.     cell_ysize = cell_ixy & 0xFF
  146.  
  147.     cell_x, cell_y = cell_idx % cell_xsize, cell_idx / cell_xsize
  148.     cell_w, cell_h = bitmap.width / cell_xsize, bitmap.height / cell_ysize
  149.     @src_rect = Rect.new(cell_x * cell_w, cell_y * cell_h, cell_w, cell_h)
  150.  
  151.     @off_x = offX + 16 - (center_type % 3 - 1) * cell_w / 2
  152.     @off_y = offY + 16 - (2 - center_type / 3) * cell_h / 2
  153.  
  154.     @rect_active = cell_xsize > 1   
  155.  
  156.     @delta_alpha = alpha_dinx >> 24
  157.     @alpha = (alpha_dinx & 0xFF0000) >> 16
  158.     @min_alpha = (alpha_dinx & 0xFF00) >> 8
  159.     @max_alpha = alpha_dinx & 0xFF
  160.     if @min_alpha > @max_alpha
  161.       @min_alpha, @max_alpha = @max_alpha, @min_alpha
  162.     end
  163.   end
  164.  
  165.   def display_at(target_bitmap)
  166.     self.alpha_update
  167.     return if @alpha == 0
  168.  
  169.     dx = (@event.real_x - $game_map.display_x + 3) / 4 + @off_x
  170.     return if dx >= target_bitmap.width            #left
  171.     return if dx + @src_rect.width - 1 <= 0        #right
  172.  
  173.     dy = (@event.real_y - $game_map.display_y + 3) / 4 + @off_y
  174.     return if dy >= target_bitmap.height           #top
  175.     return if dy + @src_rect.height - 1 <= 0       #bottom
  176.  
  177.     LIGHT::Mul.call(target_bitmap, dx, dy, @bitmap, @src_rect, @alpha)
  178.   end
  179.  
  180.   def alpha_update
  181.     if @delta_alpha != 0
  182.       @alpha += @delta_alpha
  183.       if @alpha > @max_alpha
  184.         @alpha, @delta_alpha = @max_alpha, -@delta_alpha
  185.       end
  186.       if @alpha < @min_alpha
  187.         @alpha, @delta_alpha = @min_alpha, -@delta_alpha
  188.       end
  189.     end
  190.   end
  191.  
  192.   def src_rect_update
  193.     if @rect_active == true
  194.       @src_rect.x += @src_rect.width
  195.       @src_rect.x = 0 if @src_rect.x >= @bitmap.width
  196.     end
  197.   end
  198.  
  199.   def bitmap_dispose
  200.     @bitmap.dispose
  201.   end
  202. end
  203.  
  204.  
  205. class LightRenderTarget
  206.  
  207.   def initialize(viewport)
  208.     @alpha = -1
  209.     self.alpha = 128
  210.  
  211.     return if $game_map.light_switch == false
  212.  
  213.     @rt = Sprite.new(viewport)
  214.     @target = Bitmap.new(viewport.rect.width, viewport.rect.height)
  215.     @rt.bitmap = @target
  216.     @rt.blend_type = 2
  217.     @rt.z = 1000
  218.   end
  219.  
  220.   def alpha=(new_alpha)
  221.     return if @alpha == new_alpha
  222.     @alpha = new_alpha < 0 ? 0 : (new_alpha > 255 ? 255 : new_alpha)
  223.   end
  224.  
  225.   def update
  226.     return if $game_map.light_switch == false
  227.     return if @alpha == 0
  228.  
  229.     if Graphics.frame_count % LIGHT::Light_Effect_Rect_Frame == 0
  230.       $game_map.light_data.each {|i| i.src_rect_update}  
  231.     end
  232.  
  233.     LIGHT::Full.call(@target, @alpha)   
  234.     $game_map.light_data.each {|i| i.display_at(@target)}
  235.   end
  236.  
  237.   def dispose
  238.     if @target != nil
  239.       @target.dispose
  240.       @rt.dispose
  241.       @target = nil
  242.     end
  243.  
  244.     LIGHT.cache_clear
  245.   end
  246. end
  247.  
  248. class Interpreter
  249.   include LIGHT::Macro
  250. end
  251.  
  252. class Game_Player
  253.   include LIGHT::Interface
  254.  
  255.   def light_on(*args)
  256.     @light_data ||= []
  257.     self.set_light(*args)
  258.   end
  259.  
  260.   # 其实类似手电筒,根据方向调整 center_type, off_x, off_y, cell_idx就可以实现
  261. end
  262.  
  263.  
  264. #———以下代码有大部分RMXP原代码,建议直接添加至原代码———
  265.  
  266. class Game_Map
  267.   attr_reader   :light_data
  268.   attr_reader   :light_switch
  269.   #--------------------------------------------------------------------------
  270.   # ● 初始化条件
  271.   #--------------------------------------------------------------------------
  272.   def initialize
  273.     @map_id = 0
  274.     @display_x = 0
  275.     @display_y = 0
  276.  
  277.     @light_data = []
  278.     @light_switch = false
  279.   end
  280.   #--------------------------------------------------------------------------
  281.   # ● 设置
  282.   #     map_id : 地图 ID
  283.   #--------------------------------------------------------------------------
  284.   def setup(map_id)
  285.     # 地图 ID 记录到 @map_id
  286.     @map_id = map_id
  287.     # 地图文件装载后、设置到 @map
  288.     @map = load_data(sprintf("Data/Map%03d.rxdata", @map_id))
  289.     # 定义实例变量设置地图元件信息
  290.     tileset = $data_tilesets[@map.tileset_id]
  291.     @tileset_name = tileset.tileset_name
  292.     @autotile_names = tileset.autotile_names
  293.     @panorama_name = tileset.panorama_name
  294.     @panorama_hue = tileset.panorama_hue
  295.     @fog_name = tileset.fog_name
  296.     @fog_hue = tileset.fog_hue
  297.     @fog_opacity = tileset.fog_opacity
  298.     @fog_blend_type = tileset.fog_blend_type
  299.     @fog_zoom = tileset.fog_zoom
  300.     @fog_sx = tileset.fog_sx
  301.     @fog_sy = tileset.fog_sy
  302.     @battleback_name = tileset.battleback_name
  303.     @passages = tileset.passages
  304.     @priorities = tileset.priorities
  305.     @terrain_tags = tileset.terrain_tags
  306.     # 初始化显示坐标
  307.     @display_x = 0
  308.     @display_y = 0
  309.     # 清除刷新要求标志
  310.     @need_refresh = false
  311.  
  312.     # 释放上一地图的灯光对象
  313.     @light_data.each{|i| i.bitmap_dispose}
  314.     @light_data.clear
  315.  
  316.     # 设置地图事件数据
  317.     @events = {}
  318.     for i in @map.events.keys
  319.       @events[i] = Game_Event.new(@map_id, @map.events[i])
  320.     end
  321.  
  322.     @light_switch = !@light_data.empty?
  323.  
  324.     # 设置公共事件数据
  325.     @common_events = {}
  326.     for i in 1...$data_common_events.size
  327.       @common_events[i] = Game_CommonEvent.new(i)
  328.     end
  329.     # 初始化雾的各种信息
  330.     @fog_ox = 0
  331.     @fog_oy = 0
  332.     @fog_tone = Tone.new(0, 0, 0, 0)
  333.     @fog_tone_target = Tone.new(0, 0, 0, 0)
  334.     @fog_tone_duration = 0
  335.     @fog_opacity_duration = 0
  336.     @fog_opacity_target = 0
  337.     # 初始化滚动信息
  338.     @scroll_direction = 2
  339.     @scroll_rest = 0
  340.     @scroll_speed = 4
  341.   end
  342. end
  343.  
  344.  
  345. class Game_Event
  346.   include LIGHT::Macro
  347.   include LIGHT::Interface
  348.  
  349.   # !!注释即代码,不能乱写!!
  350.   # 只在“第一个指令块”有效。
  351.   # 标志:事件当前页的第一条指令set_light(...);
  352.   def refresh_light
  353.     if @list
  354.       if @list[0].code == 108
  355.         if (params = @list[0].parameters[0]).include?(LIGHT::Flag)
  356.           i, scripts = 1, params.dup
  357.  
  358.           while (@list[i].code == 408)
  359.             scripts << @list[i].parameters[0]
  360.             i += 1
  361.           end
  362.  
  363.           self.light_erase
  364.           eval(scripts)
  365.         end
  366.       end
  367.     end
  368.   end
  369.  
  370.   #--------------------------------------------------------------------------
  371.   # ● 刷新
  372.   #--------------------------------------------------------------------------
  373.   def refresh
  374.     # 初始化本地变量 new_page
  375.     new_page = nil
  376.     # 无法暂时消失的情况下
  377.     unless @erased
  378.       # 从编号大的事件页按顺序调查
  379.       for page in @event.pages.reverse
  380.         # 可以参考事件条件 c
  381.         c = page.condition
  382.         # 确认开关条件 1
  383.         if c.switch1_valid
  384.           if $game_switches[c.switch1_id] == false
  385.             next
  386.           end
  387.         end
  388.         # 确认开关条件 2
  389.         if c.switch2_valid
  390.           if $game_switches[c.switch2_id] == false
  391.             next
  392.           end
  393.         end
  394.         # 确认变量条件
  395.         if c.variable_valid
  396.           if $game_variables[c.variable_id] < c.variable_value
  397.             next
  398.           end
  399.         end
  400.         # 确认独立开关条件
  401.         if c.self_switch_valid
  402.           key = [@map_id, @event.id, c.self_switch_ch]
  403.           if $game_self_switches[key] != true
  404.             next
  405.           end
  406.         end
  407.         # 设置本地变量 new_page
  408.         new_page = page
  409.         # 跳出循环
  410.         break
  411.       end
  412.     end
  413.     # 与上次同一事件页的情况下
  414.     if new_page == @page
  415.       # 过程结束
  416.       return
  417.     end
  418.     # @page 设置为现在的事件页
  419.     @page = new_page
  420.     # 清除启动中标志
  421.     clear_starting
  422.     # 没有满足条件的页面的时候
  423.     if @page == nil
  424.       # 设置各实例变量
  425.       @tile_id = 0
  426.       @character_name = ""
  427.       @character_hue = 0
  428.       @move_type = 0
  429.       @through = true
  430.       @trigger = nil
  431.       @list = nil
  432.       @interpreter = nil
  433.       # 过程结束
  434.       return
  435.     end
  436.     # 设置各实例变量
  437.     @tile_id = @page.graphic.tile_id
  438.     @character_name = @page.graphic.character_name
  439.     @character_hue = @page.graphic.character_hue
  440.     if @original_direction != @page.graphic.direction
  441.       @direction = @page.graphic.direction
  442.       @original_direction = @direction
  443.       @prelock_direction = 0
  444.     end
  445.     if @original_pattern != @page.graphic.pattern
  446.       @pattern = @page.graphic.pattern
  447.       @original_pattern = @pattern
  448.     end
  449.     @opacity = @page.graphic.opacity
  450.     @blend_type = @page.graphic.blend_type
  451.     @move_type = @page.move_type
  452.     @move_speed = @page.move_speed
  453.     @move_frequency = @page.move_frequency
  454.     @move_route = @page.move_route
  455.     @move_route_index = 0
  456.     @move_route_forcing = false
  457.     @walk_anime = @page.walk_anime
  458.     @step_anime = @page.step_anime
  459.     @direction_fix = @page.direction_fix
  460.     @through = @page.through
  461.     @always_on_top = @page.always_on_top
  462.     @trigger = @page.trigger
  463.     @list = @page.list
  464.     @interpreter = nil
  465.  
  466.     self.refresh_light
  467.  
  468.     # 目标是 [并行处理] 的情况下
  469.     if @trigger == 4
  470.       # 生成并行处理用解释器
  471.       @interpreter = Interpreter.new
  472.     end
  473.     # 自动事件启动判定
  474.     check_event_trigger_auto
  475.   end
  476. end
  477.  
  478.  
  479. class Spriteset_Map
  480.   #--------------------------------------------------------------------------
  481.   # ● 初始化对像
  482.   #--------------------------------------------------------------------------
  483.   def initialize
  484.     # 生成显示端口
  485.     @viewport1 = Viewport.new(0, 0, 640, 480)
  486.     @viewport2 = Viewport.new(0, 0, 640, 480)
  487.     @viewport3 = Viewport.new(0, 0, 640, 480)
  488.     @viewport2.z = 200
  489.     @viewport3.z = 5000
  490.     # 生成元件地图
  491.     @tilemap = Tilemap.new(@viewport1)
  492.     @tilemap.tileset = RPG::Cache.tileset($game_map.tileset_name)
  493.     for i in 0..6
  494.       autotile_name = $game_map.autotile_names[i]
  495.       @tilemap.autotiles[i] = RPG::Cache.autotile(autotile_name)
  496.     end
  497.     @tilemap.map_data = $game_map.data
  498.     @tilemap.priorities = $game_map.priorities
  499.     # 生成远景平面
  500.     @panorama = Plane.new(@viewport1)
  501.     @panorama.z = -1000
  502.     # 生成雾平面
  503.     @fog = Plane.new(@viewport1)
  504.     @fog.z = 3000
  505.     # 生成角色活动块
  506.     @character_sprites = []
  507.     for i in $game_map.events.keys.sort
  508.       sprite = Sprite_Character.new(@viewport1, $game_map.events[i])
  509.       @character_sprites.push(sprite)
  510.     end
  511.     @character_sprites.push(Sprite_Character.new(@viewport1, $game_player))
  512.     # 生成天气
  513.     @weather = RPG::Weather.new(@viewport1)
  514.  
  515.  
  516.     @lights = LightRenderTarget.new(@viewport1)
  517.  
  518.  
  519.     # 生成图片
  520.     @picture_sprites = []
  521.     for i in 1..50
  522.       @picture_sprites.push(Sprite_Picture.new(@viewport2,
  523.         $game_screen.pictures[i]))
  524.     end
  525.     # 生成计时器块
  526.     @timer_sprite = Sprite_Timer.new
  527.     # 刷新画面
  528.     update
  529.   end
  530.   #--------------------------------------------------------------------------
  531.   # ● 释放
  532.   #--------------------------------------------------------------------------
  533.   def dispose
  534.     # 释放元件地图
  535.     @tilemap.tileset.dispose
  536.     for i in 0..6
  537.       @tilemap.autotiles[i].dispose
  538.     end
  539.     @tilemap.dispose
  540.     # 释放远景平面
  541.     @panorama.dispose
  542.     # 释放雾平面
  543.     @fog.dispose
  544.     # 释放角色活动块
  545.     for sprite in @character_sprites
  546.       sprite.dispose
  547.     end
  548.  
  549.     @lights.dispose
  550.  
  551.     # 释放天候
  552.     @weather.dispose
  553.     # 释放图片
  554.     for sprite in @picture_sprites
  555.       sprite.dispose
  556.     end
  557.     # 释放计时器块
  558.     @timer_sprite.dispose
  559.     # 释放显示端口
  560.     @viewport1.dispose
  561.     @viewport2.dispose
  562.     @viewport3.dispose
  563.   end
  564.   #--------------------------------------------------------------------------
  565.   # ● 刷新画面
  566.   #--------------------------------------------------------------------------
  567.   def update
  568.     # 远景与现在的情况有差异发生的情况下
  569.     if @panorama_name != $game_map.panorama_name or
  570.        @panorama_hue != $game_map.panorama_hue
  571.       @panorama_name = $game_map.panorama_name
  572.       @panorama_hue = $game_map.panorama_hue
  573.       if @panorama.bitmap != nil
  574.         @panorama.bitmap.dispose
  575.         @panorama.bitmap = nil
  576.       end
  577.       if @panorama_name != ""
  578.         @panorama.bitmap = RPG::Cache.panorama(@panorama_name, @panorama_hue)
  579.       end
  580.       Graphics.frame_reset
  581.     end
  582.     # 雾与现在的情况有差异的情况下
  583.     if @fog_name != $game_map.fog_name or @fog_hue != $game_map.fog_hue
  584.       @fog_name = $game_map.fog_name
  585.       @fog_hue = $game_map.fog_hue
  586.       if @fog.bitmap != nil
  587.         @fog.bitmap.dispose
  588.         @fog.bitmap = nil
  589.       end
  590.       if @fog_name != ""
  591.         @fog.bitmap = RPG::Cache.fog(@fog_name, @fog_hue)
  592.       end
  593.       Graphics.frame_reset
  594.     end
  595.     # 刷新元件地图
  596.     @tilemap.ox = $game_map.display_x / 4
  597.     @tilemap.oy = $game_map.display_y / 4
  598.     @tilemap.update
  599.     # 刷新远景平面
  600.     @panorama.ox = $game_map.display_x / 8
  601.     @panorama.oy = $game_map.display_y / 8
  602.     # 刷新雾平面
  603.     @fog.zoom_x = $game_map.fog_zoom / 100.0
  604.     @fog.zoom_y = $game_map.fog_zoom / 100.0
  605.     @fog.opacity = $game_map.fog_opacity
  606.     @fog.blend_type = $game_map.fog_blend_type
  607.     @fog.ox = $game_map.display_x / 4 + $game_map.fog_ox
  608.     @fog.oy = $game_map.display_y / 4 + $game_map.fog_oy
  609.     @fog.tone = $game_map.fog_tone
  610.     # 刷新角色活动块
  611.     for sprite in @character_sprites
  612.       sprite.update
  613.     end
  614.     # 刷新天候图形
  615.     @weather.type = $game_screen.weather_type
  616.     @weather.max = $game_screen.weather_max
  617.     @weather.ox = $game_map.display_x / 4
  618.     @weather.oy = $game_map.display_y / 4
  619.     @weather.update
  620.  
  621.  
  622.     @lights.update
  623.  
  624.  
  625.     # 刷新图片
  626.     for sprite in @picture_sprites
  627.       sprite.update
  628.     end
  629.     # 刷新计时器块
  630.     @timer_sprite.update
  631.     # 设置画面的色调与震动位置
  632.     @viewport1.tone = $game_screen.tone
  633.     @viewport1.ox = $game_screen.shake
  634.     # 设置画面的闪烁色
  635.     @viewport3.color = $game_screen.flash_color
  636.     # 刷新显示端口
  637.     @viewport1.update
  638.     @viewport3.update
  639.   end
  640. end



更新:bitmap_light_mul 优化计算精度,效率较之前损失10%左右,目前是tktk_bitmap.dll 类似效果API的 13-15倍。
          新增 RMXP图书馆 【移植】烛光系统(VA -> XP) 脚本 tktk_bitmap.dll 替换成 Light.dll,原工程自行下载。
RUBY 代码复制
  1. =begin
  2.   HN_Light version 1.0.1.0 for VX Ace
  3.         by 半生
  4. [url]http://www.tktkgame.com[/url]
  5.  
  6.   要HN_RG_BITMAP(ver 0.1.2.1以降)
  7.  
  8. 2012/01/08 ver 1.0.1.2
  9.  队列歩行の仲间に対応
  10.  
  11. 2015/04/25 Xp移植(ver 1.0)
  12.   By RyanBern
  13.  
  14. 2015/12/20 ver 1.1
  15.   Z 坐标修正 && 战斗测试 BUG 修复
  16.  
  17. 2018/02/11 ver 1.2
  18.   增加控制黑暗不透明度的变量
  19.  
  20. =end
  21.  
  22.  
  23. # 注释掉的为原代码,替换代码都比原代码快
  24.  
  25.  
  26. class Bitmap; def to_int; self.__id__; end; end
  27. class Rect; def to_int; self.__id__; end; end
  28.  
  29. # ----- 在这里设定-----
  30. module HN_Light
  31.   # 简略化0:(精细)~2:(粗暴,负荷轻)
  32.   SIMPLIFY = 2
  33.  
  34.   # 表示黑暗处的不透明度的变量号码
  35.   # 变量的数值为0-255,越大则不可见度越高
  36.   DARK_OPACITY_VAR = 11
  37.  
  38.   # 玩家的烛光类型使用的变量号码
  39.   PLAYER_LIGHT_TYPE = 12
  40.  
  41.   # 黑暗判断上使用的开关
  42.   DARK_SWITCH = 11
  43.  
  44.   # 烛光事件识别用的正规表达式
  45.   REGEX_LIGHT = /@LIGHT(\d+)/
  46.  
  47.   # 烛光图像的目录
  48.   LIGHT_IMG_DIR = "Graphics/Pictures/"
  49.  
  50.   # 烛光Bitmap设定
  51.   LIGHTS = [
  52.   # [文件名  ,单元数, 放大率,  Y偏移值, 色相]
  53.     ["light1",     1,    2.0,        0,    0],
  54.     ["light2",     1,    1.0,        0,    0],
  55.     ["light3",     1,    0.8,        0,    0],
  56.     ["light4",     1,    1.0,      -16,    0],
  57.     ["light5",     1,    2.0,        0,    0],
  58.     ["light6",     1,    1.0,        0,    0],
  59.     ["light7",     1,    3.0,      -16,    0],
  60.     ["light1",     1,    0.5,        0,    0],
  61.     ["light6",     1,    2.0,        0,    0],
  62.   ]
  63.  
  64.   dll = "Light.dll"
  65.   Stretch = Win32API.new(dll, 'bitmap_stretch_move', 'LL', 'L')
  66.   Mul = Win32API.new(dll, 'bitmap_light_mul', 'LLLLLL', 'L')
  67.   Full = Win32API.new(dll, 'bitmap_full_white_alpha', 'LL', 'L')
  68. end
  69. #  ----- 在这里设定 -----
  70.  
  71. module HN_Light
  72.   # 事件mix-in用
  73.   module LightEvent
  74.     attr_reader :light_type
  75.     def initialize
  76.       super()
  77.       @light_type = 0
  78.     end
  79.  
  80.     def check_light
  81.       @light_type = 0
  82.       return if @list.nil?
  83.       @list.each do |command|
  84.         break if @light_type > 0
  85.         if command.code == 108 or command.code == 408
  86.           command.parameters.each do |line|
  87.             if line =~ REGEX_LIGHT
  88.               @light_type = $1.to_i
  89.               break
  90.             end
  91.           end
  92.         end
  93.       end # END @list.each
  94.     end
  95.  
  96.   end # END module LightEvent
  97.  
  98.  
  99.   class Light
  100.     attr_reader :bitmap
  101.     attr_reader :cells
  102.     attr_reader :width
  103.     attr_reader :height
  104.     attr_reader :ox
  105.     attr_reader :oy
  106.     def initialize(light_type, s_zoom = 1)
  107.       light = LIGHTS[light_type - 1]
  108.       if light.nil?
  109.         # 本来不应该来这里
  110.         @bitmap = Bitmap.new(32, 32)
  111.         @cells = 1
  112.         @zoom = 1.0
  113.         @oy = 16
  114.         @ox = 16
  115.         @width  = 32
  116.         @height = 32
  117.       else
  118.         @bitmap = Bitmap.new(LIGHT_IMG_DIR + light[0])
  119.         #@bitmap.invert()
  120.         @cells = light[1].to_i
  121.         @cells = 1 if (@cells < 1 or @cells > @bitmap.width)
  122.         @zoom = light[2].to_f
  123.         @zoom = 1.0 if @zoom <= 0.0
  124.         @zoom /= s_zoom
  125.         @width  = @bitmap.width / @cells
  126.         @height = @bitmap.height
  127.  
  128.         # 缩放处理
  129.         if @zoom != 1.0
  130.           new_width  = (@width * @zoom).round
  131.           new_height = (@height * @zoom).round
  132.           if new_width * new_height < 1
  133.             @zoom = 1.0
  134.           else
  135.             @width = new_width
  136.             @height = new_height
  137.             new_bitmap = Bitmap.new(@width * @cells, @height)
  138.             #new_bitmap.stretch_blt(new_bitmap.rect,@bitmap, @bitmap.rect)
  139.             HN_Light::Stretch.call(new_bitmap, @bitmap)
  140.             @bitmap.dispose
  141.             @bitmap = new_bitmap
  142.           end
  143.         end
  144.         @ox = @width / 2
  145.         @oy = @height / 2 - light[3].to_i / s_zoom
  146.  
  147.         # 色相変换
  148.         if ( (hue = light[4].to_i) != 0)
  149.           @bitmap.hue_change(hue)
  150.         end
  151.       end
  152.     end # End def initialize
  153.  
  154.     # 色调转换
  155.     def dispose
  156.       @bitmap.dispose
  157.       @bitmap = nil
  158.     end
  159.   end
  160.  
  161. end
  162.  
  163. class Game_Event
  164.   include HN_Light::LightEvent
  165.   alias :_hn_light__setup :refresh unless method_defined?(:_hn_light__setup)
  166.   def refresh
  167.     _hn_light__setup
  168.     check_light()
  169.   end
  170. end
  171.  
  172. class Game_Player
  173.   def light_type
  174.     return $game_variables[HN_Light::PLAYER_LIGHT_TYPE]
  175.   end
  176. end
  177.  
  178. class Game_Map
  179.   attr_reader :light_events
  180.  
  181.   # 更新烛光事件列表
  182.   def refresh_lights
  183.     @light_events = []
  184.     @events.values.each do |event|
  185.       if (event.light_type > 0)
  186.         @light_events.push(event)
  187.       end
  188.     end
  189.   end
  190.  
  191.   alias :_hn_light__setup_events :setup unless method_defined?(:_hn_light__setup_events)
  192.   def setup(map_id)
  193.     _hn_light__setup_events(map_id)
  194.     refresh_lights() if @map_id > 0
  195.   end
  196.  
  197.   alias :_hn_light__refresh :refresh unless method_defined?(:_hn_light__refresh)
  198.   def refresh
  199.     _hn_light__refresh()
  200.     refresh_lights() if @map_id > 0
  201.   end
  202. end
  203.  
  204. class Sprite_Dark < Sprite
  205.   @@base_color = Color.new(255,255,255,192)
  206.  
  207.   def initialize(viewport = nil)
  208.     super(viewport)
  209.     @width = 640
  210.     @height = 480
  211.  
  212.     case HN_Light::SIMPLIFY
  213.     when 1
  214.       @zoom = 2
  215.     when 2
  216.       @zoom = 4
  217.     else
  218.       @zoom = 1
  219.     end
  220.     @width /= @zoom
  221.     @height /= @zoom
  222.     self.zoom_x = @zoom.to_f
  223.     self.zoom_y = @zoom.to_f
  224.  
  225.     self.bitmap = Bitmap.new(@width, @height)
  226.     self.bitmap.fill_rect(self.bitmap.rect, @@base_color)
  227.     self.blend_type = 2 # 混合型(减算)
  228.     self.z = 800
  229.     self.visible = false
  230.     @light_cache = {}
  231.   end
  232.  
  233.   # 追加烛光
  234.   def add_light(charactor)
  235.     return if charactor.nil?
  236.     light_type = charactor.light_type
  237.     return if (light_type < 1 or light_type > HN_Light::LIGHTS.size)
  238.     unless @light_cache.key?(light_type)
  239.       @light_cache[light_type] = HN_Light::Light.new(light_type, @zoom)
  240.     end
  241.     light = @light_cache[light_type]
  242.  
  243.     # 画面外什麽都不做
  244.     if @zoom == 1
  245.       return if (charactor.screen_x < 0  - light.width + light.ox)
  246.       return if (charactor.screen_x > @width + light.ox)
  247.       return if (charactor.screen_y < 0 - light.height + light.oy)
  248.       return if (charactor.screen_y > @height + light.oy)
  249.     else
  250.       return if (charactor.screen_x < 0  - (light.width + light.ox) * @zoom)
  251.       return if (charactor.screen_x > (@width + light.ox)  * @zoom)
  252.       return if (charactor.screen_y < 0 - (light.height + light.oy) * @zoom)
  253.       return if (charactor.screen_y > (@height + light.oy) * @zoom)
  254.     end
  255.  
  256.     # 动画判定
  257.     if light.cells > 1
  258.       index = (Graphics.frame_count / 4) % light.cells
  259.       rect = Rect.new(index * light.width , 0, light.width, light.height)
  260.     else
  261.       rect = light.bitmap.rect
  262.     end
  263.     if @zoom != 1
  264.       p_x = charactor.screen_x / @zoom - light.ox
  265.       p_y = (charactor.screen_y - 16) / @zoom - light.oy
  266.     else
  267.       p_x = charactor.screen_x - light.ox
  268.       p_y = charactor.screen_y - 16 - light.oy
  269.     end
  270.  
  271.     # 乗算合成(3)
  272.     #self.bitmap.blend_blt(p_x, p_y, light.bitmap, rect, 3)
  273.     HN_Light::Mul.call(self.bitmap, p_x, p_y, light.bitmap, rect, 255)
  274.   end
  275.  
  276.  
  277.   def refresh
  278.     #self.bitmap.fill_rect(self.bitmap.rect, @@base_color)
  279.     HN_Light::Full.call(self.bitmap, @@base_color.alpha.to_i)
  280.     $game_map.light_events.each do |event|
  281.       next if HN_Light::LIGHTS[event.light_type - 1].nil?
  282.       add_light(event)
  283.     end
  284.     add_light($game_player)
  285.   end
  286.  
  287.   # 更新
  288.   def update
  289.     super
  290.     #@@base_color = Color.new(255, 255, 255, $game_variables[HN_Light::DARK_OPACITY_VAR])
  291.     @@base_color.alpha = $game_variables[HN_Light::DARK_OPACITY_VAR]
  292.     refresh()
  293.   end
  294.  
  295.   #--------------------------------------------------------------------------
  296.   # ● 解放
  297.   #--------------------------------------------------------------------------
  298.   def dispose
  299.     self.bitmap.dispose
  300.     @light_cache.values.each do |light|
  301.       light.dispose
  302.     end
  303.     super
  304.   end
  305. end
  306.  
  307.  
  308. class Spriteset_Map  
  309.   # 动画判定
  310.   def create_dark
  311.     @dark_sprite = Sprite_Dark.new(@viewport1)
  312.   end
  313.  
  314.   # 更新黑暗Sprite
  315.   def update_dark
  316.     if (@dark_sprite.visible = $game_switches[HN_Light::DARK_SWITCH])
  317.       @dark_sprite.update
  318.     end
  319.   end
  320.  
  321.   # 破弃黑暗Sprite
  322.   def dispose_dark
  323.     @dark_sprite.dispose
  324.   end
  325.  
  326.   # 初期化
  327.   alias :_dark__initialize :initialize unless private_method_defined?(:_dark__initialize)
  328.   def initialize
  329.     _dark__initialize()
  330.     create_dark()
  331.     update_dark()
  332.   end
  333.  
  334.   # 更新
  335.   alias :_dark__update :update unless method_defined?(:_dark__update)
  336.   def update
  337.     _dark__update()
  338.     update_dark() if !@dark_sprite.nil? and !@dark_sprite.disposed?
  339.   end
  340.  
  341.   # 结束处理
  342.   alias :_dark__dispose :dispose unless method_defined?(:_dark__dispose)
  343.   def dispose
  344.     dispose_dark()
  345.     _dark__dispose()
  346.   end
  347. end





round.png (6.38 KB, 下载次数: 25)

round.png

tmp.png (21.1 KB, 下载次数: 23)

tmp.png

Light.zip

6.32 KB, 下载次数: 18

Light.dll

Lv4.逐梦者

梦石
0
星屑
7827
在线时间
1347 小时
注册时间
2015-8-15
帖子
753
2
发表于 2022-11-23 10:18:59 | 只看该作者
大神解决一下楼下问题 如何在角色HP变量值<90窗口10的图片透明=0或关闭窗口
回复 支持 反对

使用道具 举报

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

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-25 23:59

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表