ティラノスクリプト備忘録

個別のページを作るのが面倒で放置となった直接魔改造のものとかがあるので、ここにだらーっと書いていきますが、古すぎてどうかという感じです。使用しているティラノスクリプトはgithubの4.55eというわけで。古い! まあ備忘録ですね。そのうち整理しないとなあ……。


animate.cssを利用してちょっとしたアニメをつける

最近のティラノではanimate.cssが使えるようになっているので、それを利用してちょっとしたアニメをつけてみます。使えるアニメはbgのmethodとかと同じものです。詳しくはanimate.cssで見られます。またanimate.cssのgithubを見ると何となく使い方が分かるかもしれません。知っておくと便利ですね。
ただ直接の付け替えなのでスキップ時とかセーブロードとかでアレかもしれません。使いすぎると危険かも。とりあえず基本nameをつけられるタグなら使えるはずですが、とりあえずimageタグにつけてみます。


[image layer="0" name="animated,infinite,bounce" top="0" left="0" width="100" height="100"  storage="nanka.png"]

こんな感じですね。クラスにanimatedをつけてanimate.cssのアニメさせたいアニメ名をつけると使えるようになるので、これでbounceアニメが延々と繰り返されるようになります。nameから選択できる回数は多分infiniteだけかな?infiniteをつけなければ一回だけなので、ティラノのname上ならanimated,bounceInとつければbounceInしてきます。fadeInならfadeInですね。

ただこれでOutさせる場合はおそらくjQueryとかでクラス名つけないと駄目かなあと思います。ただまあ付け替えるなら簡単ですね。割と何でも強引にできます。


[iscript]
$(".bounce").removeClass("infinite");
$(".bounce").addClass("bounceOut");
[endscript]
[l]
[freeimage layer="1"]

これでアウトされます。infiniteは最初につけてなければremoveしなくても大丈夫です。ただこれだと画像自体は消えないので、この後にfreeimageとかかける必要はあります。iscript上でアニメ終わりに削除してもいいのですが、コード書くのがめんどいのでfreeimageで楽をしました。コード書くならこういう感じです。


[iscript]
$(".bounce").removeClass("infinite");
$(".bounce").addClass("bounceOut").one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() {
    $(this).off("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend");
    $(this).remove();
});
[endscript]
[l]

画像を削除せずそのままにしておくと、また新たにbounseInとかで登場させることもできます。


[iscript]
$(".bounce").removeClass("infinite");
$(".bounce").addClass("bounceOut");
[endscript]
[l]
[iscript]
$(".bounce").removeClass("bounceOut");
$(".bounce").addClass("bounceIn");
[endscript]
[l]

と書いてはみたものの、実際動かしてないと何のこっちゃですね。これもそのうち何かしたいです。 画像にnameをつけている場合(キャラも含む)はその名前でやれば分かりやすいんじゃないかと思います。画像じゃなくてもnameつけてるものなら何でも使える気がします。

アニメ回数とか間隔とか開始時間遅らせるとかを個別に指定したい場合にはCSSで書く必要がありますが、簡単なやつなら上記のようにできます。

CSSから直接指定するなら以下のような感じです。これは私のですね。


.hearts{
animation: pulse 2s infinite;
-webkit-animation: pulse 2s infinite;
}

これくらいならクラス名にanimatedつけた方が簡単じゃないかと思います。実はこのページ書こうとするまでanimatedつければアニメできるということを知らなかったので、ずっとこういう風に書いてました。徒労! ただCSSで書くと間隔調整などしやすいので、他のアレもCSSで指定する時についでにやると便利かもしれません。


.loading {
font-size:30px;
font-family:'font_1';
position:absolute;
top:300px;
left:300px;
animation: flash 2s infinite;
-webkit-animation: flash 2s infinite;
color:aquamarine;
}

これはギャルゲ用のpreloadローディング画面でロード中という文字を表示させる時にやったやつです。ちなみにティラノ本体は-webkit-がないとアニメを認識しないので気を付けましょう。確かtyranoフォルダ内のanimate.cssでpuffとvanishがそれで効かなくなっているので、ティラノ本体でも使いたい場合には-webkit-を足すと有効になります。ただblurはfilterも含め処理に時間がかかるので、使わない方が軽いですね。


実行環境がPCかブラウザか判定する

tyranoフォルダ内のlibs.jsでは$.isNWJSというNode.js上で動作しているかどうかを判定する関数が定義されています。

$.isNWJS()

この結果がtrueならPC(Node.jsかnode-webkit?)、falseならブラウザ。実際にkag内で使われているのはkag.menu.jsのscreenFullとkag.tag_ext.jsの[web]タグですね。コード見てもぶっちゃけ何をやっているのかよく分からんのですが(無知)、とりあえずあんな感じにPCブラウザの判定は可能っぽいのでksファイル上で使ってみます。


