Project1

标题: Khas Awesome Light Effects烛光脚本分辨率的问题 [打印本页]

作者: mollyko    时间: 2020-3-13 20:40
标题: Khas Awesome Light Effects烛光脚本分辨率的问题

我把窗口分辨率改为了640x480,然后就出现了这个问题:遮不住
球大神解答!
脚本在此:


#-------------------------------------------------------------------------------
# * [ACE] Khas Awesome Light Effects
#-------------------------------------------------------------------------------
# * By Khas Arcthunder - arcthunder.site40.net
# * Version: 1.0 EN
# * Released on: 17/01/2012
#
#-------------------------------------------------------------------------------
# * Terms of Use
#-------------------------------------------------------------------------------
# When using any Khas script, you agree with the following terms:
# 1. You must give credit to Khas;
# 2. All Khas scripts are licensed under a Creative Commons license;
# 3. All Khas scripts are for non-commercial projects. If you need some script
#    for your commercial project (I accept requests for this type of project),
#    send an email to [email protected] with your request;
# 4. All Khas scripts are for personal use, you can use or edit for your own
#    project, but you are not allowed to post any modified version;
# 5. You can’t give credit to yourself for posting any Khas script;
# 6. If you want to share a Khas script, don’t post the direct download link,
#    please redirect the user to arcthunder.site40.net
#
#-------------------------------------------------------------------------------
# * Features
#-------------------------------------------------------------------------------
# - Realistic Light
# - Light does not pass over walls, blocks and roofs
# - Static Light Sources
# - Dynamic Light Sources (like a player's lantern)
# - Multiple effects
# - Easy to use (comments)
#
#-------------------------------------------------------------------------------
# * WARNING - Performance
#-------------------------------------------------------------------------------
# This script may be too heavy to old processors! The Awesome Light Effects was
# tested on a Core 2 Duo E4500 and on a Core i5, without any lag. However,
# there's other factors that may influence the script performance:
#
# 1. Map size
# This script searches surfaces on the map, in order to cut the light pictures.
# In a huge map, the number of surfaces may increase a lot, affecting the
# DYNAMIC LIGHT SOURCE only. Map size does not influence the static sources.
#
# 2. Number of effects
# This script draws the effects on the screen, but before drawing, it checks
# if the effect is out of screen (in this case, the script will skip the
# light drawing). Too much effects may cause lag, but this is just a prevision.
#
# 3. Effect's picture size
# The picture size of the DYNAMIC LIGHT SOURCE influences directly on your
# game's performace. The bigger is the picture, the slower it will be to
# draw it dynamically. The recommended maximum size is 200x200 pixels
#
#-------------------------------------------------------------------------------
# * WARNING - Light pictures
#-------------------------------------------------------------------------------
# In order to run this script correctly, the light pictures MUST obey the
# following conditions:
# 1. The picture's size MUST be multiple of 2. Example: 150x150
# 2. The picture's width MUST be equal to it's height. Example: 156x156
# 3. The picture's colors MUST be inverted! This is necessary because
#    the script inverts the colors to draw the effect. The black color
#    will be transparent!
#
#-------------------------------------------------------------------------------
# * Instructions - 1. Setup your effects!
#-------------------------------------------------------------------------------
# In order to setup your static effects, go to the setup part and define your
# effects inside the Effects hash. Do as the following mode:
#
# X => [picture,opacity,variation,cut],   <= Remember to put a comma here!
#
# Where:
# picture => Picture's name, inside the Graphics/Lights folder;
# opacity => Effect's opacity;
# variation => Effect's opacity variation;
# cut => Put true to cut the effect or false to don't;
# X => The effect's ID, it will be used on events.
#
# Check the default effects to understand how they work.
#
#-------------------------------------------------------------------------------
# * Instructions - 2. Use your effects!
#-------------------------------------------------------------------------------
# In order to use a effect, put the following comment on a event:
#
# [light x]
#
# Where x must be the Effect's ID.
#
#-------------------------------------------------------------------------------
# * Instructions - 3. Use an awesome lantern!
#-------------------------------------------------------------------------------
# The dynamic light source (lantern) is initialized invisible by default.
# You may call the following commands:
#
# l = $game_map.lantern
# Gets the lantern into a variable

# l.set_graphic(i)
# Sets the lantern's graphic to i, where i must be the picture's file name on
# Graphics/Lights folder.
#
# l.set_multiple_graphics(h)
# Sets the lantern's graphics to h, where h must be a hash with the following
# structure:
#
# h = {2=>"ld",4=>"ll",6=>"lr",8=>"lu"}
#
# Where:
# "ld" is the name of the picture when the lantern's owner is looking down;
# "ll" is the name of the picture when the lantern's owner is looking left;
# "lr" is the name of the picture when the lantern's owner is looking right;
# "lu" is the name of the picture when the lantern's owner is looking up.
#
# l.change_owner(char)
# Sets the lantern's owner to char. Char must be ONE of the following commands:
# $game_player           <= The player itself;
# self_event             <= The event where the command was called;
# $game_map.events[x]    <= The event ID x.
#
# l.set_opacity(o,p)
# Sets the lantern's opacity, where:
# o is the opacity itself;
# p is the opacity variation.
#
# l.show
# After setting the lantern with the commands above, you may set it to visible
# using this command.
#
# l.hide
# Use this command to set the lantern as invisible.
#
#-------------------------------------------------------------------------------
# * Instructions - 4. Use the effect's surface!
#-------------------------------------------------------------------------------
# The Awesome Light Effects draws the effects on a surface. In order to make
# the effects visible, the effect's surface MUST be visible. The Effect's
# Surface is initialized with it's opacity set to zero. You can call the
# following commands:
#
# s = $game_map.effect_surface
# Gets the Effect's Surface into a variable
#
# s.set_color(r,g,b)
# Changes the Effect's Surface color instantly, where:
# r => red level;
# g => green level;
# b => blue level;
#
# s.set_alpha(a)
# Changes the Effect's Surface opacity instantly to a.
#
# s.change_color(time,r,g,b)
# Changes the Effect's Surface color ONLY in a certain time, where:
# time => The change's time (frames);
# r => red level;
# g => green level;
# b => blue level;
#
# s.change_color(time,r,g,b,a)
# Changes the Effect's Surface color and it's opacity in a certain time, where:
# time => The change's time (frames);
# r => red level;
# g => green level;
# b => blue level;
# a => opacity
#
# s.change_alpha(time,a)
# Changes the Effect's Surface opacity in a certain time, where:
# time => The change's time (frames);
# a => opacity
#
#-------------------------------------------------------------------------------
# * Instructions - 5. Use the effect's surface with Tone command!
#-------------------------------------------------------------------------------
# You can access the Effect's Surface with the "Screen Tone" command. In order
# to turn this feature on, set the "Surface_UE" constant to true.
#
# If you decided to use this feature, please note some details:
# 1. The colors values must be between 0 and 255;
# 2. The time is in frames;
# 3. The "gray" value will be sent as the opacity value
#
#-------------------------------------------------------------------------------
# * Instructions - 6. Setup your Tileset Tags!
#-------------------------------------------------------------------------------
# In order to cut the effect's picture correctly, there's 3 types of behavior
# for a tile: wall, block and roof. Walls will make shadows as real walls,
# blocks as blocks and roofs as roofs. So, the tileset tags MUST be configured.
# Check the demo to understand how this system works. If the tilesets aren't
# configured correctly, the script won't cut the effects correctly.
#
#-------------------------------------------------------------------------------
# * Setup Part
#-------------------------------------------------------------------------------
module Light_Core
  Effects = { #  <= DON'T change this!
#-------------------------------------------------------------------------------
# PUT YOUR EFFECTS HERE!
#-------------------------------------------------------------------------------
  0 => ["light_m",255,0,true],
  1 => ["torch",200,20,true],
  2 => ["torch_m",180,30,true],
  3 => ["light_s",255,0,true],
  
#-------------------------------------------------------------------------------
# End of effecs configuration
#-------------------------------------------------------------------------------
  } #  <= DON'T change this!
  
  # Z coordinate of the Effect's Surface
  Surface_Z = 180
  
  # Enable Effect's Surface control by "Screen Tone" command?
  Surface_UE = true
  
  # Roof behavior tag
  Roof_Tag = 5
  # Wall behavior tag
  Wall_Tag = 6
  # Block behavior tag
  Block_Tag = 7
  
  # Don't change this!
  ACC = Math.tan(Math::PI/26)
end
#-------------------------------------------------------------------------------
# Script
#-------------------------------------------------------------------------------
module Cache
  def self.light(filename)
    load_bitmap("Graphics/Lights/", filename)
  end
