memo

ゲーム制作やデザインについての個人的メモ

【お知らせ】

おばけくんをひたすらクリックするだけのゲーム「おばけアタック!」を公開しました。
ティラノゲームフェス2017にも参加しています。1プレイ30秒程度なのでお気軽にプレイしてみてください!
プレイ&ダウンロードページ→http://novelgame.jp/games/show/508?fes=1

【ティラノスクリプト】セーブ時のバックログをロード時に再現する

自分が欲しかったので(以下略)

セーブデータをロードすると、バックログはロード前の内容のままで表示されるのですが、バックログの内容もセーブしてロードしたときに読み返せたら便利だなあ、と思って試してみました。
前回のプレイから時間があくと内容を忘れてることもあるからね…(自分だけ?)。

※本体部分を改造してるのでご利用は自己責任でお願いします

kag.menu.js

  doSave: function (num) {
    var array_save = this.getSaveData();
    var data = {};
    var that = this;
    /* 追加ここから */
    that.kag.stat.f.backlog = that.kag.variable.tf.system.backlog;
    /* 追加ここまで */
    if (this.snap == null) this.snapSave(this.kag.stat.current_save_str, function () {
      data = that.snap;
      data.save_date = $.getNowDate() + " " + $.getNowTime();
      array_save.data[num] = data;
      $.setStorage(that.kag.config.projectID + "_tyrano_data", array_save, that.kag.config.configSave)
    })
  },
  loadGameData: function (data, options) {
    var auto_next = "no";
    (中略)
    this.kag.clearTmpVariable();
    /* 追加ここから */
    this.kag.variable.tf.system.backlog = this.kag.stat.f.backlog;
    /* 追加ここまで */
    this.kag.ftag.nextOrderWithIndex(data.current_order_index, data.stat.current_scenario, true, insert, "yes")
  },

セーブ時に現在のバックログ(「tf.system.backlog」に配列として格納されている)をゲーム変数「f.backlog」に代入して、ロード時には逆に「f.backlog」を「tf.system.backlog」に代入しています。
クイックセーブやオートセーブにも対応させたい場合はdoSaveに追加した内容をsetQuickSaveやdoSetAutoSaveにも追加してください。

そもそもバックログ自体をゲーム変数にすればいい気もしますが、勝手に変更していいものか悩んだのでとりあえずこの方法で対応してみました。もっと良い方法があれば教えていただけると嬉しいです。

【ティラノスクリプト】演出スキップ用マクロ

スキップ中は背景変更とキャラクター操作の演出以外も飛ばしたい!という人(自分)向けのマクロです。

ダウンロード

