目パチ・口パクプラグイン
前に同じような記事をQiitaにあげていたのですが、内容が古くなっていたので新しく書き直し 【使い方】
リンク先のページから「frameanimation.zip」をダウンロードして展開して、同梱のreadme.txtを読んでください。
既知のバグ・不具合(2019/12/31更新)
idパラメータの値が数値のみだと動作しません。a_123のように文字を含めれば動作します。
[fa_chara_show]と[fa_chara_part]を連続して記述した場合に表情パーツの変更がされない場合がある
(2019/1/31機能追加)[fa_chara_show]タグで初期表示パーツを指定できるようにしました。また、[fa_chara_show]タグと[fa_chara_part]タグを連続して記述する場合は、[fa_chara_show]タグのwait指定をtrueにしてください。
(2019/1/31修正)ロード後の[fa_chara_show]でセーブ時の差分パーツが反映されない
ここから先は、プラグインの中で何をしているのか知りたい方向けの記事です。
プラグインそのものの使い方は、readme.txtに書いているのでそちらをご覧ください。
プラグイン概要
ティラノスクリプトでのキャラクターの目パチ・口パクといったアニメーションを、CSSのスプライトアニメーションで実現しています。
スプライトアニメーションとは、ぱらぱら漫画を1枚の画像につなげたものを用意して、時間ごとに表示する領域を変えることでアニメーションしているように見せることです。
ティラノスクリプトのキャラクター表示では、ひとつの<div>内にパーツごとの画像である<img>タグが重ねて表示されています。
しかし、通常、スプライトアニメーションを行うときは、アニメーションしたい画像を背景画像に指定して、表示する領域をCSSで変更する処理が一般的です。
<img>タグにも背景画像は指定できますが、そのままだとsrc属性で表示されている画像とバッティングしてしまいます。
しかし、src属性を空にするとhttps://gyazo.com/1cc3d2ea8c163f684a79d148e927d57aこんな表示になってしまってよろしくありません。
ではどうするか。src属性に透明なpng画像を指定してあげましょう。
やっていること
ブランク画像の設定
マクロの定義
fa_animation … パーツID単位のアニメーション定義
fa_chara_show … [chara_show]タグ拡張
fa_chara_part … [chara_part]タグ拡張
1.ブランク画像の設定
1.first.ksファイルへ[plugin]タグ記述時に透明なpng画像を指定することができます。
2.指定されなかった場合はプラグインフォルダ下にある透明画像が指定されます。
3.1または2を、f.frame_animation.blank_imageに格納しています。
2.マクロの定義
fa_animation
code:init.ks
//アニメーション定義
var anime = ""
for(var i = 0; i < mp.anime.length; i++){
anime += mp.animei0 + "{ background-position: " + ((parseInt(mp.animei1 - 1)) * mp.w) * -1 + "px 0;} " }
mp.animation = mp.name + "_" + mp.part + "_" + mp.id
var normal = " @keyframes " + mp.animation + " { " + anime + " } "
var webkit = " @-webkit-keyframes " + mp.animation + " { " + anime + " } "
var mozila = " @-moz-keyframes " + mp.animation + " { " + anime + " } "
var opera = " @-o-keyframes " + mp.animation + " { " + anime + " } "
まず、ここまででcssアニメーションの定義をしています。
[fa_animation]タグでは、各キャラクターのパーツ単位でアニメーションを定義する必要があります。
とくにanime属性には、配列で指定したアニメーションの定義が格納されています。
[fa_animation]タグでは、この配列を文字列として連結して、cssアニメーション定義に変換しています。
code:init.ks
//アニメーション開始までのスタイル
var chara_part = "." + mp.name + " img." + mp.part + "{ "
chara_part += " object-fit: cover;"
chara_part += " object-position: 0% 0%; }"
//アニメーションをクラスに紐づけ
var chara = " ." + mp.name + " ." + mp.part + "." + mp.id + "{ "
chara += " -webkit-animation: " + mp.animation + " " + second + " steps(1) 0s infinite; "
chara += " -moz-animation: " + mp.animation + " " + second + " steps(1) 0s infinite; "
chara += " -o-animation: " + mp.animation + " " + second + " steps(1) 0s infinite; "
chara += " animation: " + mp.animation + " " + second + " steps(1) 0s infinite; } "
アニメーション開始までのスタイルというのは、このプラグインではCSSアニメーションを使用していますが、たとえアニメーション用に作った画像であっても、アニメーション用のクラスが付与されるまではただの背景画像になってしまいます。
ただの背景画像として表示されている間、デフォルトの表示ですと表示領域にあわせて画像自体が縮小されます。
アニメーション用画像は、通常のパーツを横に並べて作ったものですから、縦にギュッと押しつぶされたような表示になってしまいます。
それを防ぐために、object-fitおよびobject-positionを指定しています。
アニメーションをクラスに紐づけでは、[fa_animation]タグで定義したアニメーションを、アニメーションさせるキャラクターの各パーツと紐づけて実際にアニメーションさせる用意をしています。
code:init.ks
if($.find("#frame-animation").length === 0){
//CSSなし
$("<style id='frame-animation'></style>").appendTo("head")
}
var csslist = document.styleSheets
var max = 0
for(var i = 0; i < cssrules.length; i++){
if(cssrulesi.selectorText === "." + mp.name + " img." + mp.part){ //セレクタ:キャラ名 img.パーツ名
max = i
break;
}
}
//CSSセット
if(max === 0){
$("#frame-animation").html($("#frame-animation").html() + chara_part)
}
$("#frame-animation").html($("#frame-animation").html() + normal + webkit + mozila + opera + chara)
最後。
ここまででCSSをいろいろ定義してきましたが、実はまだゲーム本体には反映されていません。
ここでは最後にゲーム側にCSSを反映する処理を行っています。
fa_chara_show
code:init.ks
//パーツのデフォルトID取得
tf.blink_part = {}
tf.blink_storage = {}
Object.keys(part).forEach(function (p){
tf.blink_partp = partp.current_part_id tf.blink_storagep = "./data/fgimage/" + partp[tf.blink_partp].storage })
Object.keys(tf.blink_part).forEach(function (p) {
$("." + mp.name + " img." + p).addClass(tf.blink_partp) var selecter = "." + mp.name + " img." + p + "." + tf.blink_partp $(selecter + "." + tf.blink_partp).css("background", "url(" + tf.blink_storagep + ") 0 0 no-repeat") $(selecter).attr("src", f.frame_animation.blank_image)
})
delete tf.blink_part
[fa_chara_show]タグは、[chara_show]タグの拡張です。
やってることは、マクロ内での[chara_show]タグの前と後に大きく分かれますが、前半ではtyrano.plugin.kag.stat.charas[キャラ名]["_layer"]オブジェクト内を参照して、パーツごとに初期表示画像を取得しています。(初期表示っていうか、キャラクター表示時に表示される画像…このへんはこっち見たほうがわかりやすいかも) 後半では、実際にキャラクター表示後、アニメーションをさせるために<img>タグ内のsrc属性に透明画像のパスをセット、代わりに本来表示される画像をbackgroundに指定しています。
fa_chara_part
code:init.ks
//各パーツのID取得
tf.blink_part = {}
tf.blink_storage = {}
Object.keys(mp).forEach(function (p) {
if(p === "name" || p === "time" || p === "wait" || p === "allow_storage" || p === "*"){
// 何もしない
}else{
var part = tyrano.plugin.kag.stat.charasmp.name._layerp if(part[mpp] === undefined){ alert(p + "=" + mpp + "はありません") return false
}
tf.blink_storagep = "./data/fgimage/" + part[mpp].storage var selecter = "." + mp.name + " img." + p
if($.find(selecter).length > 0){
tyrano.plugin.kag.preload(old_storage, function () {
$(selecter).attr("src", old_storage)
$(selecter).css("background", "none")
//余計なクラスを削除
var _class = $(selecter).attr("class")
var classlist = _class.split(" ")
for(var i = 0; i < classlist.length; i++){
if(classlisti === p || classlisti === "part"){ //何もしない
}else{
$(selecter).removeClass(classlisti) }
}
})
}
}
})
Object.keys(tf.blink_part).forEach(function (p) {
$("." + mp.name + " img." + p).addClass(tf.blink_partp) var selecter = "." + mp.name + " img." + p + "." + tf.blink_partp $(selecter).css("background", "url(" + tf.blink_storagep + ") 0 0 no-repeat") $(selecter).attr("src", f.frame_animation.blank_image)
})
こちらも途中で[chara_part]タグを挟んで前半後半に分かれます。
前半では、パーツ名=idの形で指定されるパーツとIDの組み合わせを配列に格納しています。
同時に、現在current_part_idに指定されているパーツ画像(=cssでbackgroundに指定されている画像)を読み込んで、src属性にセットしています。
そして、backgroundにはnoneを指定。これで本来キャラクター差分機能で表示されている画像の状態に戻りました。
その後、現在指定されているアニメーション用のクラスを削除しています。
[chara_part *]を挟んで後半では、前半で用意したパーツとIDの配列を使って、新しく指定されたパーツ画像をbackgroundへ指定、srcには透明画像をセットしています。