C# OpenTKで3Dカーレースっぽいゲームをつくります。前回のC# OpenTKでUnityのアセットは使えるのか?で取得したデータで自動車をつくります。

基本的な部分をOpenTKでつくる

まずは基本的な部分を示します。

車を描画するクラス

車を描画するためのクラスと関連するクラスを示します。

CarDataクラス

まず車を描画するために取得した座標を格納するクラスを示します。これは C# OpenTKでUnityのアセットは使えるのか? の最後の部分ででてきたものと同じです。

Charctorクラス

Carクラスを作成する前にその基底クラスになるCharctorクラスを作成します。

Carクラス

carDataをもとに描画するときに座標系がちがっているので修正の処理をいれています。そのまま描画するとX軸の方向を向いているので90を足して向こう側を向かせます。

コースを描画する

次にコースを描画するためのCourseクラスを示します。長々と書いていますが、画像の輪郭を取得するにはに掲載したものを少しだけ変更しただけです。

コンストラクタにコースが書かれた画像ファイルを渡すとコースの内部の点と境界線の点の座標を取得できるようになります。

コースの境界線を取得する

Bitmapの1ピクセルを1とはせずに拡大処理を入れているため、上記にさらに以下を加えます。

まず2つの境界線を構成する点のリストを取得するプロパティを作成します。

コースの内部

コースはGetPointsInsideメソッドが返した点を中心とする矩形を敷き詰めてつくります。InsideRectanglesはその矩形のリストを返します。

IsPointInsideメソッドは渡された座標がコースの内部かどうかを返します。わたされた座標を拡大率で除算し、これが_insidePoints内に存在するか調べます。

コースアウト対策

GetNeerestExpandedBorderPointsメソッドは引数でわたされた点にもっとも近い両側のブロックの座標を返します。自車がクラッシュしたときの復活地点の算出などに使用します。

GetNeerestExpandedBorderPointsメソッドを追加したので、Carクラスに以下を追加します。車の初期座標をセットすれば最適な方向を向かせることができます。

Courseクラスに話を戻します。GetCenterPointsメソッドはコースの両側にあるブロックからみて中間点にあたる点のリストを返します。この点を結べばセンターラインがひけるのかというとそうはなりません。コースの輪郭を1.0単位にしているのでギザギザになってしまうのです。

IdealPointメソッドは引数として渡された点の近くにある理想の座標(コースの真ん中)を返します。ライバル車の動作を考えるときに必要です。

GameManagerクラス

描画するオブジェクトの更新や描画をするためのGameManagerクラスを作成します。

初期化の処理

車とコースを描画します。車に対してコースの幅が狭いので調整しています。

コンストラクタを示します。クラス内からForm1とGLControlにアクセスできるように引数を渡しています。

視界と光源の設定

視界と光源の設定をする処理を示します。今回は自機(というか自分の車)の後ろをカメラが追うような描写をします。自車の方向に進行よっては逆光になることもあるので、そうはならないように光源を設定します。

車の頂点座標を読み出す

GLControlがロードされたらReadCarFilesメソッドでxmlファイルから頂点座標を読み出します。読み取るのはC# OpenTKでUnityのアセットは使えるのか?で保存したXMLファイルです。ここからダウンロードできます。

ReadCarFilesメソッドで取得したCarDataオブジェクトを引数にしてCarクラスのコンストラクタを呼び出します。

更新処理

更新処理に関する部分を示します。キーが押されていたら車の方向と速度を変えます。速度とコースアウトしていないかどうかをフォームに貼り付けているLabelに表示します。フォームのLabelはpublicにしておきます。

描画の処理

描画の処理をする部分を示します。前述のUpdateメソッドでオブジェクトの表示位置を更新したあとCar.Drawメソッドと後述するDrawCourseメソッドで車とコースを描画します。

DrawCourseメソッドを示します。

では自車を動かしてみましょう。ハンドル操作は←キーと→キーで、アクセルは↑キー、ブレーキは↓キーです。バックはできない仕様になっています。またコースアウトしてもそのまま走り続けます。