end
module Light_Bitcore
  include Light_Core
  def self.initialize
    @@buffer = {}
    Effects.values.each { |effect| Light_Bitcore.push(effect[0])}
  end
  def self::[](key)
    return @@buffer[key]
  end
  def self.push(key)
    return if @@buffer.keys.include?(key)
    @@buffer[key] = Cache.light(key)
  end
end
Light_Bitcore.initialize
class Light_SSource
  attr_reader :real_x
  attr_reader :real_y
  attr_reader :range
  attr_accessor :bitmap
  attr_reader :w
  attr_reader :h
  attr_reader :hs
  def initialize(char,bitmap,opacity,plus,hs)
    sync(char)
    @key = bitmap
    @bitmap = Light_Bitcore[@key].clone
    @range = @bitmap.width/2
    @w = @bitmap.width
    @h = @bitmap.height
    @mr = @range - 16
    @opacity = opacity
    @plus = plus
    @hs = hs
    render if @hs
  end
  def render
    tx = x
    ty = y
    tsx = x + @range
    tsy = y + @range
    dr = @range*2
    for s in $game_map.surfaces
      next if !s.visible?(tsx,tsy) || !s.within?(tx,tx+dr,ty,ty+dr)
      s.render_shadow(tx,ty,tsx,tsy,@range,@bitmap)
    end
  end
  def restore
    return unless @bitmap.nil?
    @bitmap = Light_Bitcore[@key].clone
    render if @hs
  end
  def opacity
    @plus == 0 ? @opacity : (@opacity + rand(@plus))
  end
  def sx
    return $game_map.adjust_x(@real_x)*32-@mr
  end
  def sy
    return $game_map.adjust_y(@real_y)*32-@mr
  end
  def sync(char)
    @real_x = char.real_x
    @real_y = char.real_y
  end
  def x
    return (@real_x*32 - @mr).to_f
  end
  def y
    return (@real_y*32 - @mr).to_f
  end
  def dispose
    return if @bitmap.nil?
    @bitmap.dispose
    @bitmap = nil
  end
end
class Light_DSource < Light_SSource
  attr_reader :bitmap
  attr_reader :visible
  def initialize
    @key = nil
    @bitmap = nil
    @opacity = 255
    @plus = 0
    @char = $game_player
    @visible = false
  end
  def set_opacity(o,p)
    @opacity = o
    @plus = p
  end
  def set_graphic(sb)
    dispose
    @key = {2=>sb,4=>sb,6=>sb,8=>sb}
    Light_Bitcore.push(sb)
    @bitmap = {2=>Light_Bitcore[@key[2]].clone,4=>Light_Bitcore[@key[4]].clone,6=>Light_Bitcore[@key[6]].clone,8=>Light_Bitcore[@key[8]].clone}
    @range = @bitmap[2].width/2
    @w = @bitmap[2].width
    @h = @bitmap[2].height
    @mr = @range - 16
  end
  def set_multiple_graphics(ba)
    dispose
    @key = ba
    @key.values.each {|key| Light_Bitcore.push(key)}
    @bitmap = {2=>Light_Bitcore[@key[2]].clone,4=>Light_Bitcore[@key[4]].clone,6=>Light_Bitcore[@key[6]].clone,8=>Light_Bitcore[@key[8]].clone}
    @range = @bitmap[2].width/2
    @w = @bitmap[2].width
    @h = @bitmap[2].height
    @mr = @range - 16
  end
  def get_graphic
    return @bitmap[@char.direction].clone
  end
  def show
    return if @bitmap.nil?
    @visible = true
  end
  def hide
    @visible = false
  end
  def restore
    return if @key.nil?
    @key.values.each {|key| Light_Bitcore.push(key)}
    @bitmap = {2=>Light_Bitcore[@key[2]].clone,4=>Light_Bitcore[@key[4]].clone,6=>Light_Bitcore[@key[6]].clone,8=>Light_Bitcore[@key[8]].clone}
  end
  def dispose
    return if @bitmap.nil?
    @bitmap.values.each { |b| b.dispose }
    @bitmap = nil
  end
  def change_owner(char)
    @char = char
  end
  def render
  end
  def sx
    return $game_map.adjust_x(@char.real_x)*32-@mr
  end
  def sy
    return $game_map.adjust_y(@char.real_y)*32-@mr
  end
  def x
    return (@char.real_x*32 - @mr).to_f
  end
  def y
    return (@char.real_y*32 - @mr).to_f
  end
end
class Light_Surface
  def initialize
    @ta = @a = 0
    @tr = @r = 255
    @tg = @g = 255
    @tb = @b = 255
    @va = @vr = @vg = @vb = 0.0
    @timer = 0
  end
  def refresh
    return if @timer == 0
    @a += @va
    @r += @vr
    @g += @vg
    @b += @vb
    $game_map.light_surface.opacity = @a
    @timer -= 1
  end
  def change_color(time,r,g,b,a=nil)
    r = 0 if r < 0; r = 255 if r > 255
    g = 0 if g < 0; g = 255 if g > 255
    b = 0 if b < 0; b = 255 if b > 255
    unless a.nil?
      a = 0 if a < 0; a = 255 if a > 255
    end
    @timer = time
    @tr = 255-r
    @tg = 255-g
    @tb = 255-b
    @va = (a.nil? ? 0 : (a-@a).to_f/@timer)
    @vr = (@tr - @r).to_f/@timer
    @vg = (@tg - @g).to_f/@timer
    @vb = (@tb - @b).to_f/@timer
  end
  def change_alpha(time,a)
    a = 0 if a < 0; a = 255 if a > 255
    @timer = time
    @ta = a
    @vr = @vg = @vb = 0.0
    @va = (a-@a).to_f/@timer
  end
  def set_color(r,g,b)
    r = 0 if r < 0; r = 255 if r > 255
    g = 0 if g < 0; g = 255 if g > 255
    b = 0 if b < 0; b = 255 if b > 255
    @tr = @r = 255-r
    @tg = @g = 255-g
    @tb = @b = 255-b
    @va = @vr = @vg = @vb = 0.0
    @timer = 0
  end
  def set_alpha(a)
    a = 0 if a < 0; a = 255 if a > 255
    @ta = @a = a
    $game_map.light_surface.opacity = @a
    @va = @vr = @vg = @vb = 0.0
    @timer = 0
  end
  def alpha
    return @a
  end
  def color
    return Color.new(@r,@g,@b)
  end
end
class Game_Map
  include Light_Core
  attr_accessor :light_surface
  attr_accessor :light_sources
  attr_accessor :surfaces
  attr_accessor :effect_surface
  attr_accessor :lantern
  alias kbl_setup_events setup_events
  alias kbl_initialize initialize
  alias kbl_update update
  def initialize
    kbl_initialize
    @effect_surface = Light_Surface.new
    @lantern = Light_DSource.new
  end
  def update(arg)
    @effect_surface.refresh if arg
    kbl_update(arg)
  end
  def first_tag(x,y)
    tag = tileset.flags[tile_id(x,y,0)] >> 12
    return tag > 0 ? tag : 0
  end
  def setup_events
    @light_sources.nil? ? @light_sources = [] : @light_sources.clear
    setup_surfaces
    merge_surfaces
    kbl_setup_events
  end
  def setup_surfaces
    @surfaces = []
    for x in 0..(width-1)
      for y in 0..(height-1)
        tag = first_tag(x,y)
        if tag == Wall_Tag
          i = tile_id(x,y,0)
          if i & 0x02 == 0x02
            @surfaces << Block_SD.new(x*32,y*32,x*32+32,y*32)
          end
          if i & 0x04 == 0x04
            @surfaces << Block_WR.new(x*32+31,y*32,x*32+31,y*32+32)
            @surfaces << Block_IL.new(x*32+32,y*32,x*32+32,y*32+32)
          end
          if i & 0x01 == 0x01
            @surfaces << Block_IR.new(x*32-1,y*32,x*32-1,y*32+32)
            @surfaces << Block_WL.new(x*32,y*32,x*32,y*32+32)
          end
        elsif tag == Roof_Tag
          i = tile_id(x,y,0)
          @surfaces << Block_SU.new(x*32,y*32,x*32+32,y*32) if i & 0x02 == 0x02
          @surfaces << Block_SR.new(x*32+31,y*32,x*32+31,y*32+32) if i & 0x04 == 0x04
          @surfaces << Block_SL.new(x*32,y*32,x*32,y*32+32) if i & 0x01 == 0x01
        elsif tag == Block_Tag
          f = tileset.flags[tile_id(x,y,0)]
          @surfaces << Block_SL.new(x*32,y*32,x*32,y*32+32) if f & 0x02 == 0x02
          @surfaces << Block_SR.new(x*32+31,y*32,x*32+31,y*32+32) if f & 0x04 == 0x04
          @surfaces << Block_SU.new(x*32,y*32,x*32+32,y*32) if f & 0x08 == 0x08
        end
      end
    end
  end
  def merge_surfaces
    new_surfaces = []
    hs = []; vs = []
    ws = []; is = []
    for surface in @surfaces
      if surface.type & 0x05 == 0
        hs << surface
      else
        if surface.type & 0x010 == 0
          vs << surface
        else
          if surface.type & 0x08 == 0
            ws << surface
          else
            is << surface
          end
        end
      end
    end
    for surface in hs
      surface.ready ? next : surface.ready = true
      for s in hs
        next if s.ready || s.y1 != surface.y1 || surface.type != s.type
        if s.x2 == surface.x1
          surface.x1 = s.x1
          s.trash = true
          s.ready = true
          surface.ready = false
        elsif s.x1 == surface.x2
          surface.x2 = s.x2
          s.trash = true
          s.ready = true
          surface.ready = false
        end
      end
    end
    hs.each { |s| @surfaces.delete(s) if s.trash}
    for surface in vs
      surface.ready ? next : surface.ready
      for s in vs
        next if s.ready || s.x1 != surface.x1
        if s.y2 == surface.y1
          surface.y1 = s.y1
          s.trash = true
          s.ready = true
          surface.ready = false
        elsif s.y1 == surface.y2
          surface.y2 = s.y2
          s.trash = true
          s.ready = true
          surface.ready = false
        end
      end
    end
    vs.each { |s| @surfaces.delete(s) if s.trash}
    for surface in ws
      surface.ready ? next : surface.ready
      for s in ws
        next if s.ready || s.x1 != surface.x1
        if s.y2 == surface.y1
          surface.y1 = s.y1
          s.trash = true
          s.ready = true
          surface.ready = false
        elsif s.y1 == surface.y2
          surface.y2 = s.y2
          s.trash = true
          s.ready = true
          surface.ready = false
        end
      end
    end
    ws.each { |s| @surfaces.delete(s) if s.trash}
    for surface in is
      surface.ready ? next : surface.ready
      for s in is
        next if s.ready || s.x1 != surface.x1
        if s.y2 == surface.y1
          surface.y1 = s.y1
          s.trash = true
          s.ready = true
          surface.ready = false
        elsif s.y1 == surface.y2
          surface.y2 = s.y2
          s.trash = true
          s.ready = true
          surface.ready = false
        end
      end
    end
    is.each { |s| @surfaces.delete(s) if s.trash}
  end
