4.コマンドウィンドウ
1.コマンドウィンドウ
Window_Commandは、Window_Selectableを継承し、
文字を使用した選択項目を簡単に表示できるようにしたものです。
継承して新しいクラスを作る基盤となるWindow_Selectableに対し、
Window_Commandは、完成されたものなのでそのまま使用することができます。
コマンドウィンドウは、次のように定義されています。
実際にウィンドウを表示するには、下記のように記述します。
いくつかサンプルを用意しました。
普通のウィンドウとは違い、引数で座標の指定ができません。
ですので、表示位置を変更したい場合は次のように行います。
何もしなければ、(0, 0)で左上に表示されます。
ウィンドウの縦幅は、項目の数で指定しますが、
次のようにすることで、サイズを設定することも可能です。
もちろん、表示されていない項目はスクロールで表示されます。
文字を使用した選択項目を簡単に表示できるようにしたものです。
継承して新しいクラスを作る基盤となるWindow_Selectableに対し、
Window_Commandは、完成されたものなのでそのまま使用することができます。
コマンドウィンドウは、次のように定義されています。
Window_Command.new(横幅, コマンド配列, 桁数, 列数, 余白)
実際にウィンドウを表示するには、下記のように記述します。
いくつかサンプルを用意しました。
# 縦並びの選択項目 Window_Command.new(172, ["項目A", "項目B"]) # 第4引数まで指定すると、表示されていない項目はスクロール表示されます。 Window_Command.new(172, ["項目A", "項目B"], 1, 1) # 縦並びでは、第5引数は不要です。 # 2列の選択項目 Window_Command.new(172, ["項目A", "項目B"], 2) # 横並びの選択項目 cmd = ["項目A", "項目B", "項目C"] Window_Command.new(172, cmd, cmd.size, 1, 8) # 確認はしてないけど、横スクロールは無理じゃないかな?
普通のウィンドウとは違い、引数で座標の指定ができません。
ですので、表示位置を変更したい場合は次のように行います。
何もしなければ、(0, 0)で左上に表示されます。
# 表示位置の設定 win = Window_Command.new(172, ["項目A", "項目B"]) win.x = 100 # x座標 win.y = 100 # y座標
ウィンドウの縦幅は、項目の数で指定しますが、
次のようにすることで、サイズを設定することも可能です。
もちろん、表示されていない項目はスクロールで表示されます。
# 縦幅を直接指定(行単位ではなく、px単位で指定) win = Window_Command.new(172, ["項目A", "項目B", "項目C"]) win.height = 56 # 縦幅
◆ 今回のポイント
・ 表示しきれない項目は、スクロールで表示される。
・ 列数を自動判定にすると、項目が多いと画面外に出てしまう。
・ ウィンドウの位置は、アクセスメソッド(アクセサ) x と y を使用して変更する。
・ ウィンドウの縦幅は、アクセスメソッド height を使用してpx単位で設定できる。
・ 表示しきれない項目は、スクロールで表示される。
・ 列数を自動判定にすると、項目が多いと画面外に出てしまう。
・ ウィンドウの位置は、アクセスメソッド(アクセサ) x と y を使用して変更する。
・ ウィンドウの縦幅は、アクセスメソッド height を使用してpx単位で設定できる。
2.項目処理の定義
アクターの選択くらいなら、イベントコマンドのスクリプトだけでもできちゃうよ。
さて、コマンドウィンドウを扱うにはシーンクラスが必要です。
次のスクリプトは、コマンドウィンドウを表示するだけのシーンクラスです。
イベントコマンドに$scene = Scene_Command.newと記述して実行してみてください。
新しいことは何もしてないので大丈夫かな?
配列の生成処理だけ説明しときます。
さらに、ブロックの評価結果で要素の初期値を指定できます。
では、項目の処理を定義していきたいと思います。
アクター名を表示するウィンドウを作成して、選択したアクターを表示させたいと思います。
8行目で、アクター名を表示するウィンドウを作成して表示しています。
項目の選択処理は、前回の選択ウィンドウと同じですね。
どの項目が選択されたかは、そのウィンドウのindexの値で判断します。
cmd = Array.new($game_party.members.size) cmd.fill { |i| $game_party.members[i].name } @win = Window_Command.new(172, cmd) @win.x = (544 - @win.width) / 2 @win.y = (416 - @win.height) / 2 loop do Graphics.update Input.update @win.update break if Input.trigger?(Input::C) end; p cmd[@win.index] + "を選択しました。" Input.update; @win.dispose
さて、コマンドウィンドウを扱うにはシーンクラスが必要です。
次のスクリプトは、コマンドウィンドウを表示するだけのシーンクラスです。
イベントコマンドに$scene = Scene_Command.newと記述して実行してみてください。
新しいことは何もしてないので大丈夫かな?
配列の生成処理だけ説明しときます。
cmd = Array.new(配列のサイズ) { |index|
index 番の要素に格納する値
}
p Array.new(4) {|i| i } # => [0, 1, 2, 3]
Array.new(4) で、[nil, nil, nil, nil] という配列ができます。さらに、ブロックの評価結果で要素の初期値を指定できます。
では、項目の処理を定義していきたいと思います。
アクター名を表示するウィンドウを作成して、選択したアクターを表示させたいと思います。
8行目で、アクター名を表示するウィンドウを作成して表示しています。
@text_window = Window_Base.new(72, 80, 400, 56)
項目の選択処理は、前回の選択ウィンドウと同じですね。
どの項目が選択されたかは、そのウィンドウのindexの値で判断します。
◆ 今回のポイント
・ 選択されたている項目は、そのウィンドウのindexの値で判断する。
・ 選択されたている項目は、そのウィンドウのindexの値で判断する。
3.項目の切り替え
ショップ画面や装備画面のように複数のウィンドウをカーソルが行き来するような
処理を作ってみたいと思います。
前回で作ったものに語尾を追加するというものをつくります。
13行目で変数名が重複していますが、コマンド名をウィンドウに渡した後なので問題ないです。
17行目は、ウィンドウのカーソルが表示されないようにマイナス値を代入しています。
Window_Selectable#update_cursor で、マイナス値ならカーソルを無効にする処理を行っています。
Window_Command の親子関係は次のようになっているので、以下3クラスのメソッドは全て使用できます。
Window_Command < Window_Selectable < Window_Base < Window
18行目では、カーソルの操作を行えないようにしています。
もし、カーソルが表示されている場合は、点滅しなくなると思います。
このメソッドでは、カーソルの操作について処理しています。
25行目で、アクティブなウィンドウ(現在操作している)で処理をわけています。
どちらの処理も「決定ボタン」と「キャンセルボタン」の処理を定義しています。
画像にも説明のせてるし大丈夫かな?
処理を作ってみたいと思います。
前回で作ったものに語尾を追加するというものをつくります。
13行目で変数名が重複していますが、コマンド名をウィンドウに渡した後なので問題ないです。
17行目は、ウィンドウのカーソルが表示されないようにマイナス値を代入しています。
Window_Selectable#update_cursor で、マイナス値ならカーソルを無効にする処理を行っています。
Window_Command の親子関係は次のようになっているので、以下3クラスのメソッドは全て使用できます。
Window_Command < Window_Selectable < Window_Base < Window
18行目では、カーソルの操作を行えないようにしています。
もし、カーソルが表示されている場合は、点滅しなくなると思います。
このメソッドでは、カーソルの操作について処理しています。
25行目で、アクティブなウィンドウ(現在操作している)で処理をわけています。
どちらの処理も「決定ボタン」と「キャンセルボタン」の処理を定義しています。
画像にも説明のせてるし大丈夫かな?
◆ 今回のポイント
・ 項目選択などの操作ができるウィンドウは、非アクティブにしておく。
・ 操作するウィンドウのみアクティブにし、処理はウィンドウの状態でわける。
・ 項目選択などの操作ができるウィンドウは、非アクティブにしておく。
・ 操作するウィンドウのみアクティブにし、処理はウィンドウの状態でわける。
4.アイコンの描画
アイコンを描画するには、Window_Command#draw_itemの処理を書き換えます。
変更前の処理は、次のようになっています。
アイコンを描画するには、Window_Base#draw_iconを使用します。
Window_Command は、Window_Base を継承しているので Window_Base のメソッドはすべて使用できます。
rectは、矩形を表すRectクラスです。詳しくは、ヘルプで検索してください。
Window_Base#draw_icon の使い方を知るには、draw_iconで全検索します。
セクションを右クリック「検索」を選択するか、 Ctrl + Shift + F を押してください。
検索結果に複数の項目が出ると思います。
この中から、Window_Baseのセクションで、なおかつdef draw_iconという項目を探します。
この def というのがメソッド定義ですので。
60,61行目では、アイコンを描画した分だけ描画位置をずらしています。
そのままだと、アイコンの上に文字が描画されてしまいますので。
xだけではなく、widthも調整しましょう。
変更前の処理は、次のようになっています。
アイコンを描画するには、Window_Base#draw_iconを使用します。
Window_Command は、Window_Base を継承しているので Window_Base のメソッドはすべて使用できます。
rectは、矩形を表すRectクラスです。詳しくは、ヘルプで検索してください。
Window_Base#draw_icon の使い方を知るには、draw_iconで全検索します。
セクションを右クリック「検索」を選択するか、 Ctrl + Shift + F を押してください。
検索結果に複数の項目が出ると思います。
この中から、Window_Baseのセクションで、なおかつdef draw_iconという項目を探します。
この def というのがメソッド定義ですので。
60,61行目では、アイコンを描画した分だけ描画位置をずらしています。
そのままだと、アイコンの上に文字が描画されてしまいますので。
xだけではなく、widthも調整しましょう。
◆ 今回のポイント
・ アイコンの描画には、draw_icon メソッドを使用する。
・ 描画位置を変更した場合は、描画領域がおかしくなっていないか確認する。
・ アイコンの描画には、draw_icon メソッドを使用する。
・ 描画位置を変更した場合は、描画領域がおかしくなっていないか確認する。
5.描画するアイコンを変更
このままでは、描画できるアイコンは1種類です。
今回は、このアイコンを指定できるようにしてみましょう。
では、変数を使用して変更してみます。
ここで用意する変数は、グローバル変数です。
$command_icon でも良いですが、なんだか綺麗じゃないです。
そこで、Game_Tempクラスを使用します。
説明によると、「セーブデータに含まれない、一時的なデータを扱うクラスです。」だそうです。
こちらを使用する方が、仕様に沿っていて美しい気がします。
ただ面倒だっただけです。initialize で初期化してもらって結構です。
その際には、エイリアスの処理を忘れずに。
んで、ローカル変数ではエラーが発生しますが、インスタンス変数にはnilが代入されています。
これを利用して、アイコンの描画処理を分岐させています。
もしも、0以上の数値でないなら、アイコンを描画せずに文字のみの描画となります。
もし、コマンドウィンドウを継承して新しくクラスを定義するなら、
このような面倒な方法を取る必要はありません。
競合のことを考えて普通は新しく作ると思いますが、
その場合は、引数を増やすという方法を取ります。
今回は、このアイコンを指定できるようにしてみましょう。
では、変数を使用して変更してみます。
ここで用意する変数は、グローバル変数です。
$command_icon でも良いですが、なんだか綺麗じゃないです。
そこで、Game_Tempクラスを使用します。
説明によると、「セーブデータに含まれない、一時的なデータを扱うクラスです。」だそうです。
こちらを使用する方が、仕様に沿っていて美しい気がします。
class Game_Temp #-------------------------------------------------------------------------- # ◎ 公開インスタンス変数 #-------------------------------------------------------------------------- attr_accessor :cmd_icon_index # コマンドに描画するアイコンの番号 endさて、Game_Temp ですが、変数を初期化していません。
ただ面倒だっただけです。initialize で初期化してもらって結構です。
その際には、エイリアスの処理を忘れずに。
んで、ローカル変数ではエラーが発生しますが、インスタンス変数にはnilが代入されています。
これを利用して、アイコンの描画処理を分岐させています。
# もし変数が0以上の数値ならば if $game_temp.cmd_icon_index >= 0 # アイコンを描画 draw_icon($game_temp.cmd_icon_index, rect.x, rect.y, enabled) # アイコン分描画位置をずらす rect.x += 26 rect.width -= 26 end$game_temp.cmd_icon_indexは、nilで初期化されています。
もしも、0以上の数値でないなら、アイコンを描画せずに文字のみの描画となります。
もし、コマンドウィンドウを継承して新しくクラスを定義するなら、
このような面倒な方法を取る必要はありません。
競合のことを考えて普通は新しく作ると思いますが、
その場合は、引数を増やすという方法を取ります。
6.各コマンドに描画
では、実際に既存のコマンドウィンドウに描画してみましょう。
今回描画するのは、タイトル、メニュー、戦闘コマンド+ゴールドウィンドウです。
えっと、今までの説明は無駄になっちゃいますけど、また別の方法で描画したいと思います。
いろいろやり方を知っておけば、臨機応変に対応できると思います。
んで、今回は項目名からアイコンを描画するかを判断したいと思います。
では、まずコマンドウィンドウの描画処理を変更しましょう。
項目名の先頭にに<番号>という記述があれば、アイコンを描画するようにします。
次の行で破壊的な変更を加えるためです。
もし、cloneなしだと元のデータが変更されてしまいます。
もし含まれていた場合は、その部分を空文字列に置換します。
つまり消すと言うことです。
含まれていなければ、nilが返りますので処理を実行せずに項目名を描画します。
それでは、項目名に番号を追加していきます。タイトルは、Scene_Titleですね。
startメソッドを見てみるとcreate_command_windowってあります。ビンゴ!って叫びましょう。
create_command_window をダブルクリックして単語選択を行い、そのまま Ctrl + F を押します。
キーワード欄に単語が入っちゃってますので、そのまま検索です。
知らなかった人は、頭に叩き込んでおきましょう。
1発ジャンプですね。ここのs1〜s3が項目名です。
メニューは、Scene_Menu。
ウィンドウのセクションからWindow_PartyCommandとWindow_ActorCommandを見つけて、変更しましょう。 Window_PartyCommand
最後にゴールドウィンドウにアイコンを追加して終わりです。
Window_Gold
今回描画するのは、タイトル、メニュー、戦闘コマンド+ゴールドウィンドウです。
えっと、今までの説明は無駄になっちゃいますけど、また別の方法で描画したいと思います。
いろいろやり方を知っておけば、臨機応変に対応できると思います。
んで、今回は項目名からアイコンを描画するかを判断したいと思います。
では、まずコマンドウィンドウの描画処理を変更しましょう。
項目名の先頭にに<番号>という記述があれば、アイコンを描画するようにします。
text = @commands[index].clone項目名をコピーしています。
次の行で破壊的な変更を加えるためです。
もし、cloneなしだと元のデータが変更されてしまいます。
if text.sub!(/^<(\d+)>/, "")項目名に<数字>が含まれているかを調べています。
もし含まれていた場合は、その部分を空文字列に置換します。
つまり消すと言うことです。
含まれていなければ、nilが返りますので処理を実行せずに項目名を描画します。
それでは、項目名に番号を追加していきます。タイトルは、Scene_Titleですね。
startメソッドを見てみるとcreate_command_windowってあります。ビンゴ!って叫びましょう。
create_command_window をダブルクリックして単語選択を行い、そのまま Ctrl + F を押します。
キーワード欄に単語が入っちゃってますので、そのまま検索です。
知らなかった人は、頭に叩き込んでおきましょう。
1発ジャンプですね。ここのs1〜s3が項目名です。
s1 = "<1>" + Vocab::new_game # ニューゲーム s2 = "<141>" + Vocab::continue # コンティニュー s3 = "<117>" + Vocab::shutdown # シャットダウン他の2つも同じように変更しましょう。
メニューは、Scene_Menu。
s1 = "<144>" + Vocab::item # アイテム s2 = "<128>" + Vocab::skill # スキル s3 = "<40>" + Vocab::equip # 装備 s4 = "<129>" + Vocab::status # ステータス s5 = "<159>" + Vocab::save # セーブ s6 = "<112>" + Vocab::game_end # ゲーム終了戦闘は、Scene_Battle。おや?無いですね。どうやら、Window_Commandは使っていない様子。
ウィンドウのセクションからWindow_PartyCommandとWindow_ActorCommandを見つけて、変更しましょう。 Window_PartyCommand
s1 = "<131>" + Vocab::fight # 戦う s2 = "<136>" + Vocab::escape # 逃げるWindow_ActorCommand
s1 = "<2>" + Vocab::attack # 攻撃 s2 = "<52>" + Vocab::skill # スキル s3 = "<128>" + Vocab::guard # 防御 s4 = "<144>" + Vocab::item # アイテム
最後にゴールドウィンドウにアイコンを追加して終わりです。
Window_Gold
def refresh self.contents.clear draw_icon(147, 0, 0) draw_currency_value($game_party.gold, 26, 0, 96) end