【プラグイン講座】選択肢のあるウィンドウを作る

本日は選択肢のあるウィンドウを使った簡単なゲームを作ってみましょう。
前回分のものをそのまま使うので、前回の分はまだ見てないよ~という方は前回分を参照してください。

選択肢のあるウィンドウを表示するクラス

選択肢のあるウィンドウを表示するクラスは
Window_Commandクラス
です。
このWindow_CommandクラスはWindow_Selectable.prototypeを継承して作られています

Window_Selectableクラスの説明を引用しておきますね。

The window class with cursor movement and scroll functions.

要はキー入力関係を受け付けるウィンドウですよーということです。
Window_Commandクラスはもっと機能が限定されていて(と言うか拡張されているのですが)

The superclass of windows for selecting a command.

と説明されています。
要は選択肢を表示するクラスですよーというわけですね。

では実際にWindow_Commandクラスを使ってみましょう。

//—————————————————————————–
// Window_CommandSampleクラスの定義
//—————————————————————————–
function Window_CommandSample() {
this.initialize.apply(this, arguments);
}

Window_CommandSample.prototype = Object.create(Window_Command.prototype);
Window_CommandSample.prototype.constructor = Window_CommandSample;

もうおなじみですね。
次はScene_SampleクラスにあるcreateSampleWindowメソッドの下に(しつこいですが、本当は場所はどこでもいい)以下のコードを追加してください。

Scene_Sample.prototype.createSampleCommandWindow = function() {
this.commandSampleWindow = new Window_CommandSample(300,100);
this.addWindow(this.commandSampleWindow);
};

X座標300、Y座標100に選択肢ウィンドウを作り、実際に画面に貼り付ける処理もおこなっています(ご覧のようにWindow_CommandクラスはWindow_Baseクラスと違い、サイズを指定する引数がありません。サイズを変えたい場合は別に指定する必要があります。……が、ここでは話がややこしくなるので元のサイズのままいきます)。

あとはScene_Sampleクラスのcreateメソッドの中でcreateSampleCommandWindowを呼ぶだけです。

Scene_Sample.prototype.create = function() {
Scene_Base.prototype.create.call(this);
//createSprite実行
this.createSprite();
//createFigureSprite実行
this.createFigureSprite();

//Window用のレイヤーを作成
this.createWindowLayer();
//実際のウィンドウを貼り付け
this.createSampleWindow();
//選択肢ウィンドウを貼り付け
this.createSampleCommandWindow();
};

こうですね。
では実行してみましょう。


▼マークのついている、へちゃむくれウィンドウが表示されましたか?
もしされたなら成功です。

選択肢を表示する

これだけではゴミのようなウィンドウが一つ貼り付けられただけで、何の役にも立ちません
むしろ邪魔と言っても過言ではないでしょう(まるでニートのようですね)。

そこで選択肢を表示させ、ウィンドウがきちんと動くようにしてみましょう。

ここで「わかった! 前回使ったdrawTextExメソッドを使うんだ!」と思った方、残念。
drawTextExメソッドは文字を表示するだけのメソッドなので選択肢にはなりません

答えはmakeCommandListメソッドです。
実際の使用はこんな感じ(Windo_CommandSampleクラスの近くにてきとーに置いてください。場所はどこでもいいです)。

Window_CommandSample.prototype.makeCommandList = function() {
this.addCommand(‘脱ニート’, ‘work’, true);
this.addCommand(‘現状維持’, ‘neet’, true);
};

一つずつ説明します。
まず、Window_CommandはinitializeされたタイミングでmakeCommandListメソッドを実行します(詳細はinitializeメソッドを見てください。要は初期化用のメソッドです)。
このmakeCommandListメソッドの中でコマンドを作っていくのがお作法のようです。