end
class Game_Event < Game_Character
  alias kbl_initialize initialize
  alias kbl_setup_page setup_page
  def initialize(m,e)
    @light = nil
    kbl_initialize(m,e)
  end
  def setup_page(np)
    kbl_setup_page(np)
    setup_light(np.nil?)
  end
  def setup_light(dispose)
    unless @light.nil?
      $game_map.light_sources.delete(self)
      @light.dispose
      @light = nil
    end
    unless dispose && @list.nil?
      for command in @list
        if command.code == 108 && command.parameters[0].include?("[light")
          command.parameters[0].scan(/\[light ([0.0-9.9]+)\]/)
          effect = Light_Core::Effects[$1.to_i]
          @light = Light_SSource.new(self,effect[0],effect[1],effect[2],effect[3])
          $game_map.light_sources << self
          return
        end
      end
    end
  end
  def draw_light
    sx = @light.sx
    sy = @light.sy
    w = @light.w
    h = @light.h
    return if sx > 544 && sy > 416 && sx + w < 0 && sy + h < 0
    $game_map.light_surface.bitmap.blt(sx,sy,@light.bitmap,Rect.new(0,0,w,h),@light.opacity)
  end
  def dispose_light
    @light.dispose
  end
  def restore_light
    @light.restore
  end
end
if Light_Core::Surface_UE
  class Game_Interpreter
    def command_223
      $game_map.effect_surface.change_color(@params[1],@params[0].red,@params[0].green,@params[0].blue,@params[0].gray)
      wait(@params[1]) if @params[2]
    end
  end
end
class Game_Interpreter
  def self_event
    return $game_map.events[@event_id]
  end
end
class Block_Surface
  include Light_Core
  attr_accessor :x1
  attr_accessor :y1
  attr_accessor :x2
  attr_accessor :y2
  attr_accessor :ready
  attr_accessor :trash
  def initialize(x1,y1,x2,y2)
    @x1 = x1
    @y1 = y1
    @x2 = x2
    @y2 = y2
    @ready = false
    @trash = false
  end
  def within?(min_x,max_x,min_y,max_y)
    return @x2 > min_x && @x1 < max_x && @y2 > min_y && @y1 < max_y
  end
end
class Block_SL < Block_Surface
  attr_reader :type
  def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x01
  end
  def visible?(sx,sy)
    return sx < @x1
  end
  def render_shadow(phx,phy,sx,sy,range,bitmap)
    @m1 = (@y1-sy)/(@x1-sx)
    @n1 = sy - @m1*sx
    @m2 = (@y2-sy)/(@x2-sx)
    @n2 = sy - @m2*sx
    for x in @x1..(sx+range)
      init = shadow_iy(x)
      bitmap.clear_rect(x-phx,init-phy,1,shadow_fy(x)-init+3)
    end
  end
  def shadow_iy(x)
    return @m1*x+@n1
  end
  def shadow_fy(x)
    return @m2*x+@n2
  end
end
class Block_SR < Block_Surface
  attr_reader :type
  def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x04
  end
  def visible?(sx,sy)
    return sx > @x1
  end
  def render_shadow(phx,phy,sx,sy,range,bitmap)
    @m1 = (@y1-sy)/(@x1-sx)
    @n1 = sy - @m1*sx
    @m2 = (@y2-sy)/(@x2-sx)
    @n2 = sy - @m2*sx
    for x in (sx-range).to_i..@x1
      init = shadow_iy(x)
      bitmap.clear_rect(x-phx,init-phy,1,shadow_fy(x)-init+3)
    end
  end
  def shadow_iy(x)
    return @m1*x+@n1
  end
  def shadow_fy(x)
    return @m2*x+@n2
  end
end
class Block_IL < Block_Surface
  attr_reader :type
  def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x019
  end
  def visible?(sx,sy)
    return sx < @x1 && sy > @y1
  end
  def render_shadow(phx,phy,sx,sy,range,bitmap)
    @m1 = (@y1-sy)/(@x1-sx)
    @n1 = @y1 - @m1*@x1
    @m2 = (@y2-sy)/(@x2-sx)
    @m2 = 0 if @m2 > 0
    @n2 = @y2 - @m2*@x2
    for x in @x1..(sx+range)
      init = shadow_iy(x).floor
      bitmap.clear_rect(x-phx,init-3-phy,1,shadow_fy(x)-init+3)
    end
  end
  def shadow_iy(x)
    return @m1*x+@n1
  end
  def shadow_fy(x)
    return @m2*x+@n2
  end
end
class Block_IR < Block_Surface
  attr_reader :type
  def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x01c
  end
  def visible?(sx,sy)
    return sx > @x1 && sy > @y1
  end
  def render_shadow(phx,phy,sx,sy,range,bitmap)
    @m1 = (@y1-sy)/(@x1-sx)
    @n1 = @y1 - @m1*@x1
    @m2 = (@y2-sy)/(@x2-sx)
    @m2 = 0 if @m2 < 0
    @n2 = @y2 - @m2*@x2
    for x in (sx-range).to_i..@x1
      init = shadow_iy(x).floor
      bitmap.clear_rect(x-phx,init-3-phy,1,shadow_fy(x)-init+3)
    end
  end
  def shadow_iy(x)
    return @m1*x+@n1
  end
  def shadow_fy(x)
    return @m2*x+@n2
  end
end
class Block_WL < Block_Surface
  attr_reader :type
  def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x011
  end
  def visible?(sx,sy)
    return sx < @x1 && sy < @y2
  end
  def render_shadow(phx,phy,sx,sy,range,bitmap)
    @m1 = (@y1-sy)/(@x1-sx)
    @n1 = sy - @m1*sx
    @m2 = (@y2-sy)/(@x2-sx)
    @n2 = sy - @m2*sx
    for x in @x1..(sx+range)
      init = shadow_iy(x)
      bitmap.clear_rect(x-phx,init-phy,1,shadow_fy(x)-init+2)
    end
  end
  def shadow_iy(x)
    return @m1*x+@n1
  end
  def shadow_fy(x)
    return @m2*x+@n2
  end
end
class Block_WR < Block_Surface
  attr_reader :type
  def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x014
  end
  def visible?(sx,sy)
    return sx > @x1 && sy < @y2
  end
  def render_shadow(phx,phy,sx,sy,range,bitmap)
    @m1 = (@y1-sy)/(@x1-sx)
    @n1 = sy - @m1*sx
    @m2 = (@y2-sy)/(@x2-sx)
    @n2 = sy - @m2*sx
    for x in (sx-range).to_i..@x1
      init = shadow_iy(x)
      bitmap.clear_rect(x-phx,init-phy,1,shadow_fy(x)-init+2)
    end
  end
  def shadow_iy(x)
    return @m1*x+@n1
  end
  def shadow_fy(x)
    return @m2*x+@n2
  end
