RPGツクール リスト表示


**RPGツクールでTodoリストを作ってみよう**
挑戦中

[RPGツクール 改めて開発環境構築](https://qiita.com/JQinglong/items/42b58c887b9e76e50534)からの続きです。


## SNSプラグインの使用方法

リスト表示を行うために、SNSプラグインを使用させていただくことを思い立ちました。

入手はこちらから。
[SNS風ゲーム素材ファイル](https://site.nicovideo.jp/rpgtkool/material/sns_like.html)

解凍したファイルをフォルダごと上書きするパターンでやろうと思いましたが、適用完了だけど使い方がわからない・・・ということで結局は、プラグインを利用して独自実装するパターンの方も参照します。
[SNSプラグイン説明資料](https://docs.google.com/presentation/d/1uJogZDEhNhlMZ40HZbYyUPYqLd_gC0R0laXGGb-ZyFI/edit#slide=id.g3ca5c78163_4_6)

基本的な考え方は、コモンイベントとして文章の表示をつなげた物を用意し、それをプラグインコマンドで実行すると、会話として文章が表示されるという物。

で、もろもろの設定方法もこちらで分かるが、いつものマップ上に表示されても見た目が整わない。

<img width="320" alt="スクリーンショット 2020-05-06 11.28.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77307/dc7e9efd-27fb-c2a3-976c-2cb4b95f1831.png">

本当は、[サンプルゲーム](https://game.nicovideo.jp/atsumaru/games/gm7276)のように表示されると良いと思うのですが。
プロジェクトファイルは配布終了してしまっているかな。それとも[ブロマガ](https://ch.nicovideo.jp/indies-game/blomaga)内での配布かな。
仕方ないので自分で頑張る。

まず、画面解像度の変更。有効にしているプラグインの中の、Community_Basicで、縦横の設定を逆にする。
各マップは、幅13、高さ17に変更。
SnsMapIdは初期値1になっているので、0：すべてにするか、表示させるところのMapIDに変更。

マップの自動イベントで、DisableSnsSwitchIdをOFFにしてトークを表示させて、プラグインコマンドStartAtsuTalkEvent 5を実行、トークスキップSkipModeSwitchIdをONで一気に表示させれば、リストが一覧でずらっと表示されるような動きになります。
トーク終了したというスイッチを設定して、終了スイッチONの場合に何もしないEVページを作っておく必要があります。
部屋を出るイベントを用意して、その際には、DisableSnsSwitchIdをONにすれば、戻った先のマップではリストが消えていると。
これが基本的なSNSプラグインの使い方かなと思います。

## SNSプラグインの仕組み

やっと本題だと思ったらまだでした。

やりたいことは、上にも書いたように、連続して文章の表示を送り込み、それをSNSプラグイン経由で表示させるということです。

基本部分は、[RPGツクールプラグイン入門](https://qiita.com/JQinglong/items/787c356efd73e7a9933a)でも書きました。
まずはこんな感じで書いてみます。

```js:JQTodo.js
//=============================================================================
// JQTodo.js  2020/5/5
// The MIT License (MIT)
//=============================================================================

/*:
 * @plugindesc テスト用プラグイン
 * @author JQ
 *
 * @help このプラグインにはプラグインコマンドはありません。
 * 
 * Plugin Command:
 *   JQTodo list             # 一覧表示
 */

(function(_global) {
    // ここにプラグイン処理を記載
    var N = 'JQTodo';

    // プラグインコマンド
    var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function(command, args) {
        _Game_Interpreter_pluginCommand.call(this, command, args);
        if (command == N) {

            // 仮置きリスト情報
            var listData = ["太郎\T\nやること１", "太郎\T\nやること2", "太郎\T\nやること3", "太郎\T\nやること4", "太郎\T\nやること5"]

            if (args[0] == "list") {

                for(let data of listData) {
                    $gameMessage.add(data)                    
                }

            }
        }
    };
})(this);
```

これをプラグインで有効にして、マップの適当なイベントで、プラグインコマンドJQTodo listを実行させます。
と、SNS風ではない普通の文章の表示がされました。
そこは簡単に言ってくれると思いましたが甘かった・・・。ここから時間がかかりました。

コモンスクリプトの実行の仕組みを調べてみると、コモンスクリプトは

```json:
{id: 5, list: Array(n), name: "コモンスクリプトに設定した名前", ・・・}
```

という形のオブジェクトになっています。
このlistというArrayの中に、コモンスクリプトとして指定した実行内容が入っています。
コモンスクリプトの実行内容として、文章の表示を登録した場合には、

```json:list
[{code: 101, indent: 0, parameters: Array(4)},
 {code: 401, indent: 0, parameters: Array(1)},
 {code: 101, indent: 0, parameters: Array(4)},
 {code: 401, indent: 0, parameters: Array(1)},
 {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}
```

という形で、101と401のコマンドの組み合わせが、文章の表示の数だけ入っています。
このコマンド401の中に表示する文章等が含まれています。

そして、プラグインでは、101のイベントを拾って、401の中のテキストをEntity_AtsuTalkに渡して、Entity_AtsuTalk.prototype.initializeの処理で必要な情報をセットして、Node_AtsuTalk.prototype.createの処理で、実際の整形を行う、という流れになっているようです（かな？？雰囲気で語ってます）。

※この辺の解析には、こちらを参照して、Debugger for Chromeを使用しています。
[「Visual Studio Code」+「Chrome」で「ツクールMV」のローカルでデバッグなテクニックの紹介](https://qiita.com/Sanshiro/items/084fb0971942e03db9a4)
めちゃくちゃ助かります。こうなってくると、ツクール本体は実行環境ですらなくなってきて、デザインツールになっています。

これに対して、コモンスクリプトの実行内容として、プラグインコマンドを指定した場合は、listのArrayが
code: 356 となっていて、parametersの中には、プラグインコマンドの名前が入っています。

すなわち、この場合コモンスクリプトの実行内容だけ見ても文章の表示コマンド101は登場せず、SNSプラグインではコマンド356はスルーしているため、普通に文章の表示が行われてしまうというわけです。

### 試行錯誤の過程（単なる試行錯誤の記録ですので、読み飛ばしていただければ・・・）

ということは、SNSプラグインを改造させていただく必要があると考えました。

Game_AtsuTalkInterpreter.prototype.command356
を追加します。
これのcommand101を参考にして、
var entity = new Entity_AtsuTalk(faceImageName, faceImageIndex, positionType, texts, timestamp);
を行うための処理を書きます。
例えばこんな感じ。

```js:
Game_AtsuTalkInterpreter.prototype.command356 = function() {
    // var args = this._params[0].split(" ");
    // var command = args.shift();
    // this.pluginCommand(command, args);
    // return true;
    if (!$gameMessage.isBusy()) {
        $gameSystem._isAtsutalkMessage = true;
        if (!$gameSwitches.value(_OggySns.SkipModeSwitchId)) {
            SoundManager.playAtsuTalkSound();
        }
        var faceImageName = '';
        var faceImageIndex = '';
        var positionType = 1;
        var texts = [];

        this._index++;
        texts.push('test1');
        this._index++;

        var timestamp = 0;
        if (Entity_AtsuTalk.needTimestamp(texts)) {
            timestamp = Date.now();
        }
        var entity = new Entity_AtsuTalk(faceImageName, faceImageIndex, positionType, texts, timestamp);
        SceneManager.currentScene()._atsuTalkService.addAtsuTalk(entity);
        this.setWaitMode('talk');
    }
    return false;
};
```

これでとりあえず、「test1」が表示されます。
しかし問題は、ここで取得できるのは、外部プラグインコマンドの情報（上記の例だと「JQTodo list」）のみということです。
すなわち、その中で、$gameMessage.addをしているという情報は分かりません。
やはり、自作プラグイン側で処理をする必要があります。

### TodoリストプラグインからSNSプラグインを利用する

おもむろに、下記のように処理を移してみます。上で追加した、Game_AtsuTalkInterpreter.prototype.command356はコメントアウトして良いです。
（要するに、SNSプラグインは修正しない元のまま）

```js:JQTodo.js
//=============================================================================
// JQTodo.js  2020/5/5
// The MIT License (MIT)
//=============================================================================

/*:
 * @plugindesc テスト用プラグイン
 * @author JQ
 *
 * @help このプラグインにはプラグインコマンドはありません。
 * 
 * Plugin Command:
 *   JQTodo list             # 一覧表示
 */

(function(_global) {
    // ここにプラグイン処理を記載
    var N = 'JQTodo';

    // プラグインコマンド
    var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
    Game_Interpreter.prototype.pluginCommand = function(command, args) {
        _Game_Interpreter_pluginCommand.call(this, command, args);
        if (command == N) {

            // 仮置きリスト情報
            var listData = [['太郎', 'やること１'], ['太郎', 'やること2'], ['太郎 \\T', 'やること3'], ['太郎 \\T', 'やること4', '2行目']]

            if (args[0] == "list") {

                for(let data of listData) {

                    var faceImageName = 'chkbox';
                    var faceImageIndex = '';
                    var positionType = 1;
                    var texts = [];
                    for(let str of data) {
                        if (texts.length > 0) {
                            // $gameMessage.add(str);// for atsumaru comment
                        }
                        texts.push(str);
                    }

                    var timestamp = Date.now();

                    var entity = new Entity_AtsuTalk(faceImageName, faceImageIndex, positionType, texts, timestamp);
                    SceneManager.currentScene()._atsuTalkService.addAtsuTalk(entity);
                    this.setWaitMode('talk');
                }

            }
        }
    };
})(this);
```

いけますね。listDataで設定している4行が表示されます。
チェックボックス画像はフリーのものをいただいてきて、名前をchkbox.pngにし、・・・/src/DevLab/img/facesに置いています。

<img width="320" alt="スクリーンショット 2020-05-06 13.51.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77307/97c0d297-77ef-973c-b461-9766a95fc71a.png">


Entity_AtsuTalkは外からも呼び出せるんですね。

ということで、とりあえず、一覧を表示させることができました。

## APIから情報取得して一覧表示

に行きたいのですが、いったんここまで。
GW中に終わらないな・・・