で、実際にコマンドリストを作っているメソッドがaddCommandメソッドです。
引数は最大4つ(name, symbol, enabled, ext)まで指定できますが、ぶっちゃけ最後のextが何を指定しているのか僕もわかりませんw
もう少しメソッドの説明コメントがついていたらいいんですけどねえ。
コアスクリプトを見ても、ほとんどのものが第三引数までしか指定されていませんし、僕も今のところ特に困っていないので第4引数は無視しましょう(詳しい解説は偉い人にお任せします)。

this.addCommand(‘脱ニート’, ‘work’, true);
このコードは
脱ニートという文字を表示して、選択肢へアクセスするにはworkという名前を利用して、選択可能状態で表示する
という意味です。

意味がわかりにくいと思うので、さらに詳しく説明します。
まず第一引数。
これはウィンドウに実際に表示する文字列です。
‘脱ニート’を’脱サラ’に変えればウィンドウに「脱サラ」と表示されます。

次に第二引数。
これはプログラム内でアクセスするための名前(シンボル)です。
‘work’という名前(シンボル)を介して、色々とコマンドの操作をするんですね。
ちなみにこのシンボルですが、アクセスする時に
symbol.contains(‘Volume’);
などとすることによって、Volumeという名前を含む全てのシンボルにアクセスする~とかもできちゃいます。
いくつかのグループによって挙動を変えたい場合、グループごとに「個別のシンボル名+同一のシンボル名」でシンボルを作ると便利ですね。
例えばseVolume,bgmVolumeなどです。

最後に第三引数です。
これは「選択可能かどうか」を示します
falseなら選択不可能(画面上では灰色になる)になって、trueなら選択可能になります。
タイトル画面で、何もセーブデータがないときにコンティニューが選べない状態を想像してもらえれば、falseのときがどのようなものかわかりやすいのではないでしょうか。

と、多少ややこしいですが、簡単な選択肢を表示するだけなら大して難しくありません。
今回は簡単な選択肢を表示させるだけなので大丈夫ですね。

さてmakeCommandListで選択肢を作ったところで、まずはゲームを起動してみましょう。
「脱ニート」と「現状維持」の二つの選択肢が表示されていたら成功です。
ですがどのボタンを押してもピコピコ音がなるばかりで、なんの反応も示しませんね。
それもそのはずで、ボタンが押されたときの処理を全く作っていないからです。
今度はそれを作っていきましょう。

選択肢の処理を作る

Scene_SampleクラスのcreateSampleCommandWindowメソッドを以下のように変えます。

Scene_Sample.prototype.createSampleCommandWindow = function() {
this.commandSampleWindow = new Window_CommandSample(300,100);

this.commandSampleWindow.setHandler(‘work’, this.onWork.bind(this));//脱ニートが選ばれた時
this.commandSampleWindow.setHandler(‘neet’, this.onNeet.bind(this));//現状維持が選ばれた時

this.addWindow(this.commandSampleWindow);
};

setHandlerと書かれている行が新たに追加されたコードですね。
このsetHandlerメソッドは第一引数にシンボルを指定します(addCommandするときに指定しましたね)。第二引数には実行したいメソッドを指定します。
.bind(this)ってなんやねんということですが、これまたJavaScriptの根幹に関わることなので、詳しくはJavaScriptの入門書を紐解いてください。
ここではただ「そうするのが定形」とだけ覚えておきましょう。

これだけではonWorkメソッドもonNeetメソッドもないのでエラーが出ます。
というわけで作ってあげましょう。

Scene_Sample.prototype.onWork = function() {
console.log(‘脱ニートが選ばれたよ’);
};

Scene_Sample.prototype.onNeet = function() {
console.log(‘現状維持が選ばれたよ’);
};

この二つのメソッドを作ったらゲームを実行して、選択肢を選んでみてください。
選択肢を選んだあとは固まってしまいますが、Developer ToolsのConsoleタブに、選択したコマンドによって文字列が変わって表示されるはずです。
固まったあとはゲームをリロードし、今度は別の選択肢を選んでください。
正しくコマンドが機能しているならOKです。