end
class Block_SU < Block_Surface
  attr_reader :type
  def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x02
  end
  def visible?(sx,sy)
    return sy < @y1
  end
  def render_shadow(phx,phy,sx,sy,range,bitmap)
    if @x1 == sx
      @m1 = nil
    else
      @m1 = (@y1-sy)/(@x1-sx)
      @m1 += ACC if @m1 < -ACC
      @n1 = @y1 - @m1*@x1
    end
    if @x2 == sx
      @m2 = nil
    else
      @m2 = (@y2-sy)/(@x2-sx)
      @n2 = sy - @m2*sx
    end
    for y in @y1..(sy+range)
      init = shadow_ix(y)
      bitmap.clear_rect(init-phx,y-phy,shadow_fx(y)-init+1,1)
    end
  end
  def shadow_ix(y)
    return @m1.nil? ? @x1 : (y-@n1)/@m1
  end
  def shadow_fx(y)
    return @m2.nil? ? @x2 : (y-@n2)/@m2
  end
end
class Block_SD < Block_Surface
  attr_reader :type
  def initialize(x1,y1,x2,y2)
    super(x1,y1,x2,y2)
    @type = 0x08
  end
  def visible?(sx,sy)
    return sy > @y1
  end
  def render_shadow(phx,phy,sx,sy,range,bitmap)
    if @x1 == sx
      @m1 = nil
    else
      @m1 = (@y1-sy)/(@x1-sx)
      @m1 -= ACC if @m1 > ACC
      @n1 = sy - @m1*sx
    end
    if x2 == sx
      @m2 = nil
    else
      @m2 = (@y2-sy)/(@x2-sx)
      @n2 = sy - @m2*sx
    end
    for y in (sy-range).to_i..@y1
      init = shadow_ix(y)
      bitmap.clear_rect(init-phx,y-phy,shadow_fx(y)-init+1,1)
    end
  end
  def shadow_ix(y)
    return @m1.nil? ? @x1 : (y-@n1)/@m1
  end
  def shadow_fx(y)
    return @m2.nil? ? @x2 : (y-@n2)/@m2
  end
end
class Spriteset_Map
  include Light_Core
  alias kbl_initialize initialize
  alias kbl_update update
  alias kbl_dispose dispose
  def initialize
    setup_lights
    kbl_initialize
  end
  def update
    kbl_update
    update_lights
  end
  def dispose
    kbl_dispose
    dispose_lights
  end
  def dispose_lights
    $game_map.lantern.dispose
    $game_map.light_sources.each { |source| source.dispose_light }
    $game_map.light_surface.bitmap.dispose
    $game_map.light_surface.dispose
    $game_map.light_surface = nil
  end
  def update_lights
    $game_map.light_surface.bitmap.clear
    $game_map.light_surface.bitmap.fill_rect(0,0,544,416,$game_map.effect_surface.color)
    $game_map.light_sources.each { |source| source.draw_light }
    return unless $game_map.lantern.visible
    @btr = $game_map.lantern.get_graphic
    x = $game_map.lantern.x
    y = $game_map.lantern.y
    r = $game_map.lantern.range
    sx = x + r
    sy = y + r
    dr = r*2
    $game_map.surfaces.each { |s| s.render_shadow(x,y,sx,sy,r,@btr) if s.visible?(sx,sy) && s.within?(x,x+dr,y,y+dr) }
    $game_map.light_surface.bitmap.blt($game_map.lantern.sx,$game_map.lantern.sy,@btr,Rect.new(0,0,dr,dr),$game_map.lantern.opacity)
  end
  def setup_lights
    @btr = nil
    $game_map.lantern.restore
    $game_map.light_sources.each { |source| source.restore_light }
    $game_map.light_surface = Sprite.new
    $game_map.light_surface.bitmap = Bitmap.new(544,416)
    $game_map.light_surface.bitmap.fill_rect(0,0,544,416,$game_map.effect_surface.color)
    $game_map.light_surface.blend_type = 2
    $game_map.light_surface.opacity = $game_map.effect_surface.alpha
    $game_map.light_surface.z = Surface_Z
  end
end
作者: Cupidk爱呗茶    时间: 2020-3-13 23:12
本帖最后由 Cupidk爱呗茶 于 2020-3-14 01:12 编辑