skip_effect.ks(※Dropbox

使い方

①ダウンロードしたskip_effect.ksをscenarioフォルダに入れる
②first.ksでskip_effect.ksを読み込む

[call storage="skip_effect.ks"]

③使うときはタグ名の頭に「s_」をつける

;[wait]タグをスキップ可能にしたいとき
[s_wait time=3000]

演出をスキップできるタグ一覧

オーディオ関連

[playse][fadeinse]

レイヤ関連

[image][freeimage][free][ptext][trans][layermode][layermode_movie][free_layermode][mask][mask_off]

システム操作

[wait][quake]

アニメーション関連

[anim]

カメラ操作

[camera]
[reset_camera]

その他

[bgmovie]
[stop_bgmovie]

保留(未実装)
[mtext](timeを0にしただけでは演出スキップできない)
[kanim](一回だけのアニメかループアニメかによって処理が異なる)

【ティラノスクリプト】実行環境の判定方法

自分用メモです。

ティラノスクリプトを使っていて、プレイヤーのゲーム実行環境がブラウザ版なのかPC版なのか判定したいときが(自分は)あります。

自分のホームページで公開するならブラウザ向けとPC向けのゲームファイルをそれぞれ用意すれば良いのかもしれませんが、単純に容量が倍になってしまいます。
また、ノベルゲームコレクション等の投稿サイトはブラウザ版もPC版もひとつのゲームファイルから生成するみたいなのでこの手は使えません。

ということで、どちらかだけに適用したい内容があるときは実行環境を判定するコードを書いて条件分岐させるのが良さそうです。

☆コメント欄で情報をいただきました
ティラノスクリプトでは予めPC版かブラウザ版か判定するための関数が定義されているので、それを利用すると簡単に実行環境の判定と条件分岐ができます。

ここでは例として「PC版(node-webkitで動作している場合)のみ、右上の×(閉じるボタン)を押したときに本当に終了するかの確認ダイアログを出す」という内容のコードを書いてみます。

[iscript]
if ($.isNWJS()) {
	var win = require('nw.gui').Window.get();
	win.on("close",function() {
		$.confirm($.lang("exit_game"), function() {
			win.close(true);
		}, function() {
			that.kag.ftag.nextOrder();
		});
	});
}
[endscript]

同じゲームファイルでもブラウザ版ではif内のコードは実行されません。

***

以下は判定方法から書いたコードです。参考のために残しておきます。

// Node.js で動作しているか
var isNode = (typeof process !== "undefined" && typeof require !== "undefined");
// ブラウザ上(非Node.js)で動作しているか
var isBrowser = !isNode
// node-webkitで動作しているか
var isNodeWebkit;
try {
    isNodeWebkit = isNode ? (typeof require('nw.gui') !== "undefined") : false;
} catch(e) {
    isNodeWebkit = false;
}

コード引用元:javascript - JavaScript実行環境の判定方法について - スタック・オーバーフロー

これで条件分岐させるための準備ができました。
ここでは例として「PC版(node-webkitで動作している場合)のみ、右上の×(閉じるボタン)を押したときに本当に終了するかの確認ダイアログを出す」という内容のコードを書いてみます。

if (isNodeWebkit) {
	var win = require('nw.gui').Window.get();
	win.on("close",function() {
		$.confirm($.lang("exit_game"), function() {
			win.close(true);
		}, function() {
			that.kag.ftag.nextOrder();
		});
	});
}

同じゲームファイルでもブラウザ版ではif内のコードは実行されません。

注意点

KSファイルに書く場合は判定コードと条件分岐コートを同じ[iscript]内に書いてください。別の[iscript]に記載したい場合はティラノスクリプトの変数に代入すると使えるようになります。

[iscript]
// Node.js で動作しているか
var isNode = (typeof process !== "undefined" && typeof require !== "undefined");
// ブラウザ上(非Node.js)で動作しているか
var isBrowser = !isNode
// node-webkitで動作しているか
var isNodeWebkit;
try {
    isNodeWebkit = isNode ? (typeof require('nw.gui') !== "undefined") : false;
} catch(e) {
    isNodeWebkit = false;
}

sf.isNode = isNode;
sf.isBrowser = isBrowser ;
sf.isNodeWebkit = isNodeWebkit;
[endscript]

[iscript]
if (sf.isNodeWebkit) {
	var win = require('nw.gui').Window.get();
	win.on("close",function() {
		$.confirm($.lang("exit_game"), function() {
			win.close(true);
		}, function() {
			that.kag.ftag.nextOrder();
		});
	});
}
[endscript]

※自分の環境(Windows10/Chrome)でしか動作確認していないので、コードを使用される際は十分検討の上テストプレイを必ず行ってください。

【ティラノスクリプト】マウスカーソルが載ったときに何かする

ティラノスクリプトというかjQeryの話です。最近めっちゃ使うようになったのでメモがてらまとめておきます。
いろんな方法があると思いますが、ここではhoverメソッドを使ってマウスカーソルが載ったときの処理を実装してみます。他はなるべくタグを使って頑張ります。

f:id:onigirimgmg:20170605004103g:plain

DEMO(Chrome推奨)
hover_sample.ks(※Dropbox

サンプルに収録されてる素材しか使っていないのでコピペすれば動く……はず。
以下ざっくりとした解説です。

[button graphic="../fgimage/chara/akane/normal.png" target="*character_select" name="character_icon,akane_icon" x=500 y=50 width=150 height=150 fix=true]
[button graphic="../fgimage/chara/yamato/normal.png" target="*character_select" name="character_icon,yamato_icon" x=700 y=50 width=150 height=150 fix=true]

[anim name="character_icon" opacity=0 time=0]
[anim name="character_icon" opacity=255 time=500]

この部分でボタンを表示しています。ボタン画像は立ち絵をベースにCSS(後述)でトリミングやら背景色やら角丸やらを設定しました。なのでgraphicには立ち絵のパスを指定しています。
今回はボタンをクリックしても何も起きないようにしたかったので、fixをtrueにしてジャンプ先のラベル(*character_select)で[return]しています。
[anim]タグはボタンをふわっと表示させるためのものです。透明にした直後に500ミリ秒かけて不透明にしています。

[image layer=0 name="akane_select,back" storage="../image/config/c_btn.png" x=0 y=230 width=960 height=250]
[image layer=0 name="akane_select" storage="chara/akane/normal.png" x=50 y=40]
[ptext layer=0 name="akane_select,select_text" text="【あかね】" x=380 y=250 size=42 time=0]
[ptext layer=0 name="akane_select,select_text" text="なぜかゲーム制作に詳しい女の子。<br>楽して儲けようとする人には厳しい。<br>※個人の見解によるものです" x=400 y=320 size=32 time=0]
[anim name="akane_select" opacity=0 time=0]

ここの部分でマウスカーソルが載ったときに表示する要素を記述しています。
上から順番に、

  • 半透明の黒い帯(configの透明画像を再利用してCSSで背景色を指定してる)
  • キャラクター画像(立ち絵をそのまま表示)
  • キャラクター名(timeパラメータを指定しないと[anim]が効かないっぽい)
  • 説明文(同上)
  • 要素をいったん透明にするための[anim]

です。全部透明な状態で表示されています。

$(".akane_icon").hover(
	function(e) {
		$(".akane_select").css("opacity","1")
	},
	function(e) {
		$(".akane_select").css("opacity","0")
	}
);

この部分でマウスカーソルが載ったときの動きを設定しています。載ったときは要素を不透明にして、離れたときは要素を透明に戻しています。

参考:jQuery: マウスポインターが要素に出入りした時の処理を実装するには?(mouseover、mouseout、mouseenter、mouseleave、hover) - Build Insider


最後にCSSで色々見た目の設定をしました。以下のコードをtyrano.cssの最後とかにコピペしてください。

.character_icon {
	object-fit:none;
	border-radius:10px;
	box-shadow:5px 5px 5px rgba(0,0,0,0.5);
	-webkit-filter:grayscale(100%);
	filter:grayscale(100%);
}
.character_icon:hover {
	-webkit-filter:grayscale(0%);
	filter:grayscale(0%);
}
.akane_icon {
	object-position:50% 25%;
	background-color:#ffa500;
}
.yamato_icon {
	object-position:35% 25%;
	background-color:#1e90ff;
}

.select_text {
	cursor:default;
	text-shadow:2px 2px 5px black, -2px 2px 5px black, 2px -2px 5px black, -2px -2px 5px black;<feff>
}
.back {
	background:rgba(0,0,0,0.5);
}

別に画像を用意しなくて良いのでCSSは本当に便利だ。でもローカルとChromeでしか動作確認してないから使うときは気をつけてね。

動かないよ!まちがってるよ!等々ありましたらお気軽にご連絡ください~。

【ティラノスクリプト】クリック待ち画像を透過PNGにする+アニメーションさせる

クリック待ち画像(デフォルトでは文章の最後でぴょんぴょんしている水色のGIF画像)を透過PNGにしてCSSでアニメーションさせてみます。すこーしだけ本体部分を書き換えているので、バージョンアップに対応する際はご注意ください。

①画像を用意する

f:id:onigirimgmg:20170525010326p:plain
↑この画像を「nextpage.png」という名前で保存して、tyrano/images/system に入れます。「nextpage.gif」と同じフォルダです。
f:id:onigirimgmg:20170525180552p:plain:w300

②kag.tag.jsを書き換える

tyrano/plugins/kag/kag.tag.js を開いて、「nextpage.gif」を「nextpage.png」に書き換えます。テキストエディタの置換機能を使うと簡単にできます。
f:id:onigirimgmg:20170525181134p:plain:w300
Meryの場合:Ctrl+Rで「置換」を表示して、上のボックスに「nextpage.gif」を、下のボックスに「nextpage.png」を入力して「すべて置換」をクリックすると書き換えられます。

CSSを設定する

tyrano/tyrano.cssを開いてCSSを設定します。変更するのは170行目あたりにある「次へのクリックを促すアイコン」の下にある「.img_next」から始まる部分です。
f:id:onigirimgmg:20170525181714p:plain:w300
いくつかサンプルを載せておきます。CSSアニメーションについて詳しく知りたい場合は各自でググってください。

点滅する

f:id:onigirimgmg:20170525183257g:plain

.img_next{
	-webkit-animation: next 1s ease-in-out infinite alternate;
	animation: next 1s ease-in-out infinite alternate;
}
@-webkit-keyframes next {
	0% { opacity:1; }
	100% { opacity:0; }
}
@keyframes next {
	0% { opacity:1; }
	100% { opacity:0; }
}
上下に動く

f:id:onigirimgmg:20170525190923g:plain

.img_next{
	-webkit-animation: next 1s ease-in-out infinite alternate;
	animation: next 1s ease-in-out infinite alternate;
}
@-webkit-keyframes next {
	0% {-webkit-transform: translateY(0px);}
	100% {-webkit-transform: translateY(3px);}
}
@keyframes next {
	0% {transform: translateY(0px);}
	100% {transform: translateY(3px);}
}
Y軸で回転する

f:id:onigirimgmg:20170525184418g:plain

.img_next{
	-webkit-animation: next 1s ease-in-out infinite alternate;
	animation: next 1s ease-in-out infinite alternate;
}
@-webkit-keyframes next {
	0% { -webkit-transform:rotateY(0deg); }
	100% { -webkit-transform:rotateY(180deg); }
}
@keyframes next {
	0% { transform:rotateY(0deg); }
	100% { transform:rotateY(180deg); }
}
360°回転する

f:id:onigirimgmg:20170525190245g:plain
f:id:onigirimgmg:20170525190222p:plain ←この画像を使いました

.img_next{
	-webkit-animation: next 2s linear infinite;
	animation: next 2s linear infinite;
}
@-webkit-keyframes next {
	0% {-webkit-transform: rotate(0deg);}
	100% {-webkit-transform: rotate(360deg);}
}
@keyframes next {
	0% {transform: rotate(0deg);}
	100% {transform: rotate(360deg);}
}
拡大・縮小する

f:id:onigirimgmg:20170525185229g:plain
f:id:onigirimgmg:20170525185250p:plain ←この画像を使用しました

.img_next{
	-webkit-animation: next 1s ease-in-out infinite alternate;
	animation: next 1s ease-in-out infinite alternate;
}
@-webkit-keyframes next {
	0% { -webkit-transform:scale(1.0); }
	100% { -webkit-transform:scale(0.8); }
}
@keyframes next {
	0% { transform:scale(1.0); }
	100% { transform:scale(0.8); }
}

その他「こんなのできる?」というのがありましたらリクエストしてみてください。オリジナルのクリック待ち画像の制作も承ってます。お気軽にどーぞ。