ゲームっぽくする

「コンソール画面じゃつまらんぜよ!」という方が大半だと思いますし、「プラグイン講座で学んだことをゲーム制作に活かしたいんじゃい!」というのが大勢だと思います。
というわけで、ちょっとだけゲームっぽくしてみましょう。

まずWindow_SampleクラスのdrawJobHuntingMessageメソッドを以下のように変更します。

Window_Sample.prototype.drawJobHuntingMessage = function(text) {
this.contents.clear();
this.drawTextEx(‘お仕事ください!\n’ + text + ‘\nお仕事ください!’,10,10);
//this.drawFace(‘Actor1’, 0, 0, 0, 100, 100);
};

追加したのは最初の行
this.contents.clear();
ですね。
これは「ウィンドウの中身を消しますよー」という程度の意味です。
ウィンドウの中身を消す理由は明快で、この後ウィンドウの中身を書き換える動作を追加させるからです。
中身を消しておかないと、文字が次々と追加されて、ウィンドウ内の文字が読めなくなってしまいます

次はScene_SampleクラスのonWorkメソッドとonNeetメソッドを以下のように変更してください。

Scene_Sample.prototype.onWork = function() {
// console.log(‘脱ニートが選ばれたよ’);
this.sampleWindow.drawJobHuntingMessage(‘僕はニートを脱します!’);
this.sprite.setColorTone([0,0,0,0]);
this.commandSampleWindow.activate();
};

Scene_Sample.prototype.onNeet = function() {
//console.log(‘現状維持が選ばれたよ’);
this.sampleWindow.drawJobHuntingMessage(‘僕は未来永劫ニートです!’);
this.sprite.setColorTone([0,0,0,255]);
this.commandSampleWindow.activate();
};

脱ニートが選ばれたら「僕はニートを脱します!」と表示して、現状維持が選ばれたら「僕は未来永劫ニートです!」と表示するのですね。
this.sprite.setColorTone([0,0,0,0]);
はちゃんと覚えていますか?
this.spriteはBlueSkyの画像のことで、setColorToneメソッドで色調を変化させるのでしたね。

this.commandSampleWindow.activate();
この一行は、選択肢を選んだあともウィンドウで選択肢を再び選べるようにするためのものです(さっきはいちいちリロードしなければいけませんでした)。

では、ゲームを実行してみてください。
選んだ選択肢に応じて画面が変わりましたか?
変わったなら、成功です。

動画も置いておきますね。

お疲れ様でした。
これでプラグイン講座は全て終了です。

一応完成したプラグインも置いておきますね。
SamplePlugin

注*なぜかファイル名が「SamplePlugin-1.js」となっているので「SamplePlugin.js」にリネームしてください。

フォローする

『【プラグイン講座】選択肢のあるウィンドウを作る』へのコメント

  1. 名前:匿名 投稿日:2017/05/27(土) 02:08:14 ID:014e13edf

    ツミオ様
    ツクールフォーラムに投稿していただいたステータス画面云々のプラグインですが
    商用アプリの「海老の揚げたてアチチノス」に利用させて頂いてもよろしいでしょうか
    使用料分配が必要でしたらメール下さい

    • 名前:ツミオ 投稿日:2017/05/27(土) 13:07:39 ID:0f76c3a73

      はじめまして。

      ツクール公式フォーラムに投稿している僕のプラグインは全てMITライセンスです。
      商用利用も自由ですので、もちろん商用アプリでの利用も可能です(グロ・エロなどでの使用も制限しておりません)。
      また、使用料を取ることも一切ありません。

      ただご覧の通り僕はニートですので、「わりとたくさん売れたから、500円くらいニートに寄付してやっか!」というのは大歓迎です。
      その500円で親にケーキでも買ってきます。

      ご不明な点がございましたら、お気軽にご質問ください(基本的に全て自由に使えると思ってもらって問題ないです)。

      • 名前:匿名 投稿日:2017/05/29(月) 17:02:09 ID:fa7460ae9

        寄付・・・・ですか
        ある程度検討させて頂きます、、、

        ところで 恐れ入りますが英語のステータスの能力表示などが長文すぎて端で切れてしまうのですが、ツクールMVが標準でやっているように長文はフォントサイズを詰めて表示することはできないのでしょうか?

        ムリならムリでこちらで代替案を考えますので、人生お詰みになっておられるということで、頑張りすぎないようお願いいたします

      • 名前:匿名 投稿日:2017/05/29(月) 17:10:46 ID:fa7460ae9

        コメントし忘れました
        遅くとも6/10にはツミオ様のステータス画面込みの
        海外向けにデモ版をリリースする予定です
        それ以上時間が掛かるようでしたら、プログラム的に修正可能でもあまり意味がありませんので、ムリに対応して頂かなくても問題ありません
        何かとすいません

        • 名前:ツミオ 投稿日:2017/05/29(月) 17:50:31 ID:748c1fc1d

          ステータスの表示だけ英語に対応させました。
          以下のコードを既存のWindow_Status_Expanded.prototype.createParameters_ESSメソッドと置き換えてください。

          Window_Status_Expanded.prototype.createParameters_ESS = function(x,y){
          if(this.isPageSelecting() === this._page_name.status){
          var padding = 10;
          var lineHeight = this.lineHeight() + padding;
          for (var i = 0; i < 6; i++) { var paramId = i + 2; var y2 = y + lineHeight * i; var text_widith; var font_size; if(TextManager.param(paramId).length > 6)
          {
          font_size = 20;
          text_widith = this.createBasicText_ESS(TextManager.param(paramId), x, y2,$fontColor_insideA_Ess,$fontColor_outsideA_Ess,font_size,’left’,-6);
          }else{
          font_size = 26;
          text_widith = this.createBasicText_ESS(TextManager.param(paramId), x, y2,$fontColor_insideA_Ess,$fontColor_outsideA_Ess,font_size,’left’,-6);
          }
          var margin = 10;
          this.createBasicText_ESS(this._actor.param(paramId).toString(),x – this.text_rightKerning + 130, y2,$fontColor_insideB_Ess,$fontColor_outsideB_Ess,font_size,’right’, -7);
          }
          }
          };

          海外向けとのことでしたので、英語での表示を前提としてカーニングしています(このコードは日本語での表記がおかしくなります)。
          カーニングの設定はcreateBasicText_ESSの最後の引数(今回の場合だと-6となっている場所)でおこなうようにしています。
          また、ステータスの文字が7文字以上の場合に自動でフォントサイズを縮めるようにもしました。

          あ、寄付云々はニートジョークですのでお気になさらず。

        • 名前:ツミオ 投稿日:2017/05/29(月) 17:58:17 ID:748c1fc1d

          このプラグインは基本的に日本語表記を前提としていますので、英語表記ですと全体的に文字と文字の間が空きすぎるかなと思います(僕の自作メソッドcreateBasicText_ESSの仕様上そうなります)。
          なので英語表記したい場合、createBasicText_ESSメソッド自体をいじるのもありかなあと思いました。
          具体的には
          Window_Status_Expanded.prototype.createBasicText_ESS
          の中括弧で囲まれている
          if(kerning === undefined)
          {
          kerning = 6;
          }

          if(kerning === undefined)
          {
          kerning = -6;
          }
          などと置き換えます。

          ただし既存のコードでカーニングを手動で設定している場合(数字の入っている文字列でしばしば手動で設定しています)、このカーニングは無視されます。
          つまり英語での表記がうまくいきません。

          そこで、どのような表示になるか僕も把握していませんが、
          if(kerning === undefined)
          の一行をコメントアウトすると全ての文字列が詰めて表示されます。
          よろしければお試しください。

          //if(kerning === undefined)
          //{
          kerning = -6;
          //}

          これでも可です。