小改了一点 刚刚稍微测试了下 在640X480或者更高分辨率下光源暂时没有任何问题了  可以随着分辨率提高而自适应描绘的大小,以后在更换分辨率就不会出现类似的情况啦
  1. #-------------------------------------------------------------------------------
  2. # * [ACE] Khas Awesome Light Effects
  3. #-------------------------------------------------------------------------------
  4. # * By Khas Arcthunder - arcthunder.site40.net
  5. # * Version: 1.0 EN
  6. # * Released on: 17/01/2012
  7. #
  8. #-------------------------------------------------------------------------------
  9. # * Terms of Use
  10. #-------------------------------------------------------------------------------
  11. # When using any Khas script, you agree with the following terms:
  12. # 1. You must give credit to Khas;
  13. # 2. All Khas scripts are licensed under a Creative Commons license;
  14. # 3. All Khas scripts are for non-commercial projects. If you need some script
  15. #    for your commercial project (I accept requests for this type of project),
  16. #    send an email to [email protected] with your request;
  17. # 4. All Khas scripts are for personal use, you can use or edit for your own
  18. #    project, but you are not allowed to post any modified version;
  19. # 5. You can’t give credit to yourself for posting any Khas script;
  20. # 6. If you want to share a Khas script, don’t post the direct download link,
  21. #    please redirect the user to arcthunder.site40.net
  22. #
  23. #-------------------------------------------------------------------------------
  24. # * Features
  25. #-------------------------------------------------------------------------------
  26. # - Realistic Light
  27. # - Light does not pass over walls, blocks and roofs
  28. # - Static Light Sources
  29. # - Dynamic Light Sources (like a player's lantern)
  30. # - Multiple effects
  31. # - Easy to use (comments)
  32. #
  33. #-------------------------------------------------------------------------------
  34. # * WARNING - Performance
  35. #-------------------------------------------------------------------------------
  36. # This script may be too heavy to old processors! The Awesome Light Effects was
  37. # tested on a Core 2 Duo E4500 and on a Core i5, without any lag. However,
  38. # there's other factors that may influence the script performance:
  39. #
  40. # 1. Map size
  41. # This script searches surfaces on the map, in order to cut the light pictures.
  42. # In a huge map, the number of surfaces may increase a lot, affecting the
  43. # DYNAMIC LIGHT SOURCE only. Map size does not influence the static sources.
  44. #
  45. # 2. Number of effects
  46. # This script draws the effects on the screen, but before drawing, it checks
  47. # if the effect is out of screen (in this case, the script will skip the
  48. # light drawing). Too much effects may cause lag, but this is just a prevision.
  49. #
  50. # 3. Effect's picture size
  51. # The picture size of the DYNAMIC LIGHT SOURCE influences directly on your
  52. # game's performace. The bigger is the picture, the slower it will be to
  53. # draw it dynamically. The recommended maximum size is 200x200 pixels
  54. #
  55. #-------------------------------------------------------------------------------
  56. # * WARNING - Light pictures
  57. #-------------------------------------------------------------------------------
  58. # In order to run this script correctly, the light pictures MUST obey the
  59. # following conditions:
  60. # 1. The picture's size MUST be multiple of 2. Example: 150x150
  61. # 2. The picture's width MUST be equal to it's height. Example: 156x156
  62. # 3. The picture's colors MUST be inverted! This is necessary because
  63. #    the script inverts the colors to draw the effect. The black color
  64. #    will be transparent!
  65. #
  66. #-------------------------------------------------------------------------------
  67. # * Instructions - 1. Setup your effects!
  68. #-------------------------------------------------------------------------------
  69. # In order to setup your static effects, go to the setup part and define your
  70. # effects inside the Effects hash. Do as the following mode:
  71. #
  72. # X => [picture,opacity,variation,cut],   <= Remember to put a comma here!
  73. #
  74. # Where:
  75. # picture => Picture's name, inside the Graphics/Lights folder;
  76. # opacity => Effect's opacity;
  77. # variation => Effect's opacity variation;
  78. # cut => Put true to cut the effect or false to don't;
  79. # X => The effect's ID, it will be used on events.
  80. #
  81. # Check the default effects to understand how they work.
  82. #
  83. #-------------------------------------------------------------------------------
  84. # * Instructions - 2. Use your effects!
  85. #-------------------------------------------------------------------------------
  86. # In order to use a effect, put the following comment on a event:
  87. #
  88. # [light x]
  89. #
  90. # Where x must be the Effect's ID.
  91. #
  92. #-------------------------------------------------------------------------------
  93. # * Instructions - 3. Use an awesome lantern!
  94. #-------------------------------------------------------------------------------
  95. # The dynamic light source (lantern) is initialized invisible by default.
  96. # You may call the following commands:
  97. #
  98. # l = $game_map.lantern
  99. # Gets the lantern into a variable

  100. # l.set_graphic(i)
  101. # Sets the lantern's graphic to i, where i must be the picture's file name on
  102. # Graphics/Lights folder.
  103. #
  104. # l.set_multiple_graphics(h)
  105. # Sets the lantern's graphics to h, where h must be a hash with the following
  106. # structure:
  107. #
  108. # h = {2=>"ld",4=>"ll",6=>"lr",8=>"lu"}
  109. #
  110. # Where:
  111. # "ld" is the name of the picture when the lantern's owner is looking down;
  112. # "ll" is the name of the picture when the lantern's owner is looking left;
  113. # "lr" is the name of the picture when the lantern's owner is looking right;
  114. # "lu" is the name of the picture when the lantern's owner is looking up.
  115. #
  116. # l.change_owner(char)
  117. # Sets the lantern's owner to char. Char must be ONE of the following commands:
  118. # $game_player           <= The player itself;
  119. # self_event             <= The event where the command was called;
  120. # $game_map.events[x]    <= The event ID x.
  121. #
  122. # l.set_opacity(o,p)
  123. # Sets the lantern's opacity, where:
  124. # o is the opacity itself;
  125. # p is the opacity variation.
  126. #
  127. # l.show
  128. # After setting the lantern with the commands above, you may set it to visible
  129. # using this command.
  130. #
  131. # l.hide
  132. # Use this command to set the lantern as invisible.
  133. #
  134. #-------------------------------------------------------------------------------
  135. # * Instructions - 4. Use the effect's surface!
  136. #-------------------------------------------------------------------------------
  137. # The Awesome Light Effects draws the effects on a surface. In order to make
  138. # the effects visible, the effect's surface MUST be visible. The Effect's
  139. # Surface is initialized with it's opacity set to zero. You can call the
  140. # following commands:
  141. #
  142. # s = $game_map.effect_surface
  143. # Gets the Effect's Surface into a variable
  144. #
  145. # s.set_color(r,g,b)
  146. # Changes the Effect's Surface color instantly, where:
  147. # r => red level;
  148. # g => green level;
  149. # b => blue level;
  150. #
  151. # s.set_alpha(a)
  152. # Changes the Effect's Surface opacity instantly to a.
  153. #
  154. # s.change_color(time,r,g,b)
  155. # Changes the Effect's Surface color ONLY in a certain time, where:
  156. # time => The change's time (frames);
  157. # r => red level;
  158. # g => green level;
  159. # b => blue level;
  160. #
  161. # s.change_color(time,r,g,b,a)
  162. # Changes the Effect's Surface color and it's opacity in a certain time, where:
  163. # time => The change's time (frames);
  164. # r => red level;
  165. # g => green level;
  166. # b => blue level;
  167. # a => opacity
  168. #
  169. # s.change_alpha(time,a)
  170. # Changes the Effect's Surface opacity in a certain time, where:
  171. # time => The change's time (frames);
  172. # a => opacity
  173. #
  174. #-------------------------------------------------------------------------------
  175. # * Instructions - 5. Use the effect's surface with Tone command!
  176. #-------------------------------------------------------------------------------
  177. # You can access the Effect's Surface with the "Screen Tone" command. In order
  178. # to turn this feature on, set the "Surface_UE" constant to true.
  179. #
  180. # If you decided to use this feature, please note some details:
  181. # 1. The colors values must be between 0 and 255;
  182. # 2. The time is in frames;
  183. # 3. The "gray" value will be sent as the opacity value
  184. #
  185. #-------------------------------------------------------------------------------
  186. # * Instructions - 6. Setup your Tileset Tags!
  187. #-------------------------------------------------------------------------------
  188. # In order to cut the effect's picture correctly, there's 3 types of behavior
  189. # for a tile: wall, block and roof. Walls will make shadows as real walls,
  190. # blocks as blocks and roofs as roofs. So, the tileset tags MUST be configured.
  191. # Check the demo to understand how this system works. If the tilesets aren't
  192. # configured correctly, the script won't cut the effects correctly.
  193. #
  194. #-------------------------------------------------------------------------------
  195. # * Setup Part
  196. #-------------------------------------------------------------------------------
  197. module Light_Core
  198.   Effects = { #  <= DON'T change this!
  199. #-------------------------------------------------------------------------------
  200. # PUT YOUR EFFECTS HERE!
  201. #-------------------------------------------------------------------------------
  202.   0 => ["light_m",255,0,true],
  203.   1 => ["torch",200,20,true],
  204.   2 => ["torch_m",180,30,true],
  205.   3 => ["light_s",255,0,true],
  206.   
  207. #-------------------------------------------------------------------------------
  208. # End of effecs configuration
  209. #-------------------------------------------------------------------------------
  210.   } #  <= DON'T change this!
  211.   
  212.   # Z coordinate of the Effect's Surface
  213.   Surface_Z = 180
  214.   
  215.   # Enable Effect's Surface control by "Screen Tone" command?
  216.   Surface_UE = true
  217.   
  218.   # Roof behavior tag
  219.   Roof_Tag = 5
  220.   # Wall behavior tag
  221.   Wall_Tag = 6
  222.   # Block behavior tag
  223.   Block_Tag = 7
  224.   
  225.   # Don't change this!
  226.   ACC = Math.tan(Math::PI/26)
  227. end
  228. #-------------------------------------------------------------------------------
  229. # Script
  230. #-------------------------------------------------------------------------------
  231. module Cache
  232.   def self.light(filename)
  233.     load_bitmap("Graphics/Lights/", filename)
  234.   end
  235. end
  236. module Light_Bitcore
  237.   include Light_Core
  238.   def self.initialize
  239.     @@buffer = {}
  240.     Effects.values.each { |effect| Light_Bitcore.push(effect[0])}
  241.   end
  242.   def self::[](key)
  243.     return @@buffer[key]
  244.   end
  245.   def self.push(key)
  246.     return if @@buffer.keys.include?(key)
  247.     @@buffer[key] = Cache.light(key)
  248.   end
  249. end
  250. Light_Bitcore.initialize
  251. class Light_SSource
  252.   attr_reader :real_x
  253.   attr_reader :real_y
  254.   attr_reader :range
  255.   attr_accessor :bitmap
  256.   attr_reader :w
  257.   attr_reader :h
  258.   attr_reader :hs
  259.   def initialize(char,bitmap,opacity,plus,hs)
  260.     sync(char)
  261.     @key = bitmap
  262.     @bitmap = Light_Bitcore[@key].clone
  263.     @range = @bitmap.width/2
  264.     @w = @bitmap.width
  265.     @h = @bitmap.height
  266.     @mr = @range - 16
  267.     @opacity = opacity
  268.     @plus = plus
  269.     @hs = hs
  270.     render if @hs
  271.   end
  272.   def render
  273.     tx = x
  274.     ty = y
  275.     tsx = x + @range
  276.     tsy = y + @range
  277.     dr = @range*2
  278.     for s in $game_map.surfaces
  279.       next if !s.visible?(tsx,tsy) || !s.within?(tx,tx+dr,ty,ty+dr)
  280.       s.render_shadow(tx,ty,tsx,tsy,@range,@bitmap)
  281.     end
  282.   end
  283.   def restore
  284.     return unless @bitmap.nil?
  285.     @bitmap = Light_Bitcore[@key].clone
  286.     render if @hs
  287.   end
  288.   def opacity
  289.     @plus == 0 ? @opacity : (@opacity + rand(@plus))
  290.   end
  291.   def sx
  292.     return $game_map.adjust_x(@real_x)*32-@mr
  293.   end
  294.   def sy
  295.     return $game_map.adjust_y(@real_y)*32-@mr
  296.   end
  297.   def sync(char)
  298.     @real_x = char.real_x
  299.     @real_y = char.real_y
  300.   end
  301.   def x
  302.     return (@real_x*32 - @mr).to_f
  303.   end
  304.   def y
  305.     return (@real_y*32 - @mr).to_f
  306.   end
  307.   def dispose
  308.     return if @bitmap.nil?
  309.     @bitmap.dispose
  310.     @bitmap = nil
  311.   end
  312. end
  313. class Light_DSource < Light_SSource
  314.   attr_reader :bitmap
  315.   attr_reader :visible
  316.   def initialize
  317.     @key = nil
  318.     @bitmap = nil
  319.     @opacity = 255
  320.     @plus = 0
  321.     @char = $game_player
  322.     @visible = false
  323.   end
  324.   def set_opacity(o,p)
  325.     @opacity = o
  326.     @plus = p
  327.   end
  328.   def set_graphic(sb)
  329.     dispose
  330.     @key = {2=>sb,4=>sb,6=>sb,8=>sb}
  331.     Light_Bitcore.push(sb)
  332.     @bitmap = {2=>Light_Bitcore[@key[2]].clone,4=>Light_Bitcore[@key[4]].clone,6=>Light_Bitcore[@key[6]].clone,8=>Light_Bitcore[@key[8]].clone}
  333.     @range = @bitmap[2].width/2
  334.     @w = @bitmap[2].width
  335.     @h = @bitmap[2].height
  336.     @mr = @range - 16
  337.   end
  338.   def set_multiple_graphics(ba)
  339.     dispose
  340.     @key = ba
  341.     @key.values.each {|key| Light_Bitcore.push(key)}
  342.     @bitmap = {2=>Light_Bitcore[@key[2]].clone,4=>Light_Bitcore[@key[4]].clone,6=>Light_Bitcore[@key[6]].clone,8=>Light_Bitcore[@key[8]].clone}
  343.     @range = @bitmap[2].width/2
  344.     @w = @bitmap[2].width
  345.     @h = @bitmap[2].height
  346.     @mr = @range - 16
  347.   end
  348.   def get_graphic
  349.     return @bitmap[@char.direction].clone
  350.   end
  351.   def show
  352.     return if @bitmap.nil?
  353.     @visible = true
  354.   end
  355.   def hide
  356.     @visible = false
  357.   end
  358.   def restore
  359.     return if @key.nil?
  360.     @key.values.each {|key| Light_Bitcore.push(key)}
  361.     @bitmap = {2=>Light_Bitcore[@key[2]].clone,4=>Light_Bitcore[@key[4]].clone,6=>Light_Bitcore[@key[6]].clone,8=>Light_Bitcore[@key[8]].clone}
  362.   end
  363.   def dispose
  364.     return if @bitmap.nil?
  365.     @bitmap.values.each { |b| b.dispose }
  366.     @bitmap = nil
  367.   end
  368.   def change_owner(char)
  369.     @char = char
  370.   end
  371.   def render
  372.   end
  373.   def sx
  374.     return $game_map.adjust_x(@char.real_x)*32-@mr
  375.   end
  376.   def sy
  377.     return $game_map.adjust_y(@char.real_y)*32-@mr
  378.   end
  379.   def x
  380.     return (@char.real_x*32 - @mr).to_f
  381.   end
  382.   def y
  383.     return (@char.real_y*32 - @mr).to_f
  384.   end
  385. end
  386. class Light_Surface
  387.   def initialize
  388.     @ta = @a = 0
  389.     @tr = @r = 255
  390.     @tg = @g = 255
  391.     @tb = @b = 255
  392.     @va = @vr = @vg = @vb = 0.0
  393.     @timer = 0
  394.   end
  395.   def refresh
  396.     return if @timer == 0
  397.     @a += @va
  398.     @r += @vr
  399.     @g += @vg
  400.     @b += @vb
  401.     $game_map.light_surface.opacity = @a
  402.     @timer -= 1
  403.   end
  404.   def change_color(time,r,g,b,a=nil)
  405.     r = 0 if r < 0; r = 255 if r > 255
  406.     g = 0 if g < 0; g = 255 if g > 255
  407.     b = 0 if b < 0; b = 255 if b > 255
  408.     unless a.nil?
  409.       a = 0 if a < 0; a = 255 if a > 255
  410.     end
  411.     @timer = time
  412.     @tr = 255-r
  413.     @tg = 255-g
  414.     @tb = 255-b
  415.     @va = (a.nil? ? 0 : (a-@a).to_f/@timer)
  416.     @vr = (@tr - @r).to_f/@timer
  417.     @vg = (@tg - @g).to_f/@timer
  418.     @vb = (@tb - @b).to_f/@timer
  419.   end
  420.   def change_alpha(time,a)
  421.     a = 0 if a < 0; a = 255 if a > 255
  422.     @timer = time
  423.     @ta = a
  424.     @vr = @vg = @vb = 0.0
  425.     @va = (a-@a).to_f/@timer
  426.   end
  427.   def set_color(r,g,b)
  428.     r = 0 if r < 0; r = 255 if r > 255
  429.     g = 0 if g < 0; g = 255 if g > 255
  430.     b = 0 if b < 0; b = 255 if b > 255
  431.     @tr = @r = 255-r
  432.     @tg = @g = 255-g
  433.     @tb = @b = 255-b
  434.     @va = @vr = @vg = @vb = 0.0
  435.     @timer = 0
  436.   end
  437.   def set_alpha(a)
  438.     a = 0 if a < 0; a = 255 if a > 255
  439.     @ta = @a = a
  440.     $game_map.light_surface.opacity = @a
  441.     @va = @vr = @vg = @vb = 0.0
  442.     @timer = 0
  443.   end
  444.   def alpha
  445.     return @a
  446.   end
  447.   def color
  448.     return Color.new(@r,@g,@b)
  449.   end
  450. end
  451. class Game_Map
  452.   include Light_Core
  453.   attr_accessor :light_surface
  454.   attr_accessor :light_sources
  455.   attr_accessor :surfaces
  456.   attr_accessor :effect_surface
  457.   attr_accessor :lantern
  458.   alias kbl_setup_events setup_events
  459.   alias kbl_initialize initialize
  460.   alias kbl_update update
  461.   def initialize
  462.     kbl_initialize
  463.     @effect_surface = Light_Surface.new
  464.     @lantern = Light_DSource.new
  465.   end
  466.   def update(arg)
  467.     @effect_surface.refresh if arg
  468.     kbl_update(arg)
  469.   end
  470.   def first_tag(x,y)
  471.     tag = tileset.flags[tile_id(x,y,0)] >> 12
  472.     return tag > 0 ? tag : 0
  473.   end
  474.   def setup_events
  475.     @light_sources.nil? ? @light_sources = [] : @light_sources.clear
  476.     setup_surfaces
  477.     merge_surfaces
  478.     kbl_setup_events
  479.   end
  480.   def setup_surfaces
  481.     @surfaces = []
  482.     for x in 0..(width-1)
  483.       for y in 0..(height-1)
  484.         tag = first_tag(x,y)
  485.         if tag == Wall_Tag
  486.           i = tile_id(x,y,0)
  487.           if i & 0x02 == 0x02
  488.             @surfaces << Block_SD.new(x*32,y*32,x*32+32,y*32)
  489.           end
  490.           if i & 0x04 == 0x04
  491.             @surfaces << Block_WR.new(x*32+31,y*32,x*32+31,y*32+32)
  492.             @surfaces << Block_IL.new(x*32+32,y*32,x*32+32,y*32+32)
  493.           end
  494.           if i & 0x01 == 0x01
  495.             @surfaces << Block_IR.new(x*32-1,y*32,x*32-1,y*32+32)
  496.             @surfaces << Block_WL.new(x*32,y*32,x*32,y*32+32)
  497.           end
  498.         elsif tag == Roof_Tag
  499.           i = tile_id(x,y,0)
  500.           @surfaces << Block_SU.new(x*32,y*32,x*32+32,y*32) if i & 0x02 == 0x02
  501.           @surfaces << Block_SR.new(x*32+31,y*32,x*32+31,y*32+32) if i & 0x04 == 0x04
  502.           @surfaces << Block_SL.new(x*32,y*32,x*32,y*32+32) if i & 0x01 == 0x01
  503.         elsif tag == Block_Tag
  504.           f = tileset.flags[tile_id(x,y,0)]
  505.           @surfaces << Block_SL.new(x*32,y*32,x*32,y*32+32) if f & 0x02 == 0x02
  506.           @surfaces << Block_SR.new(x*32+31,y*32,x*32+31,y*32+32) if f & 0x04 == 0x04
  507.           @surfaces << Block_SU.new(x*32,y*32,x*32+32,y*32) if f & 0x08 == 0x08
  508.         end
  509.       end
  510.     end
  511.   end
  512.   def merge_surfaces
  513.     new_surfaces = []
  514.     hs = []; vs = []
  515.     ws = []; is = []
  516.     for surface in @surfaces
  517.       if surface.type & 0x05 == 0
  518.         hs << surface
  519.       else
  520.         if surface.type & 0x010 == 0
  521.           vs << surface
  522.         else
  523.           if surface.type & 0x08 == 0
  524.             ws << surface
  525.           else
  526.             is << surface
  527.           end
  528.         end
  529.       end
  530.     end
  531.     for surface in hs
  532.       surface.ready ? next : surface.ready = true
  533.       for s in hs
  534.         next if s.ready || s.y1 != surface.y1 || surface.type != s.type
  535.         if s.x2 == surface.x1
  536.           surface.x1 = s.x1
  537.           s.trash = true
  538.           s.ready = true
  539.           surface.ready = false
  540.         elsif s.x1 == surface.x2
  541.           surface.x2 = s.x2
  542.           s.trash = true
  543.           s.ready = true
  544.           surface.ready = false
  545.         end
  546.       end
  547.     end
  548.     hs.each { |s| @surfaces.delete(s) if s.trash}
  549.     for surface in vs
  550.       surface.ready ? next : surface.ready
  551.       for s in vs
  552.         next if s.ready || s.x1 != surface.x1
  553.         if s.y2 == surface.y1
  554.           surface.y1 = s.y1
  555.           s.trash = true
  556.           s.ready = true
  557.           surface.ready = false
  558.         elsif s.y1 == surface.y2
  559.           surface.y2 = s.y2
  560.           s.trash = true
  561.           s.ready = true
  562.           surface.ready = false
  563.         end
  564.       end
  565.     end
  566.     vs.each { |s| @surfaces.delete(s) if s.trash}
  567.     for surface in ws
  568.       surface.ready ? next : surface.ready
  569.       for s in ws
  570.         next if s.ready || s.x1 != surface.x1
  571.         if s.y2 == surface.y1
  572.           surface.y1 = s.y1
  573.           s.trash = true
  574.           s.ready = true
  575.           surface.ready = false
  576.         elsif s.y1 == surface.y2
  577.           surface.y2 = s.y2
  578.           s.trash = true
  579.           s.ready = true
  580.           surface.ready = false
  581.         end
  582.       end
  583.     end
  584.     ws.each { |s| @surfaces.delete(s) if s.trash}
  585.     for surface in is
  586.       surface.ready ? next : surface.ready
  587.       for s in is
  588.         next if s.ready || s.x1 != surface.x1
  589.         if s.y2 == surface.y1
  590.           surface.y1 = s.y1
  591.           s.trash = true
  592.           s.ready = true
  593.           surface.ready = false
  594.         elsif s.y1 == surface.y2
  595.           surface.y2 = s.y2
  596.           s.trash = true
  597.           s.ready = true
  598.           surface.ready = false
  599.         end
  600.       end
  601.     end
  602.     is.each { |s| @surfaces.delete(s) if s.trash}
  603.   end
  604. end
  605. class Game_Event < Game_Character
  606.   alias kbl_initialize initialize
  607.   alias kbl_setup_page setup_page
  608.   def initialize(m,e)
  609.     @light = nil
  610.     kbl_initialize(m,e)
  611.   end
  612.   def setup_page(np)
  613.     kbl_setup_page(np)
  614.     setup_light(np.nil?)
  615.   end
  616.   def setup_light(dispose)
  617.     unless @light.nil?
  618.       $game_map.light_sources.delete(self)
  619.       @light.dispose
  620.       @light = nil
  621.     end
  622.     unless dispose && @list.nil?
  623.       for command in @list
  624.         if command.code == 108 && command.parameters[0].include?("[light")
  625.           command.parameters[0].scan(/\[light ([0.0-9.9]+)\]/)
  626.           effect = Light_Core::Effects[$1.to_i]
  627.           @light = Light_SSource.new(self,effect[0],effect[1],effect[2],effect[3])
  628.           $game_map.light_sources << self
  629.           return
  630.         end
  631.       end
  632.     end
  633.   end
  634.   def draw_light
  635.     sx = @light.sx
  636.     sy = @light.sy
  637.     w = @light.w
  638.     h = @light.h
  639.     return if sx > Graphics.width && sy > Graphics.height && sx + w < 0 && sy + h < 0
  640.     $game_map.light_surface.bitmap.blt(sx,sy,@light.bitmap,Rect.new(0,0,w,h),@light.opacity)
  641.   end
  642.   def dispose_light
  643.     @light.dispose
  644.   end
  645.   def restore_light
  646.     @light.restore
  647.   end
  648. end
  649. if Light_Core::Surface_UE
  650.   class Game_Interpreter
  651.     def command_223
  652.       $game_map.effect_surface.change_color(@params[1],@params[0].red,@params[0].green,@params[0].blue,@params[0].gray)
  653.       wait(@params[1]) if @params[2]
  654.     end
  655.   end
  656. end
  657. class Game_Interpreter
  658.   def self_event
  659.     return $game_map.events[@event_id]
  660.   end
  661. end
  662. class Block_Surface
  663.   include Light_Core
  664.   attr_accessor :x1
  665.   attr_accessor :y1
  666.   attr_accessor :x2
  667.   attr_accessor :y2
  668.   attr_accessor :ready
  669.   attr_accessor :trash
  670.   def initialize(x1,y1,x2,y2)
  671.     @x1 = x1
  672.     @y1 = y1
  673.     @x2 = x2
  674.     @y2 = y2
  675.     @ready = false
  676.     @trash = false
  677.   end
  678.   def within?(min_x,max_x,min_y,max_y)
  679.     return @x2 > min_x && @x1 < max_x && @y2 > min_y && @y1 < max_y
  680.   end
  681. end
  682. class Block_SL < Block_Surface
  683.   attr_reader :type
  684.   def initialize(x1,y1,x2,y2)
  685.     super(x1,y1,x2,y2)
  686.     @type = 0x01
  687.   end
  688.   def visible?(sx,sy)
  689.     return sx < @x1
  690.   end
  691.   def render_shadow(phx,phy,sx,sy,range,bitmap)
  692.     @m1 = (@y1-sy)/(@x1-sx)
  693.     @n1 = sy - @m1*sx
  694.     @m2 = (@y2-sy)/(@x2-sx)
  695.     @n2 = sy - @m2*sx
  696.     for x in @x1..(sx+range)
  697.       init = shadow_iy(x)
  698.       bitmap.clear_rect(x-phx,init-phy,1,shadow_fy(x)-init+3)
  699.     end
  700.   end
  701.   def shadow_iy(x)
  702.     return @m1*x+@n1
  703.   end
  704.   def shadow_fy(x)
  705.     return @m2*x+@n2
  706.   end
  707. end
  708. class Block_SR < Block_Surface
  709.   attr_reader :type
  710.   def initialize(x1,y1,x2,y2)
  711.     super(x1,y1,x2,y2)
  712.     @type = 0x04
  713.   end
  714.   def visible?(sx,sy)
  715.     return sx > @x1
  716.   end
  717.   def render_shadow(phx,phy,sx,sy,range,bitmap)
  718.     @m1 = (@y1-sy)/(@x1-sx)
  719.     @n1 = sy - @m1*sx
  720.     @m2 = (@y2-sy)/(@x2-sx)
  721.     @n2 = sy - @m2*sx
  722.     for x in (sx-range).to_i..@x1
  723.       init = shadow_iy(x)
  724.       bitmap.clear_rect(x-phx,init-phy,1,shadow_fy(x)-init+3)
  725.     end
  726.   end
  727.   def shadow_iy(x)
  728.     return @m1*x+@n1
  729.   end
  730.   def shadow_fy(x)
  731.     return @m2*x+@n2
  732.   end
  733. end
  734. class Block_IL < Block_Surface
  735.   attr_reader :type
  736.   def initialize(x1,y1,x2,y2)
  737.     super(x1,y1,x2,y2)
  738.     @type = 0x019
  739.   end
  740.   def visible?(sx,sy)
  741.     return sx < @x1 && sy > @y1
  742.   end
  743.   def render_shadow(phx,phy,sx,sy,range,bitmap)
  744.     @m1 = (@y1-sy)/(@x1-sx)
  745.     @n1 = @y1 - @m1*@x1
  746.     @m2 = (@y2-sy)/(@x2-sx)
  747.     @m2 = 0 if @m2 > 0
  748.     @n2 = @y2 - @m2*@x2
  749.     for x in @x1..(sx+range)
  750.       init = shadow_iy(x).floor
  751.       bitmap.clear_rect(x-phx,init-3-phy,1,shadow_fy(x)-init+3)
  752.     end
  753.   end
  754.   def shadow_iy(x)
  755.     return @m1*x+@n1
  756.   end
  757.   def shadow_fy(x)
  758.     return @m2*x+@n2
  759.   end
  760. end
  761. class Block_IR < Block_Surface
  762.   attr_reader :type
  763.   def initialize(x1,y1,x2,y2)
  764.     super(x1,y1,x2,y2)
  765.     @type = 0x01c
  766.   end
  767.   def visible?(sx,sy)
  768.     return sx > @x1 && sy > @y1
  769.   end
  770.   def render_shadow(phx,phy,sx,sy,range,bitmap)
  771.     @m1 = (@y1-sy)/(@x1-sx)
  772.     @n1 = @y1 - @m1*@x1
  773.     @m2 = (@y2-sy)/(@x2-sx)
  774.     @m2 = 0 if @m2 < 0
  775.     @n2 = @y2 - @m2*@x2
  776.     for x in (sx-range).to_i..@x1
  777.       init = shadow_iy(x).floor
  778.       bitmap.clear_rect(x-phx,init-3-phy,1,shadow_fy(x)-init+3)
  779.     end
  780.   end
  781.   def shadow_iy(x)
  782.     return @m1*x+@n1
  783.   end
  784.   def shadow_fy(x)
  785.     return @m2*x+@n2
  786.   end
  787. end
  788. class Block_WL < Block_Surface
  789.   attr_reader :type
  790.   def initialize(x1,y1,x2,y2)
  791.     super(x1,y1,x2,y2)
  792.     @type = 0x011
  793.   end
  794.   def visible?(sx,sy)
  795.     return sx < @x1 && sy < @y2
  796.   end
  797.   def render_shadow(phx,phy,sx,sy,range,bitmap)
  798.     @m1 = (@y1-sy)/(@x1-sx)
  799.     @n1 = sy - @m1*sx
  800.     @m2 = (@y2-sy)/(@x2-sx)
  801.     @n2 = sy - @m2*sx
  802.     for x in @x1..(sx+range)
  803.       init = shadow_iy(x)
  804.       bitmap.clear_rect(x-phx,init-phy,1,shadow_fy(x)-init+2)
  805.     end
  806.   end
  807.   def shadow_iy(x)
  808.     return @m1*x+@n1
  809.   end
  810.   def shadow_fy(x)
  811.     return @m2*x+@n2
  812.   end
  813. end
  814. class Block_WR < Block_Surface
  815.   attr_reader :type
  816.   def initialize(x1,y1,x2,y2)
  817.     super(x1,y1,x2,y2)
  818.     @type = 0x014
  819.   end
  820.   def visible?(sx,sy)
  821.     return sx > @x1 && sy < @y2
  822.   end
  823.   def render_shadow(phx,phy,sx,sy,range,bitmap)
  824.     @m1 = (@y1-sy)/(@x1-sx)
  825.     @n1 = sy - @m1*sx
  826.     @m2 = (@y2-sy)/(@x2-sx)
  827.     @n2 = sy - @m2*sx
  828.     for x in (sx-range).to_i..@x1
  829.       init = shadow_iy(x)
  830.       bitmap.clear_rect(x-phx,init-phy,1,shadow_fy(x)-init+2)
  831.     end
  832.   end
  833.   def shadow_iy(x)
  834.     return @m1*x+@n1
  835.   end
  836.   def shadow_fy(x)
  837.     return @m2*x+@n2
  838.   end
  839. end
  840. class Block_SU < Block_Surface
  841.   attr_reader :type
  842.   def initialize(x1,y1,x2,y2)
  843.     super(x1,y1,x2,y2)
  844.     @type = 0x02
  845.   end
  846.   def visible?(sx,sy)
  847.     return sy < @y1
  848.   end
  849.   def render_shadow(phx,phy,sx,sy,range,bitmap)
  850.     if @x1 == sx
  851.       @m1 = nil
  852.     else
  853.       @m1 = (@y1-sy)/(@x1-sx)
  854.       @m1 += ACC if @m1 < -ACC
  855.       @n1 = @y1 - @m1*@x1
  856.     end
  857.     if @x2 == sx
  858.       @m2 = nil
  859.     else
  860.       @m2 = (@y2-sy)/(@x2-sx)
  861.       @n2 = sy - @m2*sx
  862.     end
  863.     for y in @y1..(sy+range)
  864.       init = shadow_ix(y)
  865.       bitmap.clear_rect(init-phx,y-phy,shadow_fx(y)-init+1,1)
  866.     end
  867.   end
  868.   def shadow_ix(y)
  869.     return @m1.nil? ? @x1 : (y-@n1)/@m1
  870.   end
  871.   def shadow_fx(y)
  872.     return @m2.nil? ? @x2 : (y-@n2)/@m2
  873.   end
  874. end
  875. class Block_SD < Block_Surface
  876.   attr_reader :type
  877.   def initialize(x1,y1,x2,y2)
  878.     super(x1,y1,x2,y2)
  879.     @type = 0x08
  880.   end
  881.   def visible?(sx,sy)
  882.     return sy > @y1
  883.   end
  884.   def render_shadow(phx,phy,sx,sy,range,bitmap)
  885.     if @x1 == sx
  886.       @m1 = nil
  887.     else
  888.       @m1 = (@y1-sy)/(@x1-sx)
  889.       @m1 -= ACC if @m1 > ACC
  890.       @n1 = sy - @m1*sx
  891.     end
  892.     if x2 == sx
  893.       @m2 = nil
  894.     else
  895.       @m2 = (@y2-sy)/(@x2-sx)
  896.       @n2 = sy - @m2*sx
  897.     end
  898.     for y in (sy-range).to_i..@y1
  899.       init = shadow_ix(y)
  900.       bitmap.clear_rect(init-phx,y-phy,shadow_fx(y)-init+1,1)
  901.     end
  902.   end
  903.   def shadow_ix(y)
  904.     return @m1.nil? ? @x1 : (y-@n1)/@m1
  905.   end
  906.   def shadow_fx(y)
  907.     return @m2.nil? ? @x2 : (y-@n2)/@m2
  908.   end
  909. end
  910. class Spriteset_Map
  911.   include Light_Core
  912.   alias kbl_initialize initialize
  913.   alias kbl_update update
  914.   alias kbl_dispose dispose
  915.   def initialize
  916.     setup_lights
  917.     kbl_initialize
  918.   end
  919.   def update
  920.     kbl_update
  921.     update_lights
  922.   end
  923.   def dispose
  924.     kbl_dispose
  925.     dispose_lights
  926.   end
  927.   def dispose_lights
  928.     $game_map.lantern.dispose
  929.     $game_map.light_sources.each { |source| source.dispose_light }
  930.     $game_map.light_surface.bitmap.dispose
  931.     $game_map.light_surface.dispose
  932.     $game_map.light_surface = nil
  933.   end
  934.   def update_lights
  935.     $game_map.light_surface.bitmap.clear
  936.     $game_map.light_surface.bitmap.fill_rect(0,0,Graphics.width,Graphics.height,$game_map.effect_surface.color)
  937.     $game_map.light_sources.each { |source| source.draw_light }
  938.     return unless $game_map.lantern.visible
  939.     @btr = $game_map.lantern.get_graphic
  940.     x = $game_map.lantern.x
  941.     y = $game_map.lantern.y
  942.     r = $game_map.lantern.range
  943.     sx = x + r
  944.     sy = y + r
  945.     dr = r*2
  946.     $game_map.surfaces.each { |s| s.render_shadow(x,y,sx,sy,r,@btr) if s.visible?(sx,sy) && s.within?(x,x+dr,y,y+dr) }
  947.     $game_map.light_surface.bitmap.blt($game_map.lantern.sx,$game_map.lantern.sy,@btr,Rect.new(0,0,dr,dr),$game_map.lantern.opacity)
  948.   end
  949.   def setup_lights
  950.     @btr = nil
  951.     $game_map.lantern.restore
  952.     $game_map.light_sources.each { |source| source.restore_light }
  953.     $game_map.light_surface = Sprite.new
  954.     $game_map.light_surface.bitmap = Bitmap.new(Graphics.width,Graphics.height)
  955.     $game_map.light_surface.bitmap.fill_rect(0,0,Graphics.width,Graphics.height,$game_map.effect_surface.color)
  956.     $game_map.light_surface.blend_type = 2
  957.     $game_map.light_surface.opacity = $game_map.effect_surface.alpha
  958.     $game_map.light_surface.z = Surface_Z
  959.   end
  960. end
复制代码

作者: mollyko    时间: 2020-3-14 10:45
Cupidk爱呗茶 发表于 2020-3-13 23:12
小改了一点 刚刚稍微测试了下 在640X480或者更高分辨率下光源暂时没有任何问题了  可以随着分辨率提高而自 ...

太感谢了!
作者: daysp2    时间: 2020-3-14 12:40
没用过这个脚本的我想知道,这个是直接加个图片做图层吗?
图层的混合模式能调成“叠加”嘛?
作者: mollyko    时间: 2020-3-14 17:35
daysp2 发表于 2020-3-14 12:40
没用过这个脚本的我想知道,这个是直接加个图片做图层吗?
图层的混合模式能调成“叠加”嘛? ...

不用加图片!
https://forum.gamer.com.tw/C.php?bsn=04918&snA=22567
这里是教程,你可以看看~




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1