気ままなタンス*プログラミングなどのノートブック

プログラミングやRPGツクール、DTM、VOCALOIDについてのんびり書きます。

【RGSS】アイテムをカテゴリごとに選択できるようにメニューを改造する(自分用メモ)

タイトルどおり。メモしておかないと忘れるので。。

※自分用メモ書きのため、読みづらいです。

RPGツクール系のアイテムメニューだと、どんな種類のアイテムであっても
一覧として一つの画面に全部表示されてしまう。
特殊アイテムや武器防具がごちゃごちゃしていて、非常に見づらい。

そこで、特殊アイテムと通常アイテムを分類して表示できるようにメニューを改造することにした。

改造前のイメージ
picture04.png


改造後(改造前とアイテムの種類が一致していないが、カテゴリごとに表示する仕組みとなっている)
picture01.png

ざっくりと、やることを以下にまとめる。
・分類表示ウィンドウの追加
・アイテム種類の判断メソッドを追加
・アイテムウィンドウの表示処理内からアイテム種類判断メソッドを呼び出し、選択分類によって表示可否を判断する


・分類表示ウィンドウの追加は、特に新規クラスを追加することなくシンプルに(一部省略)
自分で適当に作ったWindow_Selectable @item_type_windowをScene_Item内に追加する。

  1.     #------------------------------------------------------------------------
  2.     # ◆ 表示するアイテムタイプの選択コマンドウィンドウ
  3.     #------------------------------------------------------------------------
  4.     t = ["通常", "種", "麦", "調味料", "麦茶", "貴重品"]
  5.     @item_type_window = Window_Selectable.new(0, 64, 640, 64) 
  6.     @item_type_window.active = true
  7.     @item_type_window.visible = true
  8.     @item_type_window.column_max = t.size
  9.     @item_type_window.item_max = t.size
  10.     @item_type_width = @item_type_window.width / @item_type_window.column_max - 32
  11.     
  12.     @item_type_window.contents = Bitmap.new(640-32, 128)
  13.     tx = 0
  14.     for i in  0..t.size
  15.       @item_type_window.contents.draw_text(tx, 0, @item_type_width, 32, t[i].to_s, 1)
  16.       tx += @item_type_window.width / @item_type_window.column_max
  17.     end
  18.     @item_type_window.index = $item_type_index
$item_type_indexっていうグローバル変数が結構重要。
今選択されているアイテム分類を保持しておく。
ちなみに、分類表示ウィンドウのindexはそれぞれの分類と対応している。
  1.   #------------------------------------------------------------------------
  2.   # ◆ アイテムタイプコマンドのフレーム更新*rinne_grid
  3.   #------------------------------------------------------------------------  
  4.   def update_item_type_window
  5.     type_word = ""
  6.     case @item_type_window.index
  7.     # 通常
  8.     when 0
  9.       type_word = "通常"
  10.     when 1
  11.       type_word = "種"
  12.     when 2
  13.       type_word = "麦"
  14.     when 3
  15.       type_word = "調味料"
  16.     when 4
  17.       type_word = "麦茶"
  18.     when 5
  19.       type_word = "貴重品"
  20.     end
  21.     @help_window.set_text( type_word + "アイテムを表示します")
  22.         
  23.     if Input.trigger?(Input::B)
  24.       $game_system.se_play($data_system.cancel_se)
  25.       @item_type_window.active = false
  26.       # メニュー画面に切り替え
  27.       $scene = Scene_Menu.new(1)
  28.       return
  29.     end
  30.     
  31.     if Input.trigger?(Input::C)
  32.       $game_system.se_play($data_system.decision_se)
  33.       $item_type_index = @item_type_window.index
  34.       @item_window.active = true
  35.       @item_type_window.active = false
  36.       @item_window.index = 0
  37.       @item_window.refresh
  38.       return
  39.     end
  40.   end

・アイテム種類の判断メソッドは以下のようなイメージ
(このメソッドをModule内に定義している。大文字はモジュールの定数)
定数にアイテムIDの範囲、もしくはアイテムIDの一覧を設定しておく。
たとえば、SEED_BASE_START, SEED_BASE_ENDだと、
「種アイテム」の範囲を表している。
(僕のRPGツクールのアイテムデータベースでは45番〜67番目に種アイテムを設定している。)

