2D 車両
1996年8月下旬の週末、Pat Kerr は後に『Grand Theft Auto』の車両システムの基礎となる 2D 物理プロトタイプを書いた。30年後、彼はそれを JavaScript で再構築し、そのモデルの仕組みを詳しく解説した。
日本語
コピー

あるプロジェクトの歴史 · 1996–2026
2D 車両
1996年8月下旬のある週末、私は2D物理シミュレーションを書いた。それが後に大ヒット作『Grand Theft Auto』(『GTA』)の車両システムの土台となった。
もともとは Atari ST で GFA BASIC を使って書いたワイヤーフレームの小さなデモだった(後に C に移植し、実際のゲームで使うことになる)。
30周年を迎えた今、JavaScript で作り直した*。少し見栄えのする「リマスター版」として、興味のある人が眺めたり触ったりできる形にした。
1996年のアイデアを Motion Lab で作り直したもの。
操作方法
上のリマスター版はそのまま遊べる。スマートフォンならタッチ操作にも対応している。
デフォルトの「Car」モード(1)のほかに、技術的にはより単純な Spaceship(つまり「Ship」、2)と「Brick」(3)のモードがある。設定のモードセレクタで切り替えてもいいし、キーボードの対応する数字キーを押してもいい。
フィールドを囲む衝突バリアはクリックか「B」キーでオンオフでき、「G」は垂直方向の重力を切り替える(これが実際に意味を持つのは Ship と Brick モードだけだ)。
カメラの操作は「Z」と「X」が受け持つ。「Z」はいわゆるカメラの「デッドゾーン」を切り替える。車両がどれだけ動いたらカメラが追従を始めるかを決めるものだ。「X」は速度に応じたズーム機能を切り替える。速く走るとカメラが少し引く(GTA と同じように)。
*(もちろん、著作権や商標を侵害する意図は一切ない)
[自発的な免責事項:本作は『Grand Theft Auto』シリーズおよびその発行元である「Take-Two」から完全に独立しており、「Rockstar Games」という開発主体とも何の関係もない。この点は明確に言っておきたい。むしろ喜んで言わせてもらう。切望していると言ってもいい。]
仕組み
小さなアイデア、二層の構造。
このプロトタイプは、汎用の2D剛体と、意図的にごく単純に作った車のモデルを組み合わせている。
最初のシミュレーションは「Brick」に近いものから始まり、いくつかの拡張を加えて「Ship」を作った(1986年の名作「Thrust」を意図的に連想させる)。最後に必要な要素を足して、より「Car」らしくした。
システムの中核は、単純な古典的2D剛体力学のシミュレーションだ。当時のゲームでは(いくつか明らかな例外はあるが)あまり一般的ではなかったと記憶している。ほとんどのゲームの車両は高校物理レベルの「質点物理」(F = ma)で、回転成分は各種の怪しい「ハック」で処理していた。本物の剛体物理(トルクを含む)を使えば、回転をより一貫して扱える。
この中核の上に、単純で近似的、技術的には正確ではないタイヤ挙動モデルによる「目新しい」車両シミュレーション層を載せた。ほぼ当てずっぽうの産物で、物理的に正確でないことは分かっていたが、当時の目的には「十分」に思えた。
入力から運動へ
以下の図は現在の JavaScript リマスター版を表している。ブラウザの UI が操作を提供し、シミュレーションが固定タイムステップで進み、Canvas レンダラーが結果の状態を描画する。この責務を分けておくと、キー入力がどこで力になり、その力がどこで運動になるのかが見えやすい。画像をクリックすると拡大できる。
ページと操作からシミュレーション、描画までの全体の流れ。
一つの剛体、三つの振る舞い
車両は、剛体、表示形状と衝突形状を記述する shell、振る舞いを与える dynamics オブジェクトを組み合わせている。Brick はポインタのドラッグによる力を受け取る。Ship は取り付け点に推力を加える。Car はエンジン出力とステアリングを加え、4つのタイヤ位置に抵抗を加える。モードを切り替えると shell と振る舞いが入れ替わり、剛体の位置と運動状態はそのまま保たれる。
車両コーディネータが形状、振る舞い、剛体の状態をどう組み合わせるか。
力は剛体を押しもするし、回しもする
剛体は位置と速度だけでなく、角度と角速度も記録する。重心を通る力は運動を変え、重心から外れて加わる力は回転も生む。シミュレーションはすべての力とトルクを合計し、速度を更新してから位置と角度を進める。回転する剛体上の一点は独自の速度を持ち、それは剛体全体の運動と重心まわりの運動を足し合わせたものになる。
Barrier が使うのはこの点速度だ。ある形状が辺を越えると、シミュレーションはそれを内側に戻し、barrier に向かって動いているなら接触インパルスを加える。したがって偏心した衝突は速度も自転も変える。これは単純な barrier ソルバーで、辺は摩擦なしであり、汎用の衝突システムではない。
共有される物理コアと、barrier 接触を解決する手順。
意図的に近似されたタイヤ
Car はタイヤごとにその位置の速度を測り、ホイールの向きに沿った成分と横方向の成分に分解する。転がりにはわずかな抵抗を、横方向の動きにはずっと強い抵抗を与える。ステアリングは前輪の向きを変えるので、その力は車体も回転させる。ハンドブレーキは後輪の転がり抵抗を増やし、後輪の横方向のグリップを下げる。
これらの抵抗は速度に比例し、上限はない。タイヤの摩擦、スリップ、使えるグリップを再現したものではなく、便利な減衰モデルにすぎない。ごく少ない仕組みで、ホイールが横にずれるのを妨げるあの手応えを得ている。Ship と Brick は同じ物理コアを使い、力を加える方法だけが違う。
ホイール速度の成分とハンドブレーキの挙動を含む力モデル。
各部分を組み合わせる
Vehicle コーディネータは選択中の dynamics オブジェクトにそれぞれの力を加えさせ、その後で剛体を進める。さらにシェルの局所点を描画用のワールド座標に変換し、各 barrier が向き合う曲面点を求める。平面が barrier に接触したときは、接触点の中点を取る。単一の角を選ぶことで生じる不自然な回転を避けるためだ。
モードの設定、シミュレーション更新、接触ジオメトリの詳細。