#----------------------------------------------------------------------------
# ● 无限图层显示系统 Unlimited Layers Display System By Taroxd
# XP 移植 By RyanBern
#----------------------------------------------------------------------------
#
# 使用方法:导入此脚本后,在游戏主目录新建一个名为 ULDS_Data 的文件夹,然后
# 新建 txt 文本文件 ULDS000.txt,其中 000 请替换成真正的地图 ID。
# 此后在此 txt 文件里面加入如下内容。
#
# 注意:保存 txt 文件请务必使用 UTF-8 编码,否则其中的中文不会被正常识别。
# 如果文件名里面没有中文则无影响。
#
# 另:本脚本会尝试和原版 ULDS 保持一致,固不再单独写出版本号。
#
# <ulds=filename>
# x: X坐标
# 公式,默认为 0
# y: Y坐标
# 公式,默认为 0
# z: Z坐标
# 公式,只计算一次,默认为 10,可以设置为 -100 来当作远景图使用
# zoom: 缩放倍率
# 公式,默认为 1。缩放的原点为画面左上角。
# zoom_x: 横向缩放倍率
# 公式,默认为 zoom
# zoom_y: 纵向缩放倍率
# 公式,默认为 zoom
# opacity: 不透明度
# 公式,默认为 255
# blend_type: 合成方式
# 公式,只计算一次。默认为 0 (0:正常、1:加法、2:减法)
# scroll: 图像跟随地图卷动的速度
# 实数,默认为 32
# scroll_x: 图像跟随地图横向卷动的速度
# 实数,默认为 scroll
# scroll_y:图像跟随地图纵向卷动的速度
# 实数,默认为 scroll
# loop: 循环
# 冒号后面不需要填写任何东西。
# visible: 图像是否显示
# 公式,默认为 true
# path: 图像的路径名
# 默认为 Parallaxes
# color: 合成的颜色
# 公式,只计算一次。默认为 Color.new(0, 0, 0, 0)
# tone: 色调
# 公式,只计算一次。默认为 Tone.new(0, 0, 0, 0)
# eval: 初始化后,以 sprite 或 plane 为 self 执行的代码。
# 公式,默认为空
# update: 图片显示时,每帧执行的更新代码
# 公式,默认为 t += 1
# dispose: 图片释放前执行的代码
# 公式,默认为空
# </ulds>
#
# 其中 filename 是图片文件名(无需扩展名),放入 Pictures 文件夹内
# 这个文件夹可以通过 path 设置更改
#
# 在 <ulds=filename> 和 </ulds> 中间的部分均为选填。不填则自动设为默认值。
# 每一个设置项只能写一行。
# 每一行只能写一个设置项。
# 一般来说,正常使用时大部分都是不需要设置的。
#
# 设置项目中的“公式”表示,这一个设置项可以像技能的伤害公式一样填写。
# “只计算一次”表示,该公式只会在刚刚进入地图时计算一次,之后不会更新。
# 可用 t 表示当前已经显示的帧数,s[n], v[n] 分别表示 n 号开关和 n 号变量。
# width 表示图片宽度,height 表示图片高度。
#
# 例:
# <ulds=BlueSky>
# x: t
# scroll_x: 16
# scroll_y: 64
# loop:
# </ulds>
#
# 需要多行公式时,可以重复备注。
# 例:
# <ulds=Slime>
# path: Battlers
# x: width / 2
# y: height / 2
# eval: self.ox = width / 2
# eval: self.oy = height / 2
# eval: self.angle = 180
# </ulds>
#
#----------------------------------------------------------------------------
# z 坐标详解:
# ulds 图层的坐标和地图画面的三个视口(Viewport)是独立的,具体设定如下
# 【0】最低图块层、在普通角色下方
# 【1~200】在地图所有内容的上方(包括远景图,任意优先度的图块,角色图,雾图形)
# 【201~3000】在【显示图片】所产生的图片上方
# 【>3000】在【画面闪烁】效果的上方
# 目前暂不支持在地图内容上的分割(例如不能设置为在角色上方而在雾图形下方),
# 如果有需求可考虑添加。
#----------------------------------------------------------------------------
# 更新记录:
# 2014.07.10 Ver1.01: 修正了 zoom、zoom_y 会报错的问题
# 2014.07.11 Ver1.02: 修正了切换图块组之后失效的问题
# 2014.08.14 Ver1.1: 增加了 speed_x, speed_y 的设置
# 2014.08.16 Ver1.2: fix 设定更改为 scroll
# 2014.08.29 Ver1.21: 修正了坐标误差
# 2014.09.19 Ver1.22: 修正了远景图与图层使用相同文件时报错的问题
# 2014.09.25 Ver2.0: 属性可以用公式进行设置了;其他细节改进
# 2014.09.26 Ver2.01: 增加了 path、update 的设置
# 2015.01.02 Ver2.1: 增加了 init、color、tone 的设置;其他细节改进
# 2015.01.03 Ver2.11: 修复了 zoom 属性会导致坐标误差的问题
# 2015.02.02 Ver2.12: 支持多行备注和公式中的 width 和 height;其他细节改进
# 2015.07.04 Ver2.13: 修复了循环时可能不会更新的问题
# 2017.03.22 Ver2.15: 允许文件名为空,即备注 <ulds></ulds>
# 2017.05.10 Ver2.16: 增加了 dispose 设置
#----------------------------------------------------------------------------
module Taroxd; end
module Taroxd::ULDS
DEFAULT_PATH = 'Pictures' # 图片文件的默认路径
DEFAULT_Z = 10 # 默认的 z 值
RE_OUTER = /<ulds[= ]?(.*?)>(.*?)<\/ulds>/mi # 读取备注用的正则表达式
RE_INNER = /(\w+) *: *(.*)/ # 读取设置用的正则表达式
MAPDATA_PREFIX = 'ULDS_Data'
module Base
include Math
attr_accessor :scroll_x, :scroll_y
def dispose
bitmap.dispose
super
end
def adjust_x
1.0 * @scroll_x * $game_map.display_x / 128
#return x if @scroll_x.abs < Float::EPSILON
#$game_map.display_x / (128.0 / @scroll_x)
#$game_map.adjust_x(1.0 * x / @scroll_x) * @scroll_x
end
def adjust_y
1.0 * @scroll_y * $game_map.display_y / 128
#return y if @scroll_y.abs < Float::EPSILON
#$game_map.display_y / (128.0 / @scroll_y)
#$game_map.adjust_y(1.0 * y / @scroll_y) * @scroll_y
end
end
class Sprite < ::Sprite
include Base
def x=(x)
self.ox = adjust_x
super
#super(-adjust_x(x))
end
def y=(y)
self.oy = adjust_y
super
#super(-adjust_y(y))
end
end
class Plane < ::Plane
include Base
attr_reader :visible
def initialize(_)
super
@visible = true
end
def x=(x)
self.ox = adjust_x + x
end
def y=(y)
self.oy = adjust_y + y
end
def visible=(visible)
super
@visible = visible
end
def width
bitmap.width
end
def height
bitmap.height
end
end
class << self
# 从备注中读取设置,并生成数组
def from_note(note, viewport)
note.scan(RE_OUTER).map do |name, contents|
settings = {nil => name}
contents.scan(RE_INNER) do |key, value|
(settings[key] ||= '') << value << "\n"
end
new(settings, viewport)
end
end
# 返回一个 ULDS::Sprite 或 ULDS::Plane 的实例
def new(settings, viewport)
@settings = settings
container(viewport)
end
private
def container(viewport)
container = (extract('loop') ? Plane : Sprite).new(viewport)
container.bitmap = make_bitmap
container.instance_eval(init_container_code, __FILE__, __LINE__)
container
end
# 在一个 sprite 或 plane 的上下文中执行的代码。
# 如果难以理解,请尝试输出这段代码来查看。
def init_container_code
"#{binding_code}
#{init_attr_code}
#{define_update_code}
#{define_dispose_code}
#{extract 'eval'}"
end
# 定义变量的代码
def binding_code
's = $game_switches
v = $game_variables
t = 0'
end
# 只计算一次的初始化代码
def init_attr_code
"#{set_attr_code 'z', DEFAULT_Z}
#{set_attr_code 'scroll_x', 32}
#{set_attr_code 'scroll_y', 32}
#{set_attr_code 'blend_type'}
#{set_attr_code 'color'}
#{set_attr_code 'tone'}"
end
# 更新的代码
def define_update_code
%{
define_singleton_method :update do
#{set_attr_code 'visible'}
return unless visible
#{set_attr_code 'zoom_x'}
#{set_attr_code 'zoom_y'}
#{set_attr_code 'opacity'}
#{set_attr_code 'x', 0}
#{set_attr_code 'y', 0}
#{set_t_code}
end
}
end
def define_dispose_code
code = extract('dispose')
!code ? "" : %{
define_singleton_method :dispose do
#{code}
super()
end
}
end
# 设置属性的代码
def set_attr_code(key, default = nil)
formula = extract(key, default)
formula && "self.#{key} = (#{formula})"
end
# 设置时间的代码
def set_t_code
extract('update', 't += 1')
end
# 获得位图
def make_bitmap
basename = extract(nil)
if !basename.empty?
folder_name = "Graphics/#{extract('path', DEFAULT_PATH).chomp}"
Bitmap.new("#{folder_name}/#{basename}")
else
nil
end
end
# 获取备注中的设定值
def extract(key, default = nil)
@settings[key] || /(.+)_[xy]\Z/ =~ key && @settings[$1] || default
end
end
end
class Game_Map
def note
filename = sprintf("%s/ULDS%03d.txt", Taroxd::ULDS::MAPDATA_PREFIX, @map_id)
if File.exist?(filename)
File.open(filename) do |f|
return f.read
end
else
return ""
end
end
end
class Spriteset_Map
def create_ulds
@ulds = Taroxd::ULDS.from_note($game_map.note, nil)
@ulds_map_id = $game_map.map_id
end
def refresh_ulds
dispose_ulds
create_ulds
end
def update_ulds
refresh_ulds if @ulds_map_id != $game_map.map_id
@ulds.each {|u| u.update}
end
def dispose_ulds
@ulds.each {|u| u.dispose}
end
# 导入 -- 没有 taroxd 那么醋的我只好瑟瑟发抖地 alias
alias rb_initialize_ulds initialize
def initialize
create_ulds
rb_initialize_ulds
end
alias rb_update_ulds update
def update
update_ulds
rb_update_ulds
end
alias rb_dispose_ulds dispose
def dispose
dispose_ulds
rb_dispose_ulds
end
end
# XP does not have define_singleton_method, then define it manually
class Object
def define_singleton_method(sym, &block)
class << self; self; end.send(:define_method, sym, &block)
end
end