動作確認はこちらから

前回の時計を表示させる TypeScript/JavaScriptでつくるチクタクバンバンのようなゲームではチクタクバンバンに出てきそうな時計を描画させました。今回は線路プレートを生成、表示させます。

線路プレートのタイプを表す列挙体

まず線路プレートのタイプを表す列挙体をつくります。

それから線路プレートは縦横4列ずつならんでいるので、変数として以下を定義しておきます。

TrackPlateクラス

まず線路プレートを生成する方法を考えます。そのあと移動させる方法を考えます(後者のほうが簡単です)。

コンストラクタ

最初にコンストラクタとプロパティ(線路プレート生成に関連する部分のみ)を示します。コンストラクタの引数は、初期状態で何行何列目に配置するかと配置する線路プレートの種類です。引数でわたされたPlateTypeから必要な線路プレートを生成します。

南北に移動できる線路プレートを生成する

PlateTypeから必要な線路プレートを生成します。最初に南北に移動できる線路プレートを生成する関数を示します。

直方体を2つつくって通路部分をあけた状態で並べればできるのですが、他の線路プレートを場合との兼ね合いであえて面倒な方法をとりました。光があたる関係で通路の溝が見えにくくなる場合があるので溝のなかの壁はつくっていません。また溝が黒く見えるように黒い板を内部に張り付けています(後述:CreateBottomMesh関数)。

それから自分でgeometryに頂点座標をセットしてTHREE.Face3関数を実行する場合、geometry.computeFaceNormals();を実行しておかないと、ライティングが必要なマテリアルを適用しようとしてもうまく描画されなくなります。

線路プレートの内部が黒く見えるようにするためのメッシュをふたつ作ります。一つ目は線路プレートの上面のすぐ下に、もうひとつは線路プレートの底面にあたる部分につくります。

東西に移動できる線路プレートを生成する

次に東西に移動できる線路プレートを生成するCreateWE関数ですが、これは簡単です。CreateNS関数で生成されたものを回転させてそのまま使います。

東西南北に移動できる線路プレートを生成する

東西南北に移動できる線路プレートを生成する関数を示します。

カーブがある線路プレートを生成する

次にカーブがある線路プレートですが、ここは斜めに切って線路が存在する部分と存在しない部分にわけて考えます。ひとつできてしまえば組み合わせて線路プレートは完成です。完成した線路プレートを回転させればほかの線路プレートにも使えます。

まず簡単にできそうな線路が存在しない三角形の線路プレートを生成する関数を示します。

次がちょっと面倒です。カーブの内側部分であれば三角関数を使えば簡単にできますが、外側はどうやってつくればいいのでしょうか?

ちょっと関数が長くなってしまいました。もっとスマートなやり方があるはずなのですが、今回はこれで勘弁してください。

上記の関数で生成したものを組み合わせれば南西間を移動する線路プレートをつくることができます。そしてこれを回転させれば北西間、南東間を移動する線路プレートも生成できます。

カーブがふたつある線路プレートを生成する

北東間と南西間、北西間と南東間を移動する線路プレートを生成するCreateNESW関数とCreateNWSE関数を示します。

これで線路プレートを生成することはできるようになりました。

線路プレートを移動する機能を追加する

次にこれを移動する機能を追加します。

静的プロパティとしてBlankColumとBlankRowがありますが、これは線路プレートが存在しない部分です。方向キーをおすとこれを埋めるように周囲の線路プレートが移動します。

線路プレートが移動するとそのX座標とZ座標が変化するだけでなくRowプロパティとColumプロパティも変化します。そしてBlankColumとBlankRowも変化します。うっかりミスをしやすい部分なのできっちり関数化してしまいましょう。

MoveNorth関数は線路プレートを上側に移動させます。GetPlate関数は引数で指定されたRowプロパティとColumプロパティをもつ線路プレートを返します。もしGetPlate関数がnullを返した場合は移動可能な線路プレートは存在しないということなのでなにもしません。

同様に下と左右に移動させる関数も示します。

となりにある線路プレートを取得する

以下は引数で渡された線路プレートの東西南北の位置にある線路プレートを返します。チクタクバンバンを移動させるときに必要になる関数です。

動作確認はこちらから