さて、前回
https://qiita.com/havin_nothin/items/0a9dd33b29583e0fa1f1
からの続きです。
どうやって作ったかを説明します。
まず、ギミックタイルを使いました。ギミックタイルは、タイルをゲーム中に変化させる仕組みです。今回はオブジェクトが重なったら、変化する仕組みを使いました。
最初に画面全体を「壁」タイルで埋め尽くしておきます。ここに迷路の「道」に当たる部分だけに、オブジェクトを瞬間移動させます。すると、「壁」のなかに「道」を作ることができます。
迷路の情報をどこかに貯めておければ、迷路の「道」に対応する場所にオブジェクトを置くことで迷路が作成できます。
ただ、迷路データをどうやって保存しておくか、という問題があります。スクリプト内で作ったデータをスクリプトの外で使う方法がないからです。(後述参照)
ここでは、迷路の壁を1、道を0として、横1列を2進数と見立てて数値化し、行ごとに複数の変数に格納して解決しました。図で示すと以下のようになります。
逆に、変数の値を2進数に変換すれば、変数から迷路が復元されます。
迷路データを作成し、いったん複数の変数に保存。
その後、迷路データを復元して、オブジェクトを動かしています。
なぜ、このようなことをしているかということですが、これはアクツクMVの仕様のおかげです。
アクツクMVには、変数がありますが数値しか扱えません。配列も文字列もつかえません。
迷路のアルゴリズムを検索すると、かならず、「迷路を2次元配列で表現すると簡単……」といった説明から始まりますが、アクツクMVには2次元どころか1次元配列もありません。
もちろんJavascriptでは使えますから、スクリプト内部では問題はありません。しかし、スクリプトとアクツクMVとの間で配列データのやり取りができないのです(たぶん)。
ゲーム実行中に変数を増やすこともできません。
以前、オブジェクトを生成するときに、共通変数を介して、オブジェクトに番号をつける方法を紹介しました。( https://qiita.com/havin_nothin/items/d810ca6c2e6f1eb017b8 )
この方法で、配列的にオブジェクトを扱うことは可能です。が、アクツクMVはオブジェクトが数百個もあるとスピードの問題が発生します。つまり遅いのでゲームにならない可能性があります(試していませんがたぶん苦しい結果が予想されます)。
アクツクMVではタイルというものがあります。迷路を作るならタイルを使用すべきでしょう。しかし、タイルをゲーム中に書き込むことはできません。スクリプトを使ってもできませんでした。
さて、ほぼここで手詰まりになったのですが、調べてみると、「ギミックタイル」というものがあります。タイルをゲーム中に変化させる仕組みです。これを使えば、オブジェクトが触れたタイルを別のタイルに変えることが出来ます。
またスクリプトを使うと、どこに、どのタイルがあるかを調べることが出来ます。
//レイヤー1の(1,1)のタイル情報を知るスクリプト(結果はログに表示)
var scene = Agtk.scenes.get(Agtk.sceneInstances.getCurrent().sceneId);
var layer = scene.getLayerById(scene.getLayerIdByName("レイヤー1"));
Agtk.log(layer.getTileInfo(1,1).x); //=タイル素材のx座標
Agtk.log(layer.getTileInfo(1,1).y);
これで行けると思ったのですが、このギミックタイル、画像が変化しても、タイルとしてのIDが変わらないのです。つまりタイルが変わったかどうかがゲーム中にはわからないということです。ある場所が「壁」なのか「道」なのか判別つかないと迷路は作れません。
「壁」のギミックタイルを敷き詰めて、オブジェクトを動かせば、オブジェクトを置いた場所が道になることはできます。あとは、迷路データにしたがってオブジェクトを動かすことができればよいわけです。
しかし、迷路データを作成したスクリプトと同じスクリプトでオブジェクトを動かしても、ギミックタイルは反応してくれません。ギミックタイルを反応させるためには、オブジェクトを動かした後、いったんスクリプトを抜ける必要があるのです。
しかし、いったんスクリプトを抜けてしまうと、データが消えてしまいます。アクツクのどこかにデータを格納する必要があるのですが、アクツクの変数は数値しか扱えません。
さすがに無理だなあとおもったところで、2進数表現を思いつきました。
最初に説明したように、0と1で迷路を数値に変えれば、アクツクMVとスクリプトで迷路データをやり取りできるはずです。
ところが、これにも問題がありました。アクツクMVというかJavascriptの変数の最大値は2進数で51桁だったのです。つまり一つの変数で、格納できる迷路情報は51マスということになります。両端を1にしているので実質49マスです。
というわけで、苦肉の策として、迷路の横幅は最大49マスとし、
迷路の行数分変数を用意することにしました。
とはいえ、これで以下のようなアルゴリズムで迷路作成が可能となりました。
1。オブジェクトが触れると「道」になるギミックタイル「壁」で全画面を埋める。
2.スクリプトAで迷路データを作成し、変数たちへ格納。
3.スクリプトBで迷路データを復元、「道」の部分であるべきタイルの場所へオブジェクトを飛ばして、ギミックタイルを「壁」から「道」へ変化させる。
ギミックタイルとオブジェクトが重なる判定は、スクリプトではできないため(たぶん)、タイル1枚ずつスクリプトで調べて、いったんアクツクに戻っています。これが、迷路作成に時間がかかる原因でもあります。
(スクリプトが遅いのではなく、アクション1つに1フレームかかるというアクツクの仕様のため)
わかっていただけたでしょうか。
アクツクMVは、配列もなく、文字列変数もなく、タイルの書き込みもできないという、なにかを自動生成しようとすると極めて困難なツールです。ゲームが作りやすいツールだけに、この点は非常に残念です。ですが、一方で自由度が高いため工夫すれば何とかなるという側面もあります。
迷路の自動生成に挑戦して、アクツクMVの限界と可能性が両方垣間見れた気がします。(もっとうまい方法があるかもしれませんが)。
ちなみにアクツクMVのロードマップには、「ストリング変数」「ローグライク機能」というものがあるそうです。アップデートしたら、文字列変数と、マップ自動生成ができるようになるかもしれません。
では。