Heliodor 2019/10/18 22:03

2Dで3D

2Dと3D…いや、ダイスの話じゃないですよ
(1D6とか3D6とかいう表記がありましたねえ。関係ないけどグーグルで 2D12 とかって打ち込むとダイスを振ってくれますよ)

今作っているゲームでは、これまで作っていたアクションゲームとは異なり奥行きの概念があります。
とは言っても基本的には横スクロールアクションなので、奥行き方向の移動はおまけ程度のものです。
よく勘違いされますが、たとえドット絵2Dのゲームであっても、奥行きの概念があるならばプログラム内部では3次元で計算しています。

そうでないと、

・ステージ奥方向に移動する(=キャラが画面の上方向に移動する)
・ステージ上空に向かって移動する(=キャラが画面の上方向に移動する)

この2つの移動を区別できないからです。
この動きを区別するためには、どうしても z という第3の座標を導入しないといけません。

縦横に加えて奥行きがあるということは、当然攻撃判定やダメージ判定も立体的で、地形も立体的なものとして扱わないといけないという事で、結局プログラム内部では3Dの計算をやることになります。

まあ本物の3Dゲームに比べればだいぶ楽だとは思いますけど。
キャラクターやオブジェクトは単なるビットマップなので四角いポリゴンにテクスチャをペタッと貼るだけで済みますし、基本的にはカメラは左右に動くだけで、奥行き方向にカメラが移動したりすることはありません。

内部の計算はそれで良いのですが、面倒なのはそれを表示する時です。
3Dモデルを作っているわけではありません。単なる平面の絵ですから、奥行き方向の情報はありません。薄っぺらです。

何が面倒かというと描画順序の決め方です。
どちらが手前に合ってどちらが奥にあるのか?これがすごく決めづらいんです。


ガチの3Dであれば、現実と同じように立体の形を持ったポリゴン(メッシュ)を作るので、その立体の情報をそのまま利用することができます。
Zバッファを使ってピクセルごとに手前か奥かの判断をすることもできますから、期待した通り綺麗に表示できます。

でも、背景も地形もキャラクターもすべて単なる平面の絵で作っている場合、奥行きに関する情報は全くありません。
奥行きがある物体があるように見えても、それは本当に奥行きがある3Dのモデルを表示しているわけではなく、板ポリゴンの薄っぺらい板に、いかにも「奥行きがあります」といった感じの絵を描いてみせているだけです。


というわけで、画面内に存在するキャラクターやオブジェクトをどのような順番で描画するかは、自分で決めなくてはなりません。
形に奥行き情報が無い以上、ビデオカードに任せることはできません。



こんな感じの箱があったとします。
ここにキャラクターを重ねたい。キャラクターは箱の上にも乗れるし、奥にも手前にも回り込めます。もしかしたら箱は高いところにあって、その下をキャラクターがくぐる事ができるかもしれません。

このとき、キャラクターと箱の描画順序はどうすれば良いでしょう?


とはいっても話は簡単で、キャラクターが【箱の上、奥、左側】にいるなら【キャラクター、箱】の順に、キャラクターが【箱の下、手前、右側】にいるなら【箱、キャラクター】の順で描画すればよさそうです。


このルールに従ってソートのための比較関数を作ってみましょう。
ソートするためには二つのオブジェクトを比較して、どちらが先になるかを判断する必要があります。

比較関数の内容は、こうです。
オブジェクトXとYを比較するとして、

・XがYよりも左にいるなら、Xを先に描画
・XがYよりも奥にいるなら、Xを先に描画
・XがYよりも下にいるなら、Xを先に描画
・それ以外の場合はYを先に描画

このルールで二つのオブジェクトを比較し、並び替えていけばよさそうです。

……ところがこれ、そう簡単にはいかないんです。
キャラクターも箱も、一つだけとは限らないからです。

図1


箱の左右にキャラAとBがいるとします。
ちなみにキャラBはAよりも奥側にいます(これは後で重要になってきます)

これ、単純に考えれば A<箱<Bの順で描画すればよいですね。


Aと箱の比較では、Aが箱の左にあるのでA<箱
箱とBの比較では、箱がBの左にあるので箱<B

となり、うまいぐあいにA<箱<Bとなりそうです。


図2

でも…この図の場合だとうまくいきません。

え?と思うでしょう
普通に考えれば、この図は B<箱<Aの順番で描画すればOKです。
先ほどのルールを思い出してみても、
Bは箱よりも奥なのでB<箱、
箱はAよりも奥なので箱<Aとなり、

B<箱<A

という順番が導かれそうです。


ところが


先ほど作った判定ルールをよく見てください。
左右かどうかの判定を、奥かどうかの判定よりも先にしていますね。

そうです。「AがBよりも左にあるからA<Bだ」という判断を、
「BがAよりも奥にあるからB<Aだ」とよりも優先してしまうんです。

上の図だと問題ありませんが、AとBの絵の横幅がもっと大きかったら?
この状態でAとBが重なった場合、BがAよりも手前に描画されてしまうんです。


じゃあ、決め方を少し変えてみます。
奥かどうかの判断を左右かどうかの判断よりも先にしてみましょう

・XがYよりも奥にいるなら、Xを先に描画 <--- ここの順番を変えた
・XがYよりも左にいるなら、Xを先に描画 <---
・XがYよりも下にいるなら、Xを先に描画
・それ以外の場合はYを先に描画

しかしこの場合ですと、図2ではうまくいっても図1ではうまくいきません。
新しい比較方法では、奥行き方向の比較を左右よりも優先しています。

図1ではBのほうがAよりも奥にいますから、比較結果はB<Aになります。
図1で見ると、AとBは重なっていませんからAとBのどちらを先に書いてもよさそうです。

でも忘れないでください。箱の存在を……。
この図を正しく描くためには、必ずA<箱<Bの順番で描かないといけないんです。
そのためには、AとBを比較したときにA<Bと判断されないといけません。

これ、箱の上下左右に10人ぐらいキャラクターがいた場合とか、どうします?
絶望的ですよね。たまたまうまくソートできる場合もあるとは思いますが、必ずどこかで矛盾が発生します。

まー

ややこしいといった理由がお分かりになったでしょうか?

一応、比較条件をもう少し細かくすると少しはマシになるのですが、矛盾をゼロにすることはできません。配置によっては必ず矛盾が発生するパターンがあります。

これを解決する一つの方法は、箱を細かく分割してしまうやり方です。
上での方法がややこしい理由は、単に箱がデカいからです(いや、本当に)。


昔よく見かけたクオータービューのゲームだと、ブロック化されていると言いますか、
例えば大きな建物などといったものは、いくつかのパーツに分かれてるんですね。
大きなものを、大きなままで扱おうとするから矛盾が発生するわけで。

でも今更背景や地形をブロック化するのもなァ……というわけで、結局3Dで作って2D視点固定にしちゃうのが早いんじゃない?となるわけです。なった。



おまけ
https://twitter.com/helio_dor/status/1182261982990225409

はい、この通り3Dなので、2Dではややこしい構造もやりたい放題です。


視点を変えて3Dっぽくするとこんな感じ。

最近はこういう3Dなのに2D(?)なゲーム、たまにありますよね。3D酔いの心配が無いので大好きです。

しかし元々立体化なんて考慮していない描き方の背景を無理矢理3Dっぽくしているので、よく見ると色々歪んでます。
というか、なんかスケール感がおかしいです。

まあこれは単なるテストで実際には使わない視点なので……。



おまけ2


本文中でチラッと触れた、キャラの横幅が長い場合。(思い返して画像作ってみた)

一体どうすりゃいいと思います……?(^ω^;)

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

記事のタグから探す

月別アーカイブ

限定特典から探す

記事を検索