赞 | 400 |
VIP | 0 |
好人卡 | 24 |
积分 | 250 |
经验 | 45372 |
最后登录 | 2024-7-2 |
在线时间 | 3339 小时 |
Lv5.捕梦者 (版主)
- 梦石
- 1
- 星屑
- 23994
- 在线时间
- 3339 小时
- 注册时间
- 2011-7-8
- 帖子
- 3926
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 guoxiaomi 于 2021-7-28 11:09 编辑
相关问题:
https://rpg.blue/thread-486363-1-1.html
示意图:
解决这个问题,通常的做法是创建一个Scene类,然后用事件call这个类,就跟使用商店一样。上面的示意图也就是我们所想要的效果:整个场景分为4部分,当左下或者右下窗口激活时,按下空格来交换队伍里的物品和储物箱里的物品。
接下来我会仔细的讲解该如何写这个脚本。对于RGSS的初学者来说,可以当作写Scene的教程。这个教程会逐步完善场景类所需的各种内容,并且每完成一小部分就会展示一下效果。
【第一节:场景类的基本结构】
首先创建一个模块,以避免跟其他的脚本同名,后续的所有类的定义都是在这个模块里进行。这里使用提问者的名字Taeckle作为模块名。
接下来创建场景的类Scene_Storage。这个场景的类需要包括:
1. main方法,在范例里,main方法被拆分成了3部分:create_windows,scene_loop和dispose_windows。
create_windows 用来创建4个窗口,使用几个比较基础的窗口类作为place holder,这里只是用来检查窗口位置是否正确,此方法会在后面的步骤里被新的定义覆盖:# ----------------------------------------- # # Help Window (640 x 64) # # ----------------------------------------- # # Menu Window (640 x 64) # # --------------------+-------------------- # # Item Window Party | Item Window Storage # # (320 x 352) | (320 x 352) # # --------------------+-------------------- # def create_windows # Help Window @help_window = Window_Help.new # Horizontal Command Window @menu_window = Window_Selectable.new(0, 64, 640, 64) # Item Window left: Party items @item_window_party = Window_Selectable.new(0, 128, 320, 480 - 64 * 2) # Item Window right: Storage items @item_window_storage = Window_Selectable.new(320, 128, 320, 480 - 64 * 2) end
# ----------------------------------------- #
# Help Window (640 x 64) #
# ----------------------------------------- #
# Menu Window (640 x 64) #
# --------------------+-------------------- #
# Item Window Party | Item Window Storage #
# (320 x 352) | (320 x 352) #
# --------------------+-------------------- #
def create_windows
# Help Window
@help_window = Window_Help.new
# Horizontal Command Window
@menu_window = Window_Selectable.new(0, 64, 640, 64)
# Item Window left: Party items
@item_window_party = Window_Selectable.new(0, 128, 320, 480 - 64 * 2)
# Item Window right: Storage items
@item_window_storage = Window_Selectable.new(320, 128, 320, 480 - 64 * 2)
end
scene_loop 直接照抄RGSS的内容。dispose_windows使用RGSS3的风格,将属于Scene的所有Window类的实例对象关闭。
由于scene_loop里呼叫了update方法,所以还需要创建一个空的update方法。
2. 数据的处理,这个场景涉及到RGSS以外的数据。所以需要定义数据的类型Data,以及场景所需的实例变量@data。
考虑到具体要解决的问题是储物箱,所以该场景要占用一个全局变量来存储数据,把这个变量的ID传给场景的initialize方法。顺便传递了储存箱最大能装的数量作为第2个参数。
def initialize(data_vid, item_max_size = 99) @scene_class = $scene.class @item_max_size = [item_max_size, 99].min if !$game_variables[data_vid].is_a?(Data) $game_variables[data_vid] = Data.new end @data = $game_variables[data_vid] end
def initialize(data_vid, item_max_size = 99)
@scene_class = $scene.class
@item_max_size = [item_max_size, 99].min
if !$game_variables[data_vid].is_a?(Data)
$game_variables[data_vid] = Data.new
end
@data = $game_variables[data_vid]
end
在initialize方法里,会检测传入的全局变量是否为Data类型,如果不是就初始化一下,然后绑定此全局变量。
储物箱应该要提供存入和取出两个方法。定义store和fetch两个空方法,其参数是要存储的东西和数量(默认为1)
最终脚本如下:# encoding: utf-8 module Taeckle @version = "0.1" class Data end class Scene_Storage attr_reader :data def initialize(data_vid, item_max_size = 99) @scene_class = $scene.class @item_max_size = [item_max_size, 99].min if !$game_variables[data_vid].is_a?(Data) $game_variables[data_vid] = Data.new end @data = $game_variables[data_vid] end def main create_windows scene_loop dispose_windows end # layout # ----------------------------------------- # # Help Window (640 x 64) # # ----------------------------------------- # # Menu Window (640 x 64) # # --------------------+-------------------- # # Item Window Party | Item Window Storage # # (320 x 352) | (320 x 352) # # --------------------+-------------------- # def create_windows # Help Window @help_window = Window_Help.new # Horizontal Command Window @menu_window = Window_Selectable.new(0, 64, 640, 64) # Item Window left: Party items @item_window_party = Window_Selectable.new(0, 128, 320, 480 - 64 * 2) # Item Window right: Storage items @item_window_storage = Window_Selectable.new(320, 128, 320, 480 - 64 * 2) end def update end def scene_loop Graphics.transition # 主循环 loop do # 刷新游戏画面 Graphics.update # 刷新输入信息 Input.update # 刷新画面 update # 如果画面切换就中断循环 if $scene != self break end end # 准备过渡 Graphics.freeze end def dispose_windows self.instance_variables.each do |name| obj = self.instance_variable_get(name) obj.dispose if obj.is_a?(Window) end end def store(item, number = 1) end def fetch(item, number = 1) end end end
# encoding: utf-8
module Taeckle
@version = "0.1"
class Data
end
class Scene_Storage
attr_reader :data
def initialize(data_vid, item_max_size = 99)
@scene_class = $scene.class
@item_max_size = [item_max_size, 99].min
if !$game_variables[data_vid].is_a?(Data)
$game_variables[data_vid] = Data.new
end
@data = $game_variables[data_vid]
end
def main
create_windows
scene_loop
dispose_windows
end
# layout
# ----------------------------------------- #
# Help Window (640 x 64) #
# ----------------------------------------- #
# Menu Window (640 x 64) #
# --------------------+-------------------- #
# Item Window Party | Item Window Storage #
# (320 x 352) | (320 x 352) #
# --------------------+-------------------- #
def create_windows
# Help Window
@help_window = Window_Help.new
# Horizontal Command Window
@menu_window = Window_Selectable.new(0, 64, 640, 64)
# Item Window left: Party items
@item_window_party = Window_Selectable.new(0, 128, 320, 480 - 64 * 2)
# Item Window right: Storage items
@item_window_storage = Window_Selectable.new(320, 128, 320, 480 - 64 * 2)
end
def update
end
def scene_loop
Graphics.transition
# 主循环
loop do
# 刷新游戏画面
Graphics.update
# 刷新输入信息
Input.update
# 刷新画面
update
# 如果画面切换就中断循环
if $scene != self
break
end
end
# 准备过渡
Graphics.freeze
end
def dispose_windows
self.instance_variables.each do |name|
obj = self.instance_variable_get(name)
obj.dispose if obj.is_a?(Window)
end
end
def store(item, number = 1)
end
def fetch(item, number = 1)
end
end
end
【第二节:测试工程】
创建一个空白的工程,并且将写好的scene_storage_base.rb插入到脚本编辑器的main前。根据具体的需求,创建如下自动事件:
按F12执行,进入新游戏后,自动执行本事件,就会进入到Scene_Storage里了。这个时候场景里还是一片空白:
【第三节:数据结构】
接下来我们需要完善Data类,以及store和fetch两个方法。ruby允许随时打开一个类添加新的内容,也允许覆盖原来的同名方法。
1. Data类是存储在箱子里的物品、武器等。所以Data类可以直接套用Game_Party的部分内容:
class Data attr_reader :item attr_reader :weapons attr_reader :armors def initialize @items = {} @weapons = {} @armors = {} end # ... end
class Data
attr_reader :item
attr_reader :weapons
attr_reader :armors
def initialize
@items = {}
@weapons = {}
@armors = {}
end
# ...
end
复制粘贴Game_Party的item_number, weapon_number, armor_number, gain_item, gain_weapon, gain_armor这6个方法即可。
由于拥有完全相同的6个方法和对应的数据结构,Game_Party和Data的实例在某些地方可以互相替换。详见后面的@bind_data部分。
2. store方法,需要根据传入的变量的不同类型(item/weapon/armor),来选择调用指定的方法。此外,当箱子或者队伍的背包已经满了的时候,就不能继续放入物品,定义一个函数来判断这种情况:
def can_store?(num_party, num_storage, number) num_party - number >= 0 && num_party - number <= 99 && num_storage + number >= 0 && num_storage + number <= @item_max_size end
def can_store?(num_party, num_storage, number)
num_party - number >= 0 && num_party - number <= 99 && num_storage + number >= 0 && num_storage + number <= @item_max_size
end
考虑到存储物品可能会失败,store方法的返回值是true或者false,以表示这次存储是成功还是失败。
fetch方法就是store方法,只不过第二个参数是负的。
最终脚本如下:# encoding: utf-8 module Taeckle @version = "0.2" class Data attr_reader :item attr_reader :weapons attr_reader :armors def initialize @items = {} @weapons = {} @armors = {} end #-------------------------------------------------------------------------- # ● 获取物品的所持数 # item_id : 物品 ID #-------------------------------------------------------------------------- def item_number(item_id) # 如果 hash 个数数值不存在就返回 0 return @items.include?(item_id) ? @items[item_id] : 0 end #-------------------------------------------------------------------------- # ● 获取武器所持数 # weapon_id : 武器 ID #-------------------------------------------------------------------------- def weapon_number(weapon_id) # 如果 hash 个数数值不存在就返回 0 return @weapons.include?(weapon_id) ? @weapons[weapon_id] : 0 end #-------------------------------------------------------------------------- # ● 获取防具所持数 # armor_id : 防具 ID #-------------------------------------------------------------------------- def armor_number(armor_id) # 如果 hash 个数数值不存在就返回 0 return @armors.include?(armor_id) ? @armors[armor_id] : 0 end #-------------------------------------------------------------------------- # ● 增加物品 (减少) # item_id : 物品 ID # n : 个数 #-------------------------------------------------------------------------- def gain_item(item_id, n) # 更新 hash 的个数数据 if item_id > 0 @items[item_id] = [[item_number(item_id) + n, 0].max, 99].min end end #-------------------------------------------------------------------------- # ● 增加武器 (减少) # weapon_id : 武器 ID # n : 个数 #-------------------------------------------------------------------------- def gain_weapon(weapon_id, n) # 更新 hash 的个数数据 if weapon_id > 0 @weapons[weapon_id] = [[weapon_number(weapon_id) + n, 0].max, 99].min end end #-------------------------------------------------------------------------- # ● 增加防具 (减少) # armor_id : 防具 ID # n : 个数 #-------------------------------------------------------------------------- def gain_armor(armor_id, n) # 更新 hash 的个数数据 if armor_id > 0 @armors[armor_id] = [[armor_number(armor_id) + n, 0].max, 99].min end end end class Scene_Storage def store(item, number = 1) # RPG::Item if item.is_a?(RPG::Item) num_party = $game_party.item_number(item.id) num_storage = @data.item_number(item.id) if can_store?(num_party, num_storage, number) $game_party.lose_item(item.id, number) @data.gain_item(item.id, number) return true end end # RPG::Weapon if item.is_a?(RPG::Weapon) num_party = $game_party.weapon_number(item.id) num_storage = @data.weapon_number(item.id) if can_store?(num_party, num_storage, number) $game_party.lose_weapon(item.id, number) @data.gain_weapon(item.id, number) return true end end # RPG::Armor if item.is_a?(RPG::Armor) num_party = $game_party.armor_number(item.id) num_storage = @data.armor_number(item.id) if can_store?(num_party, num_storage, number) $game_party.lose_armor(item.id, number) @data.gain_armor(item.id, number) return true end end return false end def fetch(item, number = 1) store(item, -number) end def can_store?(num_party, num_storage, number) num_party - number >= 0 && num_party - number <= 99 && num_storage + number >= 0 && num_storage + number <= @item_max_size end end end
# encoding: utf-8
module Taeckle
@version = "0.2"
class Data
attr_reader :item
attr_reader :weapons
attr_reader :armors
def initialize
@items = {}
@weapons = {}
@armors = {}
end
#--------------------------------------------------------------------------
# ● 获取物品的所持数
# item_id : 物品 ID
#--------------------------------------------------------------------------
def item_number(item_id)
# 如果 hash 个数数值不存在就返回 0
return @items.include?(item_id) ? @items[item_id] : 0
end
#--------------------------------------------------------------------------
# ● 获取武器所持数
# weapon_id : 武器 ID
#--------------------------------------------------------------------------
def weapon_number(weapon_id)
# 如果 hash 个数数值不存在就返回 0
return @weapons.include?(weapon_id) ? @weapons[weapon_id] : 0
end
#--------------------------------------------------------------------------
# ● 获取防具所持数
# armor_id : 防具 ID
#--------------------------------------------------------------------------
def armor_number(armor_id)
# 如果 hash 个数数值不存在就返回 0
return @armors.include?(armor_id) ? @armors[armor_id] : 0
end
#--------------------------------------------------------------------------
# ● 增加物品 (减少)
# item_id : 物品 ID
# n : 个数
#--------------------------------------------------------------------------
def gain_item(item_id, n)
# 更新 hash 的个数数据
if item_id > 0
@items[item_id] = [[item_number(item_id) + n, 0].max, 99].min
end
end
#--------------------------------------------------------------------------
# ● 增加武器 (减少)
# weapon_id : 武器 ID
# n : 个数
#--------------------------------------------------------------------------
def gain_weapon(weapon_id, n)
# 更新 hash 的个数数据
if weapon_id > 0
@weapons[weapon_id] = [[weapon_number(weapon_id) + n, 0].max, 99].min
end
end
#--------------------------------------------------------------------------
# ● 增加防具 (减少)
# armor_id : 防具 ID
# n : 个数
#--------------------------------------------------------------------------
def gain_armor(armor_id, n)
# 更新 hash 的个数数据
if armor_id > 0
@armors[armor_id] = [[armor_number(armor_id) + n, 0].max, 99].min
end
end
end
class Scene_Storage
def store(item, number = 1)
# RPG::Item
if item.is_a?(RPG::Item)
num_party = $game_party.item_number(item.id)
num_storage = @data.item_number(item.id)
if can_store?(num_party, num_storage, number)
$game_party.lose_item(item.id, number)
@data.gain_item(item.id, number)
return true
end
end
# RPG::Weapon
if item.is_a?(RPG::Weapon)
num_party = $game_party.weapon_number(item.id)
num_storage = @data.weapon_number(item.id)
if can_store?(num_party, num_storage, number)
$game_party.lose_weapon(item.id, number)
@data.gain_weapon(item.id, number)
return true
end
end
# RPG::Armor
if item.is_a?(RPG::Armor)
num_party = $game_party.armor_number(item.id)
num_storage = @data.armor_number(item.id)
if can_store?(num_party, num_storage, number)
$game_party.lose_armor(item.id, number)
@data.gain_armor(item.id, number)
return true
end
end
return false
end
def fetch(item, number = 1)
store(item, -number)
end
def can_store?(num_party, num_storage, number)
num_party - number >= 0 && num_party - number <= 99 && num_storage + number >= 0 && num_storage + number <= @item_max_size
end
end
end
将这个脚本加入到编辑器里,再次测试,应该得到跟第二节一样的效果。因为我们还没有写具体的窗口绘制。
【第四节:场景的update】
接下来我们要实现留空的update方法。在这个具体的任务里,有3个窗口,我们绘制一张简图来描述场景里各个窗口之间的切换:
这部分比较考验对RGSS的熟悉程度,总之按照RGSS的写法:
首先更新@help_window,然后依次判断是否有窗口处于active的状态,如果是就执行这个窗口的更新,主要是处理各个按键触发时要执行的内容。记得加上SE,以及各窗口refresh的时机和修改index = -1以隐藏光标。这些细节可以仔细阅读RGSS默认的各个Scene的update的实现。
注意在选择“退出”的写法,@scene_class记录了上一个场景的类(在initialize方法里),退出时利用这个值恢复了上一个场景。不定义这个变量,在此处直接写$scene = Scene_Map.new也是一样的。
然后我们需要定义各个窗口类,并设置好窗口创建时的初始状态。
1. Window_Help,直接就是RGSS默认的Window_Help:class Window_Help < ::Window_Help end
class Window_Help < ::Window_Help
end
2. Window_Menu,有可以移动的光标,所以继承自Window_Selectable。这里要参考RGSS默认的Window_ShopCommand的写法。由于绑定了@help_window,所以需要定义update_help方法:def update_help case @index when 0 then text = "存入物品" when 1 then text = "取出物品" when 2 then text = "离开场景" end @help_window.set_text(text, 1) end
def update_help
case @index
when 0 then text = "存入物品"
when 1 then text = "取出物品"
when 2 then text = "离开场景"
end
@help_window.set_text(text, 1)
end
3. Window_Item,左下和右下两个窗口,都是展示携带的物品,所以可以用同一种窗口类来实现。这两个窗口除了位置不同外,唯一的区别就是展示的数据不同,所以定义@bind_data这个实例变量表示要展示的数据来源。对于左下窗口,@bind_data = $game_party;对于右下窗口@bind_data = $scene.data。同样有可以移动的光标,所以也继承自Window_Selectable。
定义三个空方法待后续完善:item,refresh和update_help。item需要返回此窗口当前被选中的item,供场景类的store和fetch调用。class Window_Item < ::Window_Selectable attr_accessor :bind_data def item end def refresh end def update_help end end
class Window_Item < ::Window_Selectable
attr_accessor :bind_data
def item
end
def refresh
end
def update_help
end
end
定义好了所有的窗口后,覆写create_windows方法,将这些窗口添加到类里,并且设置正确的位置和初始条件。尤其要注意bind_data的设置。最终脚本如下:# encoding: utf-8 module Taeckle @version = "0.3" class Scene_Storage def update @help_window.update # update active window if @menu_window.active @menu_window.update if Input.trigger?(Input::C) $game_system.se_play($data_system.decision_se) case @menu_window.index when 0 @item_window_party.active = true @menu_window.active = false if @item_window_party.index == -1 @item_window_party.index = 0 end when 1 @item_window_storage.active = true @menu_window.active = false if @item_window_storage.index == -1 @item_window_storage.index = 0 end when 2 $scene = @scene_class.new return end @item_window_party.refresh @item_window_storage.refresh end return end if @item_window_party.active @item_window_party.update if Input.trigger?(Input::B) $game_system.se_play($data_system.cancel_se) @item_window_party.active = false @menu_window.active = true @item_window_party.index = -1 @item_window_storage.index = -1 @item_window_party.refresh @item_window_storage.refresh end if Input.trigger?(Input::C) ret = store(@item_window_party.item) if ret $game_system.se_play($data_system.decision_se) @item_window_party.refresh @item_window_storage.refresh else $game_system.se_play($data_system.buzzer_se) end end return end if @item_window_storage.active @item_window_storage.update if Input.trigger?(Input::B) $game_system.se_play($data_system.cancel_se) @item_window_storage.active = false @menu_window.active = true @item_window_party.index = -1 @item_window_storage.index = -1 @item_window_party.refresh @item_window_storage.refresh end if Input.trigger?(Input::C) ret = fetch(@item_window_storage.item) if ret $game_system.se_play($data_system.decision_se) @item_window_party.refresh @item_window_storage.refresh else $game_system.se_play($data_system.buzzer_se) end end return end end def create_windows # Help Window @help_window = Window_Help.new # Horizontal Command Window @menu_window = Window_Menu.new @menu_window.active = true # Item Window left: Party items @item_window_party = Window_Item.new(0, 128, 320, 352) @item_window_party.bind_data = $game_party @item_window_party.active = false @item_window_party.index = -1 @item_window_party.refresh # Item Window right: Storage items @item_window_storage = Window_Item.new(320, 128, 320, 352) @item_window_storage.bind_data = @data @item_window_storage.active = false @item_window_storage.index = -1 @item_window_storage.refresh # binding help windows @menu_window.help_window = @help_window @item_window_party.help_window = @help_window @item_window_storage.help_window = @help_window end end class Window_Help < ::Window_Help end class Window_Menu < ::Window_Selectable def initialize super(0, 64, 640, 64) @item_max = 3 @column_max = 3 @index = 0 @commands = ["存入", "取出", "离开"] self.contents = Bitmap.new(width - 32, height - 32) refresh end #-------------------------------------------------------------------------- # ● 刷新 #-------------------------------------------------------------------------- def refresh self.contents.clear for i in 0...@item_max draw_item(i) end end #-------------------------------------------------------------------------- # ● 描绘项目 # index : 项目编号 #-------------------------------------------------------------------------- def draw_item(index) self.contents.draw_text(index * 212 - 12, 0, 212, 32, @commands[index], 1) end def update_help case @index when 0 then text = "存入物品" when 1 then text = "取出物品" when 2 then text = "离开场景" end @help_window.set_text(text, 1) end end class Window_Item < ::Window_Selectable attr_accessor :bind_data def item end def refresh end def update_help end end end
# encoding: utf-8
module Taeckle
@version = "0.3"
class Scene_Storage
def update
@help_window.update
# update active window
if @menu_window.active
@menu_window.update
if Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
case @menu_window.index
when 0
@item_window_party.active = true
@menu_window.active = false
if @item_window_party.index == -1
@item_window_party.index = 0
end
when 1
@item_window_storage.active = true
@menu_window.active = false
if @item_window_storage.index == -1
@item_window_storage.index = 0
end
when 2
$scene = @scene_class.new
return
end
@item_window_party.refresh
@item_window_storage.refresh
end
return
end
if @item_window_party.active
@item_window_party.update
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@item_window_party.active = false
@menu_window.active = true
@item_window_party.index = -1
@item_window_storage.index = -1
@item_window_party.refresh
@item_window_storage.refresh
end
if Input.trigger?(Input::C)
ret = store(@item_window_party.item)
if ret
$game_system.se_play($data_system.decision_se)
@item_window_party.refresh
@item_window_storage.refresh
else
$game_system.se_play($data_system.buzzer_se)
end
end
return
end
if @item_window_storage.active
@item_window_storage.update
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@item_window_storage.active = false
@menu_window.active = true
@item_window_party.index = -1
@item_window_storage.index = -1
@item_window_party.refresh
@item_window_storage.refresh
end
if Input.trigger?(Input::C)
ret = fetch(@item_window_storage.item)
if ret
$game_system.se_play($data_system.decision_se)
@item_window_party.refresh
@item_window_storage.refresh
else
$game_system.se_play($data_system.buzzer_se)
end
end
return
end
end
def create_windows
# Help Window
@help_window = Window_Help.new
# Horizontal Command Window
@menu_window = Window_Menu.new
@menu_window.active = true
# Item Window left: Party items
@item_window_party = Window_Item.new(0, 128, 320, 352)
@item_window_party.bind_data = $game_party
@item_window_party.active = false
@item_window_party.index = -1
@item_window_party.refresh
# Item Window right: Storage items
@item_window_storage = Window_Item.new(320, 128, 320, 352)
@item_window_storage.bind_data = @data
@item_window_storage.active = false
@item_window_storage.index = -1
@item_window_storage.refresh
# binding help windows
@menu_window.help_window = @help_window
@item_window_party.help_window = @help_window
@item_window_storage.help_window = @help_window
end
end
class Window_Help < ::Window_Help
end
class Window_Menu < ::Window_Selectable
def initialize
super(0, 64, 640, 64)
@item_max = 3
@column_max = 3
@index = 0
@commands = ["存入", "取出", "离开"]
self.contents = Bitmap.new(width - 32, height - 32)
refresh
end
#--------------------------------------------------------------------------
# ● 刷新
#--------------------------------------------------------------------------
def refresh
self.contents.clear
for i in 0...@item_max
draw_item(i)
end
end
#--------------------------------------------------------------------------
# ● 描绘项目
# index : 项目编号
#--------------------------------------------------------------------------
def draw_item(index)
self.contents.draw_text(index * 212 - 12, 0, 212, 32, @commands[index], 1)
end
def update_help
case @index
when 0 then text = "存入物品"
when 1 then text = "取出物品"
when 2 then text = "离开场景"
end
@help_window.set_text(text, 1)
end
end
class Window_Item < ::Window_Selectable
attr_accessor :bind_data
def item
end
def refresh
end
def update_help
end
end
end
将这个脚本加入到F11脚本编辑器,执行可以看到如下效果:
可以看到场景里各项window的切换已经做好了,只是现在还没有做好队伍携带的物品的显示。有对齐强迫症的,可以仔细修改Window_Menu的draw_item方法里面的212和-12这两个参数。
【第五节:显示物品的窗口】
刚才给Window_Item留下了3个空的方法:item,refresh和update_help。这里item和update_help照抄RGSS默认的Window_Item。refresh和被refresh调用的draw_item也是基本照抄,但是需要做几点修改:
1. 将所有的$game_party替换成@bind_data
2. 默认的Window_Item是两列,而这个脚本里是一列,修改draw_item里的x和y的设置
3. 默认draw_item会让无法使用的物品显示灰色,改成当前窗口未激活则所有物品显示灰色
4. (可选)额外的需求要求物品按照其desc属性来排序,在refresh方法里添加按照desc排序的内容:# Sort by description if @data.first.respond_to?(:desc) @data.sort! { |a, b| a.desc <=> b.desc } end
# Sort by description
if @data.first.respond_to?(:desc)
@data.sort! { |a, b| a.desc <=> b.desc }
end
最终脚本如下:# encoding: utf-8 module Taeckle @version = "0.4" class Window_Item #-------------------------------------------------------------------------- # ● 获取物品 #-------------------------------------------------------------------------- def item return @data[self.index] end #-------------------------------------------------------------------------- # ● 刷新 #-------------------------------------------------------------------------- def refresh if self.contents != nil self.contents.dispose self.contents = nil end @data = [] # 添加物品 for i in 1...$data_items.size if @bind_data.item_number(i) > 0 @data.push($data_items[i]) end end # 在战斗中以外添加武器、防具 unless $game_temp.in_battle for i in 1...$data_weapons.size if @bind_data.weapon_number(i) > 0 @data.push($data_weapons[i]) end end for i in 1...$data_armors.size if @bind_data.armor_number(i) > 0 @data.push($data_armors[i]) end end end # Sort by description if @data.first.respond_to?(:desc) @data.sort! { |a, b| a.desc <=> b.desc } end # 如果项目数不是 0 就生成位图、重新描绘全部项目 @item_max = @data.size if @item_max > 0 self.contents = Bitmap.new(width - 32, row_max * 32) for i in 0...@item_max draw_item(i) end end end #-------------------------------------------------------------------------- # ● 描绘项目 # index : 项目编号 #-------------------------------------------------------------------------- def draw_item(index) item = @data[index] case item when RPG::Item number = @bind_data.item_number(item.id) when RPG::Weapon number = @bind_data.weapon_number(item.id) when RPG::Armor number = @bind_data.armor_number(item.id) end if self.active self.contents.font.color = normal_color else self.contents.font.color = disabled_color end x = 4 y = index * 32 rect = Rect.new(x, y, self.width / @column_max - 32, 32) self.contents.fill_rect(rect, Color.new(0, 0, 0, 0)) bitmap = RPG::Cache.icon(item.icon_name) opacity = self.contents.font.color == normal_color ? 255 : 128 self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity) self.contents.draw_text(x + 28, y, 212, 32, item.name, 0) self.contents.draw_text(x + 240, y, 16, 32, ":", 1) self.contents.draw_text(x + 256, y, 24, 32, number.to_s, 2) end #-------------------------------------------------------------------------- # ● 刷新帮助文本 #-------------------------------------------------------------------------- def update_help @help_window.set_text(self.item == nil ? "" : self.item.description) end end end
# encoding: utf-8
module Taeckle
@version = "0.4"
class Window_Item
#--------------------------------------------------------------------------
# ● 获取物品
#--------------------------------------------------------------------------
def item
return @data[self.index]
end
#--------------------------------------------------------------------------
# ● 刷新
#--------------------------------------------------------------------------
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
@data = []
# 添加物品
for i in 1...$data_items.size
if @bind_data.item_number(i) > 0
@data.push($data_items[i])
end
end
# 在战斗中以外添加武器、防具
unless $game_temp.in_battle
for i in 1...$data_weapons.size
if @bind_data.weapon_number(i) > 0
@data.push($data_weapons[i])
end
end
for i in 1...$data_armors.size
if @bind_data.armor_number(i) > 0
@data.push($data_armors[i])
end
end
end
# Sort by description
if @data.first.respond_to?(:desc)
@data.sort! { |a, b| a.desc <=> b.desc }
end
# 如果项目数不是 0 就生成位图、重新描绘全部项目
@item_max = @data.size
if @item_max > 0
self.contents = Bitmap.new(width - 32, row_max * 32)
for i in 0...@item_max
draw_item(i)
end
end
end
#--------------------------------------------------------------------------
# ● 描绘项目
# index : 项目编号
#--------------------------------------------------------------------------
def draw_item(index)
item = @data[index]
case item
when RPG::Item
number = @bind_data.item_number(item.id)
when RPG::Weapon
number = @bind_data.weapon_number(item.id)
when RPG::Armor
number = @bind_data.armor_number(item.id)
end
if self.active
self.contents.font.color = normal_color
else
self.contents.font.color = disabled_color
end
x = 4
y = index * 32
rect = Rect.new(x, y, self.width / @column_max - 32, 32)
self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
bitmap = RPG::Cache.icon(item.icon_name)
opacity = self.contents.font.color == normal_color ? 255 : 128
self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
self.contents.draw_text(x + 28, y, 212, 32, item.name, 0)
self.contents.draw_text(x + 240, y, 16, 32, ":", 1)
self.contents.draw_text(x + 256, y, 24, 32, number.to_s, 2)
end
#--------------------------------------------------------------------------
# ● 刷新帮助文本
#--------------------------------------------------------------------------
def update_help
@help_window.set_text(self.item == nil ? "" : self.item.description)
end
end
end
将这段脚本添加到F11脚本编辑器里,效果如图:
范例如下:
20210727-storage.zip
(208.06 KB, 下载次数: 80)
使用的小技巧:
1. 由于数据存储在全局变量里,会跟随存档一起存下来。
2. 场景绑定不同的变量就会对应不同的储物箱。
3. 如果预先设置好变量的内容,就可以做到储物箱在第一次打开时就有东西了。
- $game_variables[2] = Taeckle::Data.new
- $game_variables[2].gain_item(1, 1)
复制代码
4. 设置可以存储的物品上限为0,并且在箱子里的每件物品数量恰好为1,此时箱子里的物品只能取出不能放回。
5. 可以在条件分歧里使用脚本里检查箱子里的内容:- $game_variables[2].item_number(1) > 0
复制代码 |
评分
-
查看全部评分
|