見出し画像

ティラノスクリプトでゲームを作ろう!特定テーマ⑥マクロでスクリプト効率化

おはこんにちばんは! 富井サカナです!
今日も元気にゲームを作りましょう!

はじめに

みなさん! マクロは使っていますか!!
長編作者で全く使っていないという方がいてマジで驚きましたが、
マクロは制作効率を高めるためには絶対使った方が良いです。
珍しくこれは絶対だと断言できます!!(ある程度慣れてからの話)

ちなみに、偉そうなことを言いつつサブルーチンは使ったことないです。
使う必要性というか必然性を全く理解できていなくて。。。
『修学旅行』が無事に完成したら内容を理解する旅に出ます。


おススメな考え方

ちょっと極端なことを言うと、普通のタグを使うのは極力やめましょう!!
たとえば文章を表示する際にクリック待ち+改行としたい場合、
[l][r]と記載するのではなく、[lr]マクロ(名称自由)を作ってしまいましょう!
[p]も使うのはやめましょう! [pp]を作ってそれでいきましょう!

なぜかというと、細かくこだわりたくなった時にその方が楽だからです。
例えばクリック待ち+改行という場面において…………

・クリックしたら効果音を出るようにしたくなった
・クリックしたら何らかの画像が一瞬表示されるようにしたくなった
・改行後の文章が表示される前に50ミリ秒ほどウェイトがほしくなった

という場合、[l][r]と記載していたら全箇所に記載が必要になります。
検索+置換で一発だと思うかもしれませんが、
ksファイルを分けていたら地味に面倒ですし置換漏れもあるかも。
その点、[lr]マクロを作っていたら1か所だけ調整すれば全部直ります!

また、うっかり記述ミスの際に全ての箇所で一律不具合が出るおかげで
バグの発見が容易になり『バグ含み公開』の確率が大きく下がりますし、
ゲーム本編部分のksファイルの見た目がスッキリすることにより
シーンの内容を制作中に把握しやすくなったりします。

とはいえ、いきなりそんなことを言われても、
実際に1,2作くらい作らないとイメージが湧かないような気がします。
とはいえ、このタグのセット(演出など)は何度も出てきそうだな、
と思うようなものはマクロ化した方が良いと思います。

代表的なところだとシーンが変わるところなどでしょうか。
・メッセージ枠、登場キャラ、背景、音楽を消して
・音楽を流して、背景、登場キャラ、メッセージ枠を表示する。
この辺は作り手の数だけ理想的な間や演出がありそうですよね。


基本編~マクロの設定の仕方~

マクロの設定の仕方は公式にも書いてありますが簡単に説明します。

⓵『macro.ks』というファイルを作る(名前は違くても良い)
②[macro name="XXX"]と[endmacro]の間にスクリプトを記述する
 これが1つのマクロを作るための1セット
③複数のマクロを作成する([macro name="XXX"]~[endmacro]を繰り返す)
④『macro.ks』の最後に[eval exp="tf.first = 1"]と[return]を記述する
⑤ゲーム序盤の必ず通る部分に以下の記述を置く
 [call storage="macro.ks" cond="tf.first == undefined"]

④と⑤は読み込みを1回にすれば挙動が軽くなる?と入れていますが、
macroを通過しても別に読み込みに時間は掛からないかもしれません。
(まあだとしても特に不利益もないからおまじないということで)

以上です!
こうしておけば元々なかったタグが複数作られますので、
[XXX]とか[YYY]とか本文中に打った際に、
[macro name="XXX"]と[endmacro]で挟まれた部分の記述が発動します。

この間の記述に変数や場合分けを入れることで高度なマクロが作れますが、
まずは手始めに特定の「効果音+待ち時間+[cm]」みたいなのが吉かと。

実例がないとイメージしにくいと思いますので、
以下、行き当たりばったりで作ったかみかくしの夜のマクロの一部です。
今見ると我ながらセンスのないことをやっていますが。。

<『macro.ks』の中身(例)>
☟『first.ks』などに[[call storage="macro.ks"]を入れて読み込ませる

[macro name="bgm_stop"]
[fadeoutbgm time=%jikan|1000 ]
[endmacro]

[macro name="starthaikei"]
[image layer=base page=back storage=%gazou time=1]
[filter brightness=%akarusa|35 layer=base page=back]
[trans layer=base time=%jikan|3000]
[wt]
[endmacro]

[macro name="startbgm"]
[fadeinbgm storage=%ongaku time=%jikan|1]
[endmacro]

[macro name="end"]
[clearfix]
[wait time=1000]
[ptext page=back face=coin1 size=100 color=white name=title x=825 y=500 layer=2 text="終" wait=false]
[trans time=4000 layer=2 method=vanishIn]
[wt]
[endmacro]

[eval exp="tf.first = 1"]
[return] ☜一番最後に1つだけ置く


応用編~役立ったマクロたち~

ここから下は実際にマクロを作って良かったと思うものをご紹介します。
スクリプトそのものをドーンと公開します。(大したものではない)
内容は相当に簡単な方のはずなのでこれくらいは是非理解しましょう!

1作作るごとにこうすれば良かったと思う内容が増えていくので、
ゲ制の効率を高めていくには経験がかなり必要なんだと思います。

①暗転マクロ(エレベーター)

レトロゲーなのにスーッと画面が黒くなるのは嫌だなぁと思って、
カクカク黒くなるような演出を考えました。

[macro name="anten"]
[image visible=true left="40" top="60" width=%width|860 height=height%|380 storage="black30.png" layer=13 name=30]
[wait time=%time|500]
[image visible=true left="40" top="60" width=%width|860 height=height%|380 storage="black40.png" layer=13 name=40]
[wait time=%time|500]
[image visible=true left="40" top="60" width=%width|860 height=height%|380 storage="black50.png" layer=13 name=50]
[wait time=%time|500]
[image visible=true left="40" top="60" width=%width|860 height=height%|380 storage="black60.png" layer=13 name=60]
[wait time=%time|500]
[image visible=true left="40" top="60" width=%width|860 height=height%|380 storage="black70.png" layer=13 name=70]
[endmacro]

これはゲーム中何回か使っています。
「black30」とかの「30」に当たる数値は透過率です。
0.5秒ずつにちょっとずつ黒が濃くなる画像を出している感じです。
「name」で各画像を特定しているので、暗転解除時については
逆の順番でnameを特定して「free」をやればちょっとずつ明るくなります。
白暗転(明転?)も同じように準備しています。

「%」とか「|」とか見慣れない記号が出てきますが、
「%」は特定のマクロにパラメータを作ることができるもので、
「|」はパラメーターを省略した場合のデフォルト値の設定です。
上記の例だと[anten]だけでも機能するし、
[anten width=640 height=180 time=100]とかにすれば
記載部分は上書きされた条件でタグが発動することになります。


②みよちゃん話すマクロ(エレベーター)

みよちゃんが話す際のマクロです。
なんとここでみよちゃんの秘密が明らかに!

[macro name="miyo"]
[eval exp="tf.miyotalk = 1"]
[freeimage layer=0]
[freeimage layer=6]
[cm]
[wait time=100]
[image visible=true left="190" top="450" storage="messageB.png" layer=0]
;[font color="pink"]
[ptext size=30 layer=6 x="120" y="480" text="みよ"]
[playse storage="mojiB.ogg" buf=10]

;みよちゃんの状態によって口パクのアニメーションが変わる
[image storage="../fgimage/chara/miyo/miyo_01_normal.gif" layer=10 time=0 left=386 top=248 cond="f.miyo == 1"]
[image storage="../fgimage/chara/miyo/miyo_02_bikkuri.gif" layer=10 time=0 left=386 top=248 cond="f.miyo == 2"]
[image storage="../fgimage/chara/miyo/miyo_03_cold.gif" layer=10 time=0 left=386 top=248 cond="f.miyo == 3"]
[image storage="../fgimage/chara/miyo/miyo_04_mojimoji.gif" layer=10 time=0 left=386 top=248 cond="f.miyo == 4"]
[image storage="../fgimage/chara/miyo/miyo_05_keibetu.gif" layer=10 time=0 left=386 top=248 cond="f.miyo == 5"]
[image storage="../fgimage/chara/miyo/miyo_06_tere.gif" layer=10 time=0 left=386 top=248 cond="f.miyo == 6"]
[image storage="../fgimage/chara/miyo/miyo_07_cry.gif" layer=10 time=0 left=386 top=248 cond="f.miyo == 7"]
[image storage="../fgimage/chara/miyo/miyo_20_normal.gif" layer=10 time=0 left=386 top=248 cond="f.miyo == 20"]
[image storage="../fgimage/chara/miyo/miyo_21_tere.gif" layer=10 time=0 left=386 top=248 cond="f.miyo == 21"]
[freeimage layer=2]
[layopt layer=2 visible=true]
[endmacro]

これはもうゲーム中メチャクチャ使ってます。
流れとしてはおよそ以下のようになります。
・表示されている不要なテキストを消す
・みよちゃんの吹き出しと「みよ」という名前を表示
・話している際の効果音を流し始める
・みよちゃんのその時の気分によって異なる口パクgifを表示
・その前に既に表示している立ち絵を消す
こんな感じです。

口パクgifのlayerを10、立ち絵を2としていますが、
zindexの値を変えてそれぞれnameで特定すれば同一レイヤーで良いです。

謎のフラグ「tf.miyotalk」は次の項で説明します。

なお「;」は後で見返す時に直ぐに内容が思い出せるので、
めんどくさがらずにこまめに書いておいた方が良いです。
10年後にリメイクしたくなったりすることもあるかもしれませんし。
(発言者によって色変えようとしてたことを思い出しました)


③セリフ終了マクロ(エレベーター)

セリフが終わったタイミングでもマクロを発動させています。
テキストを打つ際に面倒なのでかちょうとみよちゃんで統一しました。
ちょっと長いので説明だけ見れば良いと思います。

[macro name="o"]
[stopse buf=10]
[resetfont]

;状態によって口パク終わりの画像が変わる
[if exp="tf.miyotalk == 1"]
[image storage="../fgimage/chara/miyo/miyo_01_normal.png" layer=2 time=0 left=386 top=248 cond="f.miyo == 1"]
[image storage="../fgimage/chara/miyo/miyo_02_bikkuri.png" layer=2 time=0 left=386 top=248 cond="f.miyo == 2"]
[image storage="../fgimage/chara/miyo/miyo_03_cold.gif" layer=2 time=0 left=386 top=248 cond="f.miyo == 3"]
[image storage="../fgimage/chara/miyo/miyo_04_mojimoji2.gif" layer=2 time=0 left=386 top=248 cond="f.miyo == 4"]
[image storage="../fgimage/chara/miyo/miyo_05_keibetu.png" layer=2 time=0 left=386 top=248 cond="f.miyo == 5"]
[image storage="../fgimage/chara/miyo/miyo_06_tere.png" layer=2 time=0 left=386 top=248 cond="f.miyo == 6"]
[image storage="../fgimage/chara/miyo/miyo_07_cry.png" layer=2 time=0 left=386 top=248 cond="f.miyo == 7"]
[image storage="../fgimage/chara/miyo/miyo_20_normal.png" layer=2 time=0 left=386 top=248 cond="f.miyo == 20"]
[image storage="../fgimage/chara/miyo/miyo_21_tere.png" layer=2 time=0 left=386 top=248 cond="f.miyo == 21"]
[freeimage layer=10]
[layopt layer=10 visible=true]
[eval exp="tf.miyotalk = 0"]

[elsif exp="tf.kachotalk == 1"]
[image storage="../fgimage/chara/kacho/kacho_01_normal.png" layer=7 time=0 left=146 top=248 cond="f.kacho == 1"]
[image storage="../fgimage/chara/kacho/kacho_02_bikkuri.png" layer=7 time=0 left=146 top=248 cond="f.kacho == 2"]
[image storage="../fgimage/chara/kacho/kacho_03_kizetu.png" layer=7 time=0 left=146 top=248 cond="f.kacho == 3"]
[image storage="../fgimage/chara/kacho/kacho_04_smile.png" layer=7 time=0 left=82 top=248 cond="f.kacho == 4"]
[image storage="../fgimage/chara/kacho/kacho_05_bashi.png" layer=7 time=0 left=82 top=248 cond="f.kacho == 5"]
[image storage="../fgimage/chara/kacho/kacho_06_tere.png" layer=7 time=0 left=146 top=248 cond="f.kacho == 6"]
[image storage="../fgimage/chara/kacho/kacho_07_ikemen.png" layer=7 time=0 left=146 top=248 cond="f.kacho == 7"]
[image storage="../fgimage/chara/kacho/kacho_20_ikemen.png" layer=7 time=0 left=146 top=248 cond="f.kacho == 20"]
[freeimage layer=11]
[layopt layer=11 visible=true]
[eval exp="tf.kachotalk = 0"]

[endif]

[p]
[playse storage="pi.ogg" buf=1]
[endmacro]

これは確実にゲーム内で一番使っているマクロです。
流れとしてはおよそ以下のようになります。
・話している際の効果音を消す
・フォントを元に戻す(結果不要となっているタグ)
・話しているのがみよちゃんかかちょうかでマクロ内分岐
・話者のその時の気分によって異なる静止立ち絵を表示
・口パクgifの表示を消す
・キャラが話しているよフラグをオフにする
・クリック待ちページ送りの[p]
・クリックしたら「ピ」音を流す
こんな感じです。
改行されてしまっているので見にくいかもしれませんが、
コピペして貼り付けたら結構簡単なのが分かると思います。

なお、こんな感じでその時の条件によって
発動する内容が変わるマクロは超強力です。
簡単なところから使っていくとかなりマクロを共通化できます。


④改ページマクロ(かみかくしの夜)

本作はかまいたちリスペクトゲーですので、
改ページは絶対に本家に寄せたいという強い気持ちを持っていました。
が、デフォルト設定を変えるのが面倒なため以下のような力業に出ました。

[macro name="x"]
[glyph fix=true left=1200 top=1100]
[image visible=true left="880" top="560" width=40 storage="close.png" layer=2 name=l]
[kanim keyframe=pikopiko count="infinite" time=500 name=l]
[p]
[stop_kanim name=l](※)
[eval exp="TYRANO.kag.tmp.num_anim=0"](※)

[freeimage layer=2]
[glyph fix=false]
[endmacro]

流れとしてはおよそ以下のようになります。
・デフォルトの改ページのアイコンの表示位置を画面外にうっちゃる
・改ページのマークをイイ感じの位置に[image]で表示
・そのマークを[kanim](別途設定)で永遠にピコピコさせる
・通常の改ページの[p]
・マークを消去
・[glyph fix=false]の意味合いはちょっと思い出せません
こんな感じです。

(※)
『かみかくし』では[wa]を一度も使っていなかったので
※の二列は記述しなくても特に問題はなかったのですが、
[kanim]を使用した場合はきちんと終了させておかないと、
その後のどこかで[wa]を使った瞬間にゲームがフリーズします。
どのような仕組みかは自分レベルだと正直理解できていないのですが、
きちんと終了させるには[stop_kanim]だけでは不十分なようで、
自分の場合は[eval exp="TYRANO.kag.tmp.num_anim=0"]
を入れることでそれ以降の[wa]でもフリーズしなくなりました。
『この瞬間全てのanimは終わりだぜ!』という魔法の呪文との認識です。
ご指摘&以前本件についてご助言を頂いたありんこさん、
魔法の呪文を授けて頂いた丹綿樫さん、誠にありがとうございますm(_ _)m

改ページマークの設定方法は調べたので知っていたのですが、
初心者には敷居の高い色んな箇所を修正する必要があったので、
画面外にうっちゃりという大技を繰り出して即解決しました!
これ結構良いアイデアだと思い付いた時はニヤニヤしましたw
[kanim]についてはいずれまとめて説明予定です。
簡単な上に表現の幅が広がるのでおススメです!ハマってます。


⑤おまけシナリオ不評マクロ(かみかくしの夜)

とにかく不評なおまけシナリオのカメラのシャッターマクロです。
すみません。初心者がいいマクロができた!と実装したものです。
大事なのはマクロを作ることでなくゲーム内でどう使うかですので、
反省のため、反面教師にするためにここでご紹介します。

[macro name="shutter"]
[getrand min="1" max="7"]
[image storage="white.jpg" width=960 height=640 time=10 layer=4]
[playse storage="61_camera1.ogg" cond="tf.rand == 1"]
[playse storage="62_camera2.ogg" cond="tf.rand == 2"]
[playse storage="63_camera3.ogg" cond="tf.rand == 3"]
[playse storage="64_camera4.ogg" cond="tf.rand == 4"]
[playse storage="65_camera5.ogg" cond="tf.rand == 5"]
[playse storage="66_camera6.ogg" cond="tf.rand == 6"]
[freeimage layer=4 time=10]
[endmacro]

流れとしてはおよそ以下のようになります。
・1から7の間のランダム数値を取得
 (getrandはマクロです。どう記述するかは以下に貼り付けます)
・短時間でに白画面を表示
・ランダムで数値した数値に応じて異なるシャッター音を鳴らす
・短時間で白画面を消去
以上です。

ランダムでシャッター音が流れるというのを気に入ってしまいましたが、
これはプレーヤーからはかなり明確に評判が悪かったです。
確かに特に終盤は連発が無茶苦茶しつこいですし、
ピカチュウ事件のような体調に異変を与えてしまう懸念もあるし、
この場(どの場?)を借りてお詫び申し上げます。(カシャーカシャー!)

・・・・・。

えっと、今見るとランダムで撮らないということにしたつもりが、
フラッシュだけは残ってる感じで作りが粗々ですし、
フラッシュのタイミングは割と一定なので音だけランダムにしても、
という感じでした。
今年中にはブラウザでも遊べるように修正予定ですので、
その際に大幅にフラッシュは削るようにするつもりです。

<『getrand』の中身>
※引用元『公式サイトの機能デモ「ランダム分岐」
[macro name="getrand"]
[iscript]
var max = mp.max || '10'
var min = mp.min || '1'
max = Number(max)
min = Number(min)
tf.rand = min + Math.floor(Math.random() * (max - min + 1))
if (mp['var']) eval(mp['var'] + ' = ' + tf.rand)
[endscript]
[endmacro]


おわりに

こんな風にマクロは効率化の面で非常に有用ですので、
登場回数が多いものは是非設定してみてはいかがでしょうか。

私の場合はちょっと力を入れ過ぎた結果、
現在制作中のゲームではむしろ効率が悪化している気がします。
あんまり極端に意識しすぎるのもかえって良くなさそうです。
数回しか出てこないようなものは個別に設定したほうが良いですし、
条件分岐を入れまくるよりは複数マクロを作った方が良いこともあります。
マクロは奥深い世界だなぁとしみじみ感じます。
上級者の方の(たぶん)スッキリなマクロに少しは近づきたいものです。

以上、富井サカナでした。
みなさまもよき制作ライフを。

↓↓ティラノスクリプトでゲームを作ろう!記事一覧はこちら↓↓

↓↓本記事で参照したゲームはこちらから遊べます↓↓


この記事が気に入ったらサポートをしてみませんか?