[iscript]
if($.isNWJS()==true){
tf.pc=1;	//ここにPCの時に実行したい処理
}
else{
tf.pc=0;	//ここにブラウザの時に実行したい処理
}
[endscript]
[call storage="preload.ks" cond="tf.pc==0"]

こんな感じです。これでブラウザの時だけpreload用のksファイルが読み込ませることができます。多分。iscriptで直接callしてもいいかもしれませんが書き方がいまだによく分からないので大人しく変数に入れときます。なんかもっと省力的な方法ありませんかね。

またlibs.jsの$.userenvでPCかスマホかの判定もできるようです。これは$.userenv()でユーザー環境に応じてiphone,android,pcのどれかが返されます。ティラノではkag.key_mouseのスマホ用処理とかオーディオ関係とかをこれでスマホ判定してる感じなので、ksファイル上では[iscript][endscript]内で使えばPC・スマホに合わせた対応ができるかもしれません。


未読スキップを有効にする

魔改造とかではないのですがメモ。コンフィグで未読スキップを切り替えても、正常に動かないことがあります。その場合には三つの問題が考えられます。

一つ目は既読管理が有効になっていないケースです。未読スキップを有効にするためには既読管理を有効にする必要があります。それにはdataフォルダのsystemフォルダ内のConfig.tjs内の、「ラベル履歴」という項目をtrueとします。

;autoRecordLabel = true;

こうなっていれば既読判定が有効になります。デフォルトがfalseなので、trueにするのを忘れないようにします。

二つ目はシナリオ中にラベルが設置されていないことです。既読管理にはラベルを使います。ラベルを通過したかどうかで既読かどうかを判定するので、シナリオ内の冒頭以外にラベルがないと、その間では既読になるものもならないというわけです。targetのみでjumpする時にはラベルを置きますが、他の部分でも適当な間隔(五行ごととか十行ごととか)で適当なラベル(1とか2でもOK)を置いていくことで、狭い範囲での既読スキップが可能になります。ラベルは同じksファイル内で同じものを使うとエラーを出されますが、違うksファイルで使うのは大丈夫です。変数で保存されるのでラベル名も特にこだわらなくてもOKです。ただ長いとデータ量も多くなるかも。

三つ目は、ティラノスクリプト自体のバグです。ver4.54aより前のティラノスクリプトには未読スキップ切り替えにちょっとバグがあり、公式コンフィグで切り替えても上手くいかないという場合がありました。そのため一つ目と二つ目のことをやっていても既読スキップが上手くいかない場合には、4.54a以上のティラノスクリプトを使うことで問題が解消されると思われます。ティラノビルダーも1.6台を使っている場合には、最新バージョンに更新するのがオススメです。

未読スキップと書いていますが、未読スキップの反対(?)が既読スキップなので、既読スキップの話ですね。未読スキップがOFFで既読スキップONです。


テストプレイ中にシナリオキャッシュを無効にする

ver4.55からシナリオのキャッシュが有効となって、ブラウザ版をそのまま公開してもサクサクプレイが可能になってヒャッホーなのですが、ティラノライダーでのテストプレイ中はキャッシュが有効だと再起動なしでのクイックセーブロード無双ができないので、JSでキャッシュを無効にします。kag.jsをいじります。

ただfirst.ksから読み込んだマクロを変更すると、セーブデータとの行数が変わるのかバグることがあるので、マクロはmake.ksからも呼び出した方がよさそうです。

//シナリオファイルの読み込み
loadScenario:function(file_name,call_back){
var that = this;
this.stat.is_strong_stop = true;
this.stat.current_scenario = file_name;
var file_url = "";
if($.isHTTP(file_name)){
    file_url = file_name;
}else{
    file_url = "./data/scenario/"+file_name;
}

//キャッシュ確認・公開時のみ有効とする
/*if(that.cache_scenraio[file_url]){

    if(call_back){
    var result_obj = that.cache_scenraio[file_url];
    var tag_obj = result_obj.array_s;
    var map_label = result_obj.map_label;
    that.stat.map_label = map_label;
    that.stat.is_strong_stop = false;
    call_back(tag_obj);

    }

}else{
    */
    $.loadText(file_url,function(text_str){
    var result_obj = that.parser.parseScenario(text_str);
    that.cache_scenraio[file_url] = result_obj;
    var tag_obj = result_obj.array_s;
    var map_label = result_obj.map_label;
    that.stat.map_label = map_label;
    that.stat.is_strong_stop = false;
    if(call_back){
        call_back(tag_obj);
    }
    });

    /*ここも忘れずに
}
*/
},