貴重品に関しては後で処理を追加したこともあって、とりあえず配列でアイテムIDを設定する形とした。
12行目のSPECIAL_ITEM_LISTのこと。ツクールのデータベース上で29番目のアイテムが貴重品
だということにしている(複数指定する場合は、カンマ区切りで[29, 30]とかに設定すればよい)


  1. module Hoge_Module   
  2.   SEED_BASE_START       = 45
  3.   SEED_BASE_END         = 67
  4.   MUGI_BASE_START       = 90
  5.   MUGI_BASE_END         = 112
  6.   SEASONING_BASE_START  = 114
  7.   SEASONING_BASE_END    = 122
  8.   MUGICHA_BASE_START    = 140
  9.   MUGICHA_BASE_END      = 239
  10.   
  11.   # 貴重品リスト
  12.   SPECIAL_ITEM_LIST = [29]
  13.   
  14.   # 麦茶リスト
  15.   MUGICHA_ITEM_LIST = [44]
  16. #-------------------------------------------------------------------------
  17.   # ● アイテム種類の判断
  18.   # id: アイテムID
  19.   # return: 0:通常, 1:種, 2:麦 3:調味料 4:麦茶 5:貴重品
  20.   #-------------------------------------------------------------------------   
  21.   def get_item_type(id)
  22.     item_type = 0
  23.     
  24.     # 種
  25.     if (id >= SEED_BASE_START && id <= SEED_BASE_END)
  26.       item_type = 1
  27.     # 麦
  28.     elsif (id >= MUGI_BASE_START && id <= MUGI_BASE_END) 
  29.       item_type = 2
  30.     # 調味料
  31.     elsif (id >= SEASONING_BASE_START && id <= SEASONING_BASE_END)
  32.       item_type = 3
  33.     # 麦茶
  34.     elsif (id >= MUGICHA_BASE_START && id <= MUGICHA_BASE_END) || MUGICHA_ITEM_LIST.include?(id)
  35.       item_type = 4
  36.     end
  37.     
  38.     # 貴重品
  39.     if SPECIAL_ITEM_LIST.include?(id)
  40.       item_type = 5
  41.     end
  42.     
  43.     # 上記IF文に当てはまらない:通常
  44.     return item_type
  45.   end
  46. end
  
・アイテムウィンドウの処理について。
上記で用意したメソッドを利用する部分。
Scene_Itemの一部を修正する対応でOK。
$data_items[n].idで、アイテムIDが取得できる。
取得したアイテムIDを上記に記述したget_item_typeに渡すことで、
「現在表示すべきアイテムなのかどうか」を判断する。
今回unlessを初めて使った。unless 「もし〜でなければ」について、
「戦闘中」でなければという判断に利用。( unless $game_temp.in_battle)
  1.   def refresh
  2.     if self.contents != nil
  3.       self.contents.dispose
  4.       self.contents = nil
  5.     end
  6.     @data = []
  7.     # アイテムを追加
  8.     unless $game_temp.in_battle
  9.         for i in 1...$data_items.size
  10.           if $game_party.item_number(i) > 0
  11.             if Hoge_Module.get_item_type($data_items[i].id) == $item_type_index
  12.               @data.push($data_items[i])
  13.             end
  14.             
  15.           end
  16.         end
  17.     else
  18.       for i in 1...$data_items.size
  19.         if $game_party.item_number(i) > 0
  20.           @data.push($data_items[i])
  21.         end
  22.       end
  23.     end
  24.     # 戦闘中以外なら武器と防具も追加
  25.     unless $game_temp.in_battle
  26.       if Seed_Module.get_item_type(item.id) == $item_type_index
  27.         for i in 1...$data_weapons.size
  28.           if $game_party.weapon_number(i) > 0
  29.             @data.push($data_weapons[i])
  30.           end
  31.         end
  32.         for i in 1...$data_armors.size
  33.           if $game_party.armor_number(i) > 0
  34.             @data.push($data_armors[i])
  35.           end
  36.         end
  37.       end
  38.     end
  39.     # 項目数が 0 でなければビットマップを作成し、全項目を描画
  40.     @item_max = @data.size
  41.     if @item_max > 0
  42.       self.contents = Bitmap.new(width - 32, row_max * 32)
  43.       for i in 0...@item_max
  44.         draw_item(i)
  45.       end
  46.     end
  47.   end

グローバル変数について、確かセーブデータ間でも共有されてしまうので、
Load、Save時にリフレッシュする対応が必要。
後でどっかにまとめて定義する予定。

【どうでもいい備忘録】
そういえば、グラデーション表示メソッドがあまりに重すぎたため、あわせて改良した。

picture03.png 

写真