ちょっと気の利いたRPGばかりでなく、マップが重要なSRPGや不思議のダンジョン系ではフリーゲームでもミニマップの表示機能が充実しています。ウディタには<SQUARE>のコマンドもあるし、結構自作も簡単そう。
ですが、めちゃくちゃ処理が重いのです。
今回はその対処方法を考えてみました。
追記:より実践的な方法をコメント欄でご提示いただきました! 必見です(ありがとうございます!)
ミニマップの素直な作り方はめちゃくちゃ重い
ミニマップとはどんなものか。ウディタの名作だとこんな感じ。画面中央あたりに浮かんでいる四角の窓です。
(左:『片道勇者』 右:『ローグと崖の巨大迷宮』)
だいたいのマップの大きさと主人公の現在位置がわかれば良いのなら、やることは結構シンプルそうですね。
しかし、SRPGなどではマップの1マス1マスが「地形」というゲーム的に重要な意味を持つので、できればミニマップでは地形の差がわかるよう、色分けしておきたいところ。ジャンルに関係なく、色のついたミニマップの方がカッコいい気もしますね。マップだってがんばって作っているのですし。
普通に考えると、そうしたミニマップの作り方はこうです。
ユーザーデータベース(udb)で色指定リストを作り、RGB値も設定します(ウディタでは0-200範囲ですが、このあたりを参考に)。
そして、マップチップのタグ番号を使って対応する色の指定を振ります。udbの緑色が1なので、緑色のマップチップのタグ番号も1にするわけです(スクショは設定中の様子)。
次はミニマップ表示用のコモンイベント作成です。
二重の回数ループでマップの座標を1マスずつチェックし、対応する色の四角い画像(<SQUARE>)を並べていくのです。あとはマスを表示するたびに、次のマスの描画座標をズラすことを忘れずに。
主人公の座標を打つ場合は、先に主人公座標を拾って、チェック座標との一致をみて分岐を足しましょう(レイヤ2~3の装飾的な、ミニマップとしては無視してほしいチップの場合はタグ番号99にして、その場合は一段下のレイヤのタグを見るように分岐を足すのもよいでしょう)。
左の20×15サイズのサンプルマップで、上のコモンを呼び出すと、右画面のようなミニマップが表示されます。
しかし、これが実に高負荷。
実際はこういう具合に、マップの1マスを画像1個で表現しているので、見かけ以上に大変な負荷となっています。
20×15サイズのマップでも、ミニマップの表示に使うマス画像(ピクチャ)は実に300個。
普通にマップをつくればこの2~3倍はマス(使用ピクチャ)が増えてきます。30×30のマップでもう900個!
ウディタで1000枚近い画像(ピクチャ)を取り回すのは非常に重たく、もともと高負荷になりがちなSRPGやローグライクで使うとなればカクつくこと間違いなし。
なんとかしなければ!
※ちなみに『片道勇者』や『ローグと崖の巨大迷宮』はそのあたり問題なく動作しています。表示領域を狭める他、おそらく大きなシート画像1枚の上に、主要な地形・キャラのみのマークを描画するといった工夫があるのでしょう。
対策その1「マス伸ばし法」
上の画像はサンプルマップでしたが、普通に作ったマップであっても「木や水など、同じ種類(色)のチップは基本的に密集している」はずです。
ミニマップにしたとき、すべてのマス(四角)を隙間なく並べるなら、「隣接するマスが同じ色のとき、1つの四角ピクチャを引き延ばすことで一気に複数マスの表現をしてよい!」というのが、この「マス伸ばし法」の考え方。
前回のソースに必要な処理を足してみましょう。
今表示しようとしているマスの色が前のマスと同じ場合、新たなピクチャを作るのではなく、前のマスのピクチャの縦拡大率を+100%しています。
縦に上から下までマップを調べて横へズレている処理ですから、いちばん下について隣の列の先頭へ戻るときには拡大率や色の記憶は確実にリセットしてくださいね。
これで、「土」とか「日」の長い縦棒なんかは、ピクチャ1個だけで描画されるようになったはず。そして、「最後に使ったピクチャ番号」がわかるデバッグ文を足せば準備完了です。
さて、結果はどうなるでしょうか?
見かけはまったく同じですが、「マス伸ばし法」での使用ピクチャ数は84。前回の300個から216個削減、つまり72%オフに成功しました。
とはいえ、まだ安心できません。
マップが複雑なら、実際の削減率はもっともっと低くなるからです。
対策その2「ブルーシート法」
また別の方法がありそうです。
というか、上記の『片道勇者』等からの推測を適用しましょう。大きなシートを1枚だけ描画して、特別なマスのみピクチャを追加するのです。ブルーシートを最初にひいてしまえ、というわけです。
先ほどまでのサンプルマップですが、パッと見、一番多い色のマスは緑色ですね。
だったら、マップ全体のサイズに合わせた大きな緑色のシート(四角ピクチャ)を最初に置いてしまいましょう。その上に、「シートとは違う色のマスのピクチャだけ並べていく」のです。
この手法で使用されたピクチャは71個。
無対策時の300個から229個、つまり76%オフです。単純なマップほど効果の高い手法ですね。
注意点として、マップごとに「ここはどの色が一番多いか」をコモンで調べるのも大変ですから、新たなユーザーベースに項目を立てて、あらかじめmap1のシートは緑色、map2は青色……と登録したり、どこのマップでも高確率でそれなりに多いであろう緑色(草地)でシート色を固定する、といった工夫や割り切りが必要になって来ます。
必殺の合わせ技
上記の2つの方法は併用が可能です。
つまり、「今回描画する色が、前回描画した色と同じなら、前のマスを伸ばす」かつ「今回描画する色が、シートと同じ色なら描画しない」のです。
ブルーシート法の描画フラグ1分岐のなかで、マス伸ばし方のRGB比較を行う感じがよいかと思います。
さて、ドキドキワクワクの削減率チェックです。
結果はピクチャ33個!
シートで1個、赤青白部分で32個という内訳ですね。無対策の300個からは267個、89%オフとなりました。ほぼほぼ90%の軽量化です。
マップが複雑になってきても高い削減率が期待できますね。
実際には、1・2どちらかの実施のみで充分に実用的な軽量化と言えるでしょう。合わせ技は、こだわり抜きたい職人気質なアナタへのご提案となります。
低負荷でミニマップを実装したいなら「文字列ピクチャ」がオススメです。
地形情報を読み取り、\c[X]■を文字列操作で加算してそれを文字列ピクチャで表示すれば、1枚のピクチャでミニマップを表現できます。(■と■の間に生じる隙間は\-[X]や\space[X]等のコマンドで処理)
片道勇者では恐らく、ミニマップ用のアイコンを用意して、\c[X]■の部分を\i[X]で表現することで、もう少しリッチなミニマップを実装していると思われます。
おお、なるほど・・・!
おっしゃるやり方が決定版ミニマップですね!ありがとうございます!