これでksファイルの修正が即座に反映されるようになります。セーブデータを読み込んでも更新されるので、クイックセーブからのクイックロード&クイックロード&クイックロード修正もできます。ただ公開時にウッカリこのままにしているとラグって大変なので、テストプレイ・デバッグが終わったら忘れずにコメントを外します。

と書いてから思いましたが、ライダーからの起動で判定した方が楽そうですね。まあいいか。


読点の後にウェイトを入れる

TGF2016MCの蔵野杖人さんのバード・ダイブで読点ごとにウェイト入るのいいなーと思ったので、kag.tag.jsをいじって読点の後にウェイトを入れてみました。単純に一文字ずつ文字を拾って表示する時に、「、」の場合はsetTimeoutです。とりあえず横書きのみ。

var pchar = function(pchar) {

var c = _message_str.substring(index, ++index);

//ルビ指定がされている場合
if (that.kag.stat.ruby_str != "") {
    c = "<ruby><rb>" + c + "</rb><rt>" + that.kag.stat.ruby_str + "</rt></ruby>";
    that.kag.stat.ruby_str = "";

}

current_str += c;

//スキップ中は1文字ずつ追加ということはしない
if(that.kag.stat.is_skip != true && that.kag.stat.is_nowait!=true && ch_speed >3){
    that.kag.appendMessage(jtext, current_str);
}

if (index <= _message_str.length) {

    that.kag.stat.is_adding_text = true;

    //再生途中にクリックされて、残りを一瞬で表示する
    if (that.kag.stat.is_click_text == true || that.kag.stat.is_skip == true || that.kag.stat.is_nowait == true) {
    setTimeout(function() {
        pchar(pchar)
    }, 0);
    //★句読点の時にウェイト入れます
    } else if(c == "、"){
    setTimeout(function() {
        pchar(pchar)
        //★200くらいでいいんじゃないかと適当に入れました
    }, 200);
    } else {
    setTimeout(function() {
        pchar(pchar)
    }, ch_speed);
    }

スキップ中や多重クリック進行時にはウェイトは無視されます。読点だけでなく句点にも入れたい場合はif(c == "、"||c == "。")とします。

ただこれグリフの表示も待つので、「。」にもウェイトを入れるとグリフ表示までちょっと時間がかかって微妙です。[l][p]タグが入ってる時以外にできればいいかもしれませんが、この部分ではもうタグ解析が終わってるので他の方法じゃないとダメでしょうかね。

これをシステム変数でtrueの時にのみ行うとかすると、プレイヤー側が任意で選べるようにもなります。でも需要あるんだろうか?


fix用のボタンタグを作る

fix_buttonというタグをkag.tag.jsの最後に入れて使ってます。roleが入ってたらfix_buttonというクラスを付与して、そのクラスにCSSでボタンのスタイルを入れる感じですね。

//指定した位置にグラフィックボタンを配置する
tyrano.plugin.kag.tag.fix_button = {

    pm : {
        graphic : "",
        font_color : "",
        storage : null,
        target : null,
        ext : "",
        name : "",
        x : "",
        y : "",
        width : "",
        height : "",
        fix : "true",
        savesnap : "false",
        folder : "image",
        exp : "",
        prevar : "",
        visible:"true",
        hint : "",
        clickse : "",
        enterse : "",
        leavese : "",
        clickimg : "",
        enterimg : "",
        face : "",

        auto_next:"yes",

        role : ""

    },

    //イメージ表示レイヤ。メッセージレイヤのように扱われますね。。
    //cmで抹消しよう
    start : function(pm) {

        var that = this;

        var target_layer = null;

        target_layer = this.kag.layer.getLayer("fix");

        if(pm.role==""){
        var j_button = $("<div class='glink_button'>" + pm.text + "</div>");
        }
        else{
        var j_button = $("<div class='fix_button'>" + pm.text + "</div>");
        }

        if(pm.font_color !=""){
            j_button.css("color",$.convertColor(pm.font_color));
        }


        j_button.css("position", "absolute");
        j_button.css("cursor", "pointer");
        j_button.css("z-index", 99999999);
        j_button.css("font-size", pm.size + "px");

        if (pm.width != "") {
            j_button.css("width", pm.width + "px");
        }

        if (pm.height != "") {
            j_button.css("height", pm.height + "px");
        }

        //graphic 背景画像を指定できます。
        if(pm.graphic !=""){
            //画像の読み込み
            j_button.removeClass("glink_button").addClass("button_graphic");
            var img_url = "./data/image/" + pm.graphic ;
            j_button.css("background-image","url("+img_url+")");
            j_button.css("background-repeat","no-repeat");
            j_button.css("background-position","center center");
            j_button.css("background-size","100% 100%");

        }else{
            j_button.addClass(pm.color);
        }