TL;DR
- 3DゲームエンジンをHot Soup Processor3で作成しています
- レイキャスティングを使用しています
概要
こんにちは。Unityを全く使えない私は2Dゲームの制作を主にやってますが、この前友達に「Doom作ってみてよ」と突然言われたことがきっかけで、3Dゲーム制作に挑戦することにしました。
まだ未完成なのですが、現状のゲーム画面は以下のようになっています。
この記事では、どのように制作したかを、そこはかとなく書きつくっております。
製作開始から7日間の軌跡は、↓ 私のツイートのリプライツリーに載せております。
理論説明
ソースコードをドン!でも普通はいいのですが、上記のようにノリで一気に開発しておりましたので、自分でも後で見て理解に苦しむような長文計算式だらけで、とても人に見せられるモノではありません。
そのため、ここではこのゲームエンジンを作るにあたって使用した理論を説明していこうと思います。
当たり判定
1日目のツイートをご覧の通り、まずこのゲームは3Dではなく、単なる壁(線分)とキャラクター(円)の当たり判定エンジンとしてスタートしました。
ここでは単純に、高校数学IIで勉強する「点と直線の距離公式」を使用しています。
下図のように、壁は線分(x1, y1) - (x2, y2)、キャラクターは円(中心: (x, y)、半径r) で表さています。フレーム(ゲームをアニメーションとみたときの1コマ1コマ)毎に、線分と円の中心との距離を求めて、円の半径よりも距離が短ければ壁と円が当たっているで、適切な移動処理を行います。
詳しくは割愛しますが、キャラクターの移動の結果、そのキャラクターが壁にめり込むようなことがあれば、キャラクターを壁に接する位置まで押し戻すアルゴリズムも、このとき実装されています。
3D描画
2日目~6日目では、いきなり3D画面が出来上がっています。1日目を見て薄々勘付くかもしれませんが、このゲーム、見た目は3Dですが中身では2Dで処理しています。
3D描画には、「レイキャスティング」という技術を使用しています。
これは、視界の始点から角度の少しずつ異なる光線(レイ) を沢山引き、それぞれの光線が、どの壁に、どの程度の距離で当たっているかを計算して、画面を構成するという手法です。計算方法は、壁と光線の交点を求めるだけです。また数学IIです。
デバッグの為に、1日目のような俯瞰図の上にレイを可視化する機能もつけています。こちらのほうが分かりやすいかもしれません。
テクスチャ
レイキャスティングを使って、光線がどの壁に、どの程度の距離で当たっているかを判定することができました。しかしこのままでは、壁に絵(テクスチャといいます) を貼ることができません。
これを解決するために、「光線が、壁の左端からどれだけの距離にある点で、壁に接触したか」を考えることにしました。線分と直線の距離測定により、交点を求める。求めた交点が壁の左端からどれほど離れているかの値を求め、画像と照らし合わせます。こうやって、画像の何列目の色を画面に描画すればいいかを計算することによって、7日目の画像にあるような、絵を壁に貼ることに成功しました。なんでマリオ
キャラクター
Doom(ゲーム) を見て、キャラクターは2Dの絵を貼っているだけということに気付くと思います。今回はそのようなスタイルを目指して、キャラクターに複雑な3D処理は行わず、壁と同じような要領で、レイキャスティングで済ませることにしました。(「概要」中の画像の、シアン色の四角がキャラクターです。) ガチ3D描画すると重いので。CPUをシングルスレッドでブン回して描画してるからね。仕方ないね。さっき自前のノートパソコンで動かしたら15FPSでした。ナメてんのか。
まだテクスチャが貼れていません。サボりです。サボりすぎてもうコードに何が書いてあるのか忘れかけています。よくないね。
おわりに
ありがとうございました いかがだったでしょうか。今回は3Dゲームを基礎の基礎から作ってみるための理論と、使用した実例を紹介しました。このように、ほかのプログラムを作るための「土台」の部分を作るのは、普段とはまた異なる方向の趣がありとても楽しいので、みなさんもライブラリなりフレームワークなりの自作に、是非挑戦してみてください。あとHot Soup Processor(ここで使用したプログラミング言語)はいいゾ。