ツクールMZでのWindow_Selectableの使い方まとめ

ツクールMZで自作プラグイン等でアイテム一覧とかを作成したい場合は、 Window_Selectableクラスを使って実装するのがよい。

今回は、その方法をまとめていく。

Window_Selectableでの実装

まずは、コードを見たほうがわかりやすい。

class Window_MyList extends Window_Selectable {

    // 初期化。データをセットして描画・カーソル位置を設定
    initialize(rect) {
        super.initialize(rect);
        this._data = [
            { name: "アイテムA", value: 100 },
            { name: "アイテムB", value: 200 },
            { name: "アイテムC", value: 300 },
        ];
        this.refresh();
        this.select(0);
    }

    // リストの項目数を返す @override 必須メソッド
    maxItems() {
        return this._data ? this._data.length : 0;
    }

    // 指定インデックスの項目を描画@override 必須メソッド
    drawItem(index) {
        const item = this._data[index];
        if (item) {
            const rect = this.itemLineRect(index);
            this.drawText(item.name, rect.x, rect.y, rect.width);
        }
    }

    // 現在カーソルが当たっている項目を返す
    item() {
        return this._data[this.index()];
    }

    // データを差し替えて再描画 必須ではないが、作成しておくと便利
    setData(data) {
        this._data = data;
        this.refresh();
    }
}


class Scene_MyMenu extends Scene_MenuBase {

    // ウィンドウを生成してシーンに追加
    create() {
        super.create();
        const rect = new Rectangle(0, 0, 400, 300);
        this._listWindow = new Window_MyList(rect);
        this._listWindow.setHandler("ok",     this.onOk.bind(this));
        this._listWindow.setHandler("cancel", this.popScene.bind(this));
        this.addWindow(this._listWindow);
    }

    // 決定キー押下時の処理
    onOk() {
        const item = this._listWindow.item();
        console.log("選択:", item.name);
        this._listWindow.activate();
    }
}

ここではthis._dataを使っているが、プロパティ名は何でもよい。 (多くの場合は_dataとか_listが採用される。)

重要なのは、maxItemsdrawItemをoverrideすること。

maxItemsは例のような実装がほとんどだろう。

問題はdrawItemである。

drawItemの実装について

もう一度、drawItemを再掲しよう。

    // 指定インデックスの項目を描画@override 必須メソッド
    drawItem(index) {
        const item = this._data[index];
        if (item) {
            const rect = this.itemRect(index);
            this.drawText(item.name, rect.x, rect.y, rect.width);
        }
    }

drawItemはそれぞれの項目を描画するごとに呼ばれるメソッドである。 引数のindexは何番目に描画するかが入っている。

重要なのはitemRectだろう。 これは*この項目のRectangleを取得してくれるメソッド*となっている。

つまり、MZ側がその項目の描画範囲を勝手に計算してくれるのだ。

似たようなメソッドにitemRectWithPadding(index)がある。 これは名前の通りpaddingも考慮した描画範囲のReactangleを返してくれる。

それぞれの項目の描画範囲をコントロールしたい場合

自作プラグインの作成の時、それぞれの描画範囲をコントロールしたい時はあるだろう。

その時は、itemHeightをoverrideして変えるのがよい。

Window_Selectable.prototype.itemWidth = function() {
    return Math.floor(this.innerWidth / this.maxCols());
};

Window_Selectable.prototype.itemHeight = function() {
    return Window_Scrollable.prototype.itemHeight.call(this) + 8;
};

デフォルトのitemHeightのサイズは大体テキスト1行分のサイズになっている。 もし、適当な値に変更したい場合は以下のようにすればよい。

Window_Oreore.prototype.itemHeight = function() {
    return 300;
}

これで各項目の高さが300に設定される。

また、幅を変えたい場合は、itemWidthを変えるのではなく、maxColsの方を overrideするのが良いだろう。

デフォルトではmaxColsは 1 が設定されている。 これは各行に対して1列ずつ描画する設定になっている。

例えば、以下のように設定してあげると、各行に対して2列ずつ項目を描画してくれるようになる。

Window_Oreore.prototype.maxCols = function() {
    return 2;
}