『愛とはあなたを破壊する魔法』制作記録十三

2023年10月7日

目次
  1. 進捗
  2. メモリーとコンフィグについて
  3. コンフィグについて
  4. 独自イベントリスナについて
  5. 進捗状況について

進捗

ティラノスクリプト版のプログラミングを進めています。
タイトルイラストも清書しました。

メモリーとコンフィグについて

今回は主に、メモリー画面とコンフィグ画面を作りました。
メモリーは、章ごとに物語を読むことができる機能です(クリア後要素)。

今回メモリー画面とコンフィグ画面は、ksファイルではなくhtmlファイルで作成しました。

htmlで作成したメニュー機能をメニュー画面から開けるようにする方法を簡易的に解説します。
コンフィグについて解説しますが、メモリーでも流れは同じです。

まずTYRANO.kag.stat.sysviewにコンフィグ画面を登録します。
名前とファイルの場所を登録します。ここに登録することで、ティラノ内の機能(TYRANO.kag.html)を使って画面が表示できるようになります。

const plugin_src = "./data/others/plugin/old_cinema_theme/"
TYRANO.kag.stat.sysview["config"] = plugin_src + "html/config.html"

次にコンフィグ表示用の関数を作成します。
バックログ表示用のコードを参考にしつつ、セーブ画面表示時のフェードインも取り入れました。

TYRANO.kag.menu.displayConfig = function() {
    let that = this;
    that.kag.unfocus();
    this.kag.setSkip(false);
    let j_save = $("<div></div>");

    this.kag.html(
        "config",
        {
            novel: $.novel,
        },
        function (html_str) {
            //実際に表示するHTMLです
            var j_menu = $(html_str);
            
            //ここで一旦コンフィグ画面を非表示にします。こうすることでフェードイン表示が可能になります。
            j_menu.hide();

            //メニューを表示するレイヤーを取得します。
            var layer_menu = that.kag.layer.getMenuLayer();
            
            //取得したレイヤーにコンフィグ画面を追加します。
            layer_menu.append(j_menu);
            layer_menu.show();

            //メニューを閉じるボタン用の設定です。
            that.setMenuCloseEvent(layer_menu);
            that.setHoverEvent(layer_menu);

            // スマホのタッチ操作でスクロールできるようにするために touchmove の伝搬を切る
            // (document まで伝搬するとそこのリスナで e.preventDefault() が呼ばれるため)
            j_menu.find(".config_body").on("touchmove", (e) => {
                e.stopPropagation();
            });

            //フェードインで表示します。メニュー画面から表示した場合は、メニュー画面をフェードアウトで非表示させます。
            $.preloadImgCallback(
                layer_menu,
                function () {
                    j_menu.stop(true, true).fadeIn(300);
                    layer_menu.find(".block_menu").fadeOut(300);
                },
                that,
            );

        },
    );

}

最後にメニュー画面にコンフィグ画面を開く機能を追加します。

menu.html(メニュー画面のHTML)にコンフィグを開くボタンを追加します。

<div class="display_menu block_menu">

    <div class="container">

        <button class="menu_item menu_start" id="menu_start">
            START
        </button>
        
        <!--(省略)-->

        <!--コンフィグボタンのクラスにmenu_configを追加します。後に使います。-->

        <button class="menu_item menu_config" id="menu_config">
            CONFIG
        </button>
        
        <!--(省略)-->

    </div>

    <!--(省略)-->

</div>

TYRANO.kag.menu.showMenuにコンフィグを開く機能を追加します。

TYRANO.kag.menu.showMenu = function(call_back) {
    if (this.kag.layer.layer_event.css("display") == "none" && this.kag.stat.is_strong_stop != true) {
        return false;
    }

    //(省略)

    //ここが各メニュー機能画面を開くためのひとかたまりです。ここはロード画面の機能です。
    layer_menu
        .find(".menu_load")
        .click(function (e) {
            //連続クリック対策
            if (button_clicked == true) {
                return;
            }
            button_clicked = true;
            that.kag.makeUnfocusableAll(layer_menu);
            that.displayLoad();
            e.stopPropagation();
        })
        .focusable();

        //コンフィグを開く機能の記述です。
        //findにmenu.htmlのコンフィグボタンに追加したクラス.menu_configを指定しています。
        layer_menu
            .find(".menu_config")
            .click(function (e) {
                //連続クリック対策
                if (button_clicked == true) {
                    return;
                }
                button_clicked = true;
                that.kag.makeUnfocusableAll(layer_menu);
                that.displayConfig();
                e.stopPropagation();
            })
            .focusable();

        //(省略)

以上でコンフィグ画面の追加は完了です。

コンフィグについて

コンフィグ画面の動作を動画で撮影しました。

先述の通りコンフィグはksファイルではなくhtmlファイルで作成しました。
その際、htmlで作るコンフィグ特有の課題がいくつかありました。

コンフィグで変更した設定が保存されない

html内のjavascriptでシステム変数を変更すると、リスタート時(タイトルへ戻るや再起動など)に変更が保存されないということがありました。

解決策は「システム変数を変更した後にsaveSystemVariable()を実行する」です。

TYRANO.kag.variable.sf.hoge = "hoge"
TYRANO.kag.saveSystemVariable()

evalタグで変更したシステム変数はリスタート時も保持されたため、evalタグの記述を確認しました。
その中にsaveSystemVariable()という記述があったため、コンフィグ内でも使用しています(内部的にはローカルストレージ、平たく言うとセーブデータを更新している関数です)。

またbgmoptタグの記述の中に「システム変数の変更とセーブ(sfのデータは[eval]実行時点でセーブされる)」というコメントもありました。
システム変数を外部javascriptで変更した場合は、saveSystemVariable()も同時に実行した方がよさそうです。

メッセージテキストを表示できない

ノベルゲームのコンフィグには、テキスト設定の確認用に、テストメッセージが表示されることがあります。
ティラノスクリプトのデフォルトテーマにもあります。

ティラノスクリプトのコンフィグは通常ksファイルで作ります。そのためテストメッセージはティラノスクリプトのメッセージ機能で表示できます。
しかし今回はhtmlファイルで作るため、メッセージ機能を使用できません。

解決策は「コンフィグ用のメッセージ表示機能を作る」です。

ティラノスクリプト本体のメッセージ表示機能を参考にして、「任意のHTML要素にメッセージ風のテキスト表示を行う機能」を作りました。
詳細なコードは以下のリンクからご確認ください。

github
tyrano_freetext

禁則処理やアニメーション機能など高度な機能の無いシンプルな構成ですが、今回のコンフィグ画面なら十分だと思います。

実際には以下の様な関数で使用しました。

function show_test_message() {
    const text = "テスト文章です。文字表示速度、オート速度、既読文章の色変更の設定を反映した文章がここに表示されます。"

    //一度前回表示分のメッセージを消去する。
    TYRANO.kag.freetext.clear_message("#freetext")

    //テキスト表示
    TYRANO.kag.freetext.show_message(text, "#freetext")

    //コンフィグモード終了時に停止
    if ($(".config_body").length === 0) {
        return
    }

    //テキスト表示が終了したらオートモードの速度で次へ

    let auto_speed = TYRANO.kag.config.autoSpeed
    let cnt_text = text.length

    auto_speed = parseInt(auto_speed) + parseInt(TYRANO.kag.config.chSpeed) * cnt_text;

    //テキスト表示を再帰的に繰り返す
    $.setTimeout(() => {
        show_test_message()
    }, auto_speed);
}

コンフィグ内でタグを使用するとゲームが進んでしまう

コンフィグ内でタグを使用するとゲームが進行してしまう課題がありました。
愛とはあなたを破壊する魔法の各メニュー画面は透けているため、コンフィグ操作時ゲームが動いているのがすぐわかります。

解決策は「既存タグからnextOrder()を削除したタグを作る」です。

基本的にjavascript内でティラノスクリプトのタグを使用すると、まずnextOrder()問題に直面します。
例えばループ内でタグを使用すると、nextOrder()(次のタグに進む処理)が大量に積もり、その分ゲームが勝手に進行してしまう現象が発生します。

javascript内でタグを使用した際ゲームが勝手に進行してしまう場合は、既存タグからnextOrder()を削除したタグを使うのが有効です。
本来のタグに上書きしてしまうとシナリオ内での使用に不具合が生じるため、新しいタグとして作成するのがよいと思います。

正直に言うとこの解決策はあまりよくないと思っています。javascript内で使用したいタグがある場合、その分新しいタグを作らなければならないからです。
他にも解決策は模索したのですが(TYRANO.kag.stronglyStop()を使用するなど)、あまり上手くいきませんでした。
もっと洗練された方法があればそちらを使用したいと考えています。

独自イベントリスナについて

選択肢を表示したタイミングを取得する方法の内、今作に適する方法が無かったため、独自のイベントリスナを追加することで解決しました。

選択肢表示タイミングを取得する方法には現状、tag-glink(に代表される各種ボタンのイベントリスナ)があります。愛とはあなたを破壊する魔法では選択肢にglinkを使用しています。
ただglinkボタンはゲーム内選択肢以外にも使用する可能性があったこと、独自イベントリスナに興味があったことから、今回は独自イベントリスナを使用しました。

独自イベントリスナを使う方法は簡単で、TYRANO.kag.trigger()の引数に独自のイベントリスナ名を指定するだけです。
通常のイベントリスナと同じようにコールバック関数を指定できます。

コードの例です。

[macro name="oct_mc_select_glink" ]

    ;選択肢を表示するマクロ

    [iscript]

        //イベントリスナはティラノスクリプト上でも使用可能
        TYRANO.kag.trigger("oct-show-select")

    [endscript]
    
    [glink color="oct_glink1" target="&mp.target" text="&mp.text"]

[endmacro]
//通常のイベントリスナ同様コールバック関数を指定できます。
TYRANO.kag.on("oct-show-select", oct_stop_skip)

function oct_stop_skip(){
    //(省略)
}

イベントリスナ名は、今後ティラノスクリプト本体で新しいイベントリスナが追加される可能性を考えて、被りにくい名称にしました。

進捗状況について

システム面(メニュー機能や立ち絵表示など)が完成したので、後はデバッグ作業とスチル作業だけです。
ここからが長いような気もしますが、引き続きがんばります。