| 赞 | 400  | 
 
| VIP | 0 | 
 
| 好人卡 | 24 | 
 
| 积分 | 250 | 
 
| 经验 | 45372 | 
 
| 最后登录 | 2024-7-2 | 
 
| 在线时间 | 3339 小时 | 
 
 
 
 
 
Lv5.捕梦者 (版主) 
	- 梦石
 - 1 
 
        - 星屑
 - 23998 
 
        - 在线时间
 - 3339 小时
 
        - 注册时间
 - 2011-7-8
 
        - 帖子
 - 3925
 
 
  
 
 | 
	
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员  
 
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
 
  复制代码 |   
 
评分
- 
查看全部评分
 
 
 
 
 
 |