Project1
标题:
ISA——支持子选项的选择窗口(理论支持无限层)
[打印本页]
作者:
沙漠点灰
时间:
2011-4-3 10:04
标题:
ISA——支持子选项的选择窗口(理论支持无限层)
本帖最后由 沙漠点灰 于 2011-4-3 10:16 编辑
先上效果图(?):
截图.jpg
(44.97 KB, 下载次数: 30)
下载附件
保存到相册
2011-4-3 10:01 上传
比较鸡肋...
关于这个脚本的用法,稍后会发放范例(
http://rpg.blue/thread-174282-1-1.html
)
这张截图里面用的格式是:
commands = ["dust",["a","b",["c","c1",["c1_1","c1_2","c1_3"]],"d","f"],"p"]
@folder_window = Window_Folder.new(50,96,480,32*8,commands)
有点晕...?数组类(含子选项要求超过1个)会判定为"文件夹",该数组第2,3一直到最后1个会判定为
"子选项",当然,这些"子选项"还可以是"文件夹",以次类推
50,96,480,32*8 分别是x,y,宽,高
这个版本不是很完美,期待下个版本吧(不过极有可能TJ掉)
最后,上脚本(技术有限,比较臃肿...):
#==============================================================================
# ■ Window_Folder ISA
#------------------------------------------------------------------------------
# 拥有光标的移动以及滚动功能、子项目的窗口类。
# ISA
# 制作 : 沙漠.灰
# 本脚本版本 : v0.9 P.S : 制作中遇到了一个Bug,找了3个小时,不惜动用rescue
# 最后发现是 if @folder_window.index = [0,2] .....写成了 = 号了...
#
# 本脚本很无敌(指的是Bug方面).欢迎各位朋友进行优化及DeBug
#==============================================================================
class Window_Folder < Window_Base
#--------------------------------------------------------------------------
# ● 定义实例变量
#--------------------------------------------------------------------------
attr_reader :index # 光标位置
attr_reader :c # C 键允许
#--------------------------------------------------------------------------
# ● 初始画对像
# x : 窗口的 X 坐标
# y : 窗口的 Y 坐标
# width : 窗口的宽
# height : 窗口的高
#--------------------------------------------------------------------------
def initialize(x,y,width, height, commands)
super(x, y, width, height)
# 初始化数据
@move_to = 0
@to_refresh = false
@commands_size = 0
@c = false
@index = [0]
@spread_command = []
@disable_item = []
commands.size.times{@spread_command.push(1)}
@true_commands = commands
# 初始化所有项目
ini_command @true_commands
# 生成位图
self.contents = Bitmap.new(width - 32, @commands_size * 32)
v = Viewport.new(16+self.x, 16+self.y, width-32, height-32) ; v.z = 999
@new_bitmap = Sprite.new(v)
@new_bitmap.bitmap = Bitmap.new(width - 32, @commands_size * 32)
index = 0 # 描绘顶层项目
# 描绘父项目
for unit in @true_commands
# 描写项目
draw_command [index]
# index 前进1
index += 1
end
end
#--------------------------------------------------------------------------
# ● 初始化所有项目 array : 父项目
#--------------------------------------------------------------------------
def ini_command(array)
for unit in array
if unit.is_a?(Array)
unit.size > 1 ? ini_command(unit): @commands_size += 1
else
@commands_size += 1
end
end
end
#--------------------------------------------------------------------------
# ● 项目无效化
# index : 项目编号
#--------------------------------------------------------------------------
def disable_item(index)
@disable_item.push(index)
end
#--------------------------------------------------------------------------
# ● 指定项目是否为父项目 index 所在位置
#--------------------------------------------------------------------------
def is_folder?(commands,index)
# 若指定项目为数组且子单元数目大于1就判定为父项目
if index.size == 1 and commands[index[0]].is_a?(Array)
return true if commands[index[0]].size > 1
elsif index.size > 1
return is_folder?(commands[index[0]],index[1...index.size])
end
# 否则就判定为非父项目
return false
end
#--------------------------------------------------------------------------
# ● 描绘项目名称 index 所在位置 branch 是否分支
#--------------------------------------------------------------------------
def draw_command(index,branch=false)
# 查看当前index所在坐标
x, y = check_index_xy(index)
rect = Rect.new(x+32,y,self.width-32,32)
self.contents.font.color = disabled_color if @disable_item.include?(index)
name = get_command(@true_commands,index)
self.contents.draw_text(rect, name)
# 为父项目时,描绘指引
if is_folder?(@true_commands,index)
draw_flag(index,branch)
end
self.contents.font.color = normal_color
end
#--------------------------------------------------------------------------
# ● 取得项目名称 index 所在位置
#--------------------------------------------------------------------------
def get_command(name_array,index)
# 当index到底时(只有一个单元时)
return get_command_name(name_array[index[0]]) if index.size == 1
# 没到底,删除首单元,继续调用自己
# 删除首单元?为嘛不用shift? 因为shift删除首单元,并返回它...
return get_command name_array[index[0]],index[1...index.size]
end
#--------------------------------------------------------------------------
# ● 再次 取得项目名称 index 所在位置
#--------------------------------------------------------------------------
def get_command_name(name_array)
if name_array.is_a?(String)
# 目前已经为字符串时,直接返回
return name_array
else
# 目前为数组且数组第X个还是数组时,调用并返回自己
if name_array[0].is_a?(Array)
return get_command_name(name_array[0])
else
# 第X个为字符串,直接返回
return name_array[0]
end
end
end
#--------------------------------------------------------------------------
# ● 描绘项目标记 index 所在位置
#--------------------------------------------------------------------------
def draw_flag(index,branch=false)
# 查看当前index所在坐标
x, y = check_index_xy index
src_rect = Rect.new(x+16,y+10,16,16)
# 清除原来标记
self.contents.fill_rect(src_rect, Color.new(0,0,0,0))
dest_rect = branch ? Rect.new(152, 40, 16, 16): Rect.new(168, 24, 16, 16)
src_bitmap= RPG::Cache.windowskin($game_system.windowskin_name)
# 图上现在标记
self.contents.stretch_blt(src_rect, src_bitmap, dest_rect)
end
#--------------------------------------------------------------------------
# ● 检查 index 所在坐标
#--------------------------------------------------------------------------
def check_index_xy(index)
y = 0
# 检查项目 多1项,y+32
for i in 0...@spread_command.size
# 检查缩进项目,为数组时,进一步检查
if @spread_command[i].is_a?(Array)
# 在这个项目活动....
if index.size > 1
y += check_spread(@spread_command[i], index[1...index.size])
else
# 否则,加1行
y += 32
end
else
# 上次的没关闭,则自相加
#if @spread_command[i-1].is_a?(Array)
#y += @spread_command[i-1].self_all_plus * 32 - 32
#end
# 这个版本不支持↑,这里直接加32
y += 32#@spread_command[i] * 32
end
break if index[0] <= i
end
# 检查本index所有上面的展开数
#size = size(index)*32
# 多1层,x+32
return index.new_to_s.size/3*32-32, y-32
end
#--------------------------------------------------------------------------
# ● 检查展开项目,返回项目数
#--------------------------------------------------------------------------
def check_spread(spread_array,index)
y = 0
# 检查项目 多1项,y+32
for i in 0...spread_array.size
# 检查缩进项目,为数组时,进一步检查
if spread_array[i].is_a?(Array)
# 在这个项目活动....
if index.size > 1
y += check_spread(spread_array[i],index[1...index.size])
else
# 否则,加1行
y += 32
end
else
# 上次的没关闭,则自相加
#if @spread_command[i-1].is_a?(Array)
#y += @spread_command[i-1].self_all_plus * 32 - 32
#end
# 这个版本不支持↑,这里直接加32
y += 32#@spread_command[i] * 32
end
break if index[0] <= i
end
return y
end
#--------------------------------------------------------------------------
# ● 释放
#--------------------------------------------------------------------------
def dispose
# 释放新的位图 精灵
@new_bitmap.bitmap.dispose
@new_bitmap.dispose
super
end
#--------------------------------------------------------------------------
# ● 设置光标的位置
# index : 新的光标位置
#--------------------------------------------------------------------------
def index=(index)
@index = index
# 刷新光标矩形
update_cursor_rect
end
#--------------------------------------------------------------------------
# ● 检查指定项目大小 index :
#--------------------------------------------------------------------------
def check_command_size(index,commands=@true_commands)
# 在次选项下,返回次commands的单元数
return commands.size if index.size == 1
# 删首调自
return check_command_size(index[1...index.size],commands[index[0]])
end
#--------------------------------------------------------------------------
# ● 关闭\展开父选项
#--------------------------------------------------------------------------
def folder(index,close=true)
if close
# 关闭时
# 如果当前为父选项,关闭它,若已经关闭,关闭此层(顶层除外)
# 把需关闭的子项目清空,10帧淡入淡出
if closed?(index)
# 顶层...?
return if index.size == 1
# 关闭上层
folder(index[0...index-1],close)
return
end
x1, y1 = check_index_xy(index)
new_height = check_command_size(index+[1]) * 32
Graphics.freeze
eval("@spread_command#{@index.new_to_s} = 1 ")
src_rect = Rect.new(0,0,self.width,self.contents.height)
dest_rect = Rect.new(0,y1+new_height,self.width,self.contents.height)
@new_bitmap.bitmap.stretch_blt(src_rect, self.contents, dest_rect)
# 把当前信息"剪切"到新位图上,使之移动
src_rect = Rect.new(0,y1,self.width,self.contents.height)
self.contents.fill_rect(src_rect, Color.new(0,0,0,0))
@new_bitmap.y= y1 + new_height
@move_to = -new_height + 32
@to_refresh = -1
draw_command(@index,false)
Graphics.transition(10)
else
# 展开时
# 如果当前为父选项,展开它,若已经展开,什么也不做
# 把需展开的子项目写入位图,10帧淡入淡出
return if !is_folder?(@true_commands,index)
if !closed?(index)
@index.push(1)
return
end
new_height = check_command_size(index+[0]) * 32 - 32
x1, y1 = check_index_xy(index+[0])
@new_bitmap.bitmap.clear
@new_bitmap.y = y1 + 32
src_rect = Rect.new(0 ,0 ,self.width,self.contents.height)
dest_rect = Rect.new(0,y1+32,self.width,self.contents.height)
@new_bitmap.bitmap.stretch_blt(src_rect, self.contents, dest_rect)
# 把当前信息"剪切"到新位图上,使之移动
src_rect = Rect.new(0,y1,self.width,self.contents.height)
self.contents.fill_rect(src_rect, Color.new(0,0,0,0))
@move_to = new_height
@to_refresh = 1
draw_command(@index,true)
size = "1," * check_command_size(@index+[0])
eval("@spread_command#{@index.new_to_s} = [#{size}] ")
end
end
#--------------------------------------------------------------------------
# ● 移动项目
#--------------------------------------------------------------------------
def move_command
if @move_to == 0 and @to_refresh != 0
if @to_refresh == 1
@to_refresh = 0
for i in 1...check_command_size(@index+[0])
draw_command(@index+[i])
end
Graphics.freeze
# "剪切"回来
src_rect = Rect.new(@new_bitmap.x,@new_bitmap.y,self.width,self.contents.height)
dest_rect = Rect.new(0,0,self.width,self.contents.height)
self.contents.stretch_blt(src_rect, @new_bitmap.bitmap, dest_rect)
@new_bitmap.bitmap.clear
Graphics.transition(10)
@index.push(1)
else
@to_refresh = 0
# "剪切"回来
src_rect = Rect.new(@new_bitmap.x,@new_bitmap.y,self.width,self.contents.height)
dest_rect = Rect.new(0,0,self.width,self.contents.height)
self.contents.stretch_blt(src_rect, @new_bitmap.bitmap, dest_rect)
@new_bitmap.bitmap.clear
end
end
return if @move_to == 0
step = @move_to/@move_to.abs * 4
@move_to -= step
@new_bitmap.y += step
end
#--------------------------------------------------------------------------
# ● 父选项已关闭?
#--------------------------------------------------------------------------
def closed?(index,commands=@spread_command)
# @spread_command 记录着展开的信息:若为数组,则展开;否则,关闭
return true if !commands[index[0]].is_a?(Array)
return closed?(index[1...index.size],commands[index[0]]) if index.size > 1
return false
end
#--------------------------------------------------------------------------
# ● 刷新画面
#--------------------------------------------------------------------------
def update
super
move_command
return if @to_refresh != 0
# 可以移动光标的情况下
if self.active
# 方向键下被按下的情况下
if Input.repeat?(Input::DOWN)
$game_system.se_play($data_system.cursor_se)
# 跳跃到下一个同层选项
@index[-1] = (@index[-1]+1)%check_command_size(@index)
@index[-1] += 1 if @index.size > 1 and @index[-1] == 0
end
# 方向键上被按下的情况下
if Input.repeat?(Input::UP)
# 跳跃到上一个同层选项
$game_system.se_play($data_system.cursor_se)
# 跳跃到下一个同层选项
@index[-1] -= 1 if @index.size > 1 and @index[-1] == 1
@index[-1] = (@index[-1]-1)%check_command_size(@index)
end
# A键被按下的情况下
if Input.trigger?(Input::A)
# 展开\关闭 当前选项,展开优先
# 这个功能暂时被和谐掉...
#p @new_bitmap.x, @new_bitmap.y
end
# B键被按下的情况下
if Input.trigger?(Input::B)
# 退到上一层,若允许关闭,则关闭
if @index.size == 1
$game_system.se_play($data_system.buzzer_se)
else
@index.pop
$game_system.se_play($data_system.cancel_se)
# 允许关闭的情况下
folder(@index) # if $game_party.closed_by_b
end
end
# C键被按下的情况下
if Input.trigger?(Input::C)
@c = !is_folder?(@true_commands,@index)
# 展开当前选项,不能展开时,打开允许C键键入开关(否则关掉)
# 等待场景捕捉动作
if is_folder?(@true_commands,@index)
$game_system.se_play($data_system.decision_se)
folder(@index,false)
end
end
end
# 刷新光标矩形
update_cursor_rect
end
#--------------------------------------------------------------------------
# ● 更新光标矩形
#--------------------------------------------------------------------------
def update_cursor_rect
x, y = check_index_xy(@index)
# 超出范围,更新self.oy
if y - self.oy >= self.height - 32
self.oy += 32
@new_bitmap.oy += 32
elsif y - self.oy < 0
self.oy -= 32
@new_bitmap.oy -= 32
end
# 更新光标矩形
self.cursor_rect.set(x, y-self.oy,
[email protected]
_to_s.size/3*32, 32)
end
end
#==============================================================================
# ■ Array
#------------------------------------------------------------------------------
# 数组类 又拿数组开刀...
#==============================================================================
class Array
#--------------------------------------------------------------------------
# ● 转换 新 字符串
#--------------------------------------------------------------------------
def new_to_s
string = ""
for unit in self
string += "[#{unit}]"
end
return string
end
=begin
#--------------------------------------------------------------------------
# ● 自相加
#--------------------------------------------------------------------------
def self_all_plus(array=self)
plus = 0
for unit in self
if unit.is_a?(Array)
plus += self_all_plus(unit)
else
plus += unit.to_i
end
end
return plus
end
=end
end
复制代码
作者:
SVM伟
时间:
2011-4-3 12:47
432行,的确蛮臃肿的,估计可以大幅度缩水
作者:
kuerlulu
时间:
2013-8-13 17:15
坟= =
LZ签名碉堡!如果是用RM做的我也要做一个
欢迎光临 Project1 (https://rpg.blue/)
Powered by Discuz! X3.1