回答:
昔(1990年)、古いピンボールゲームは次のように作成されました。
プレイフィールドにはいくつかのレイヤーがあります(ゲームをプレイすると表示されるもの):
衝突のためのいくつかのレイヤー:
左のグレースケールの画像はメインゲームのコリジョンマップ、右の画像は特別なエリアのピンボールランプのコリジョンマップです。
White
=ボールの空き領域、カラーインデックスは255です。
Gray
=ボールはこのゾーンから「押し出されます」。カラーインデックス=ボールの位置に追加するベクトルの角度。薄い灰色= 0度 濃い灰色= 360度
いくつかの擬似コード:
void do_ball_physics()
{
while(1)
{
byte color = read_pixel_under_ball(ballx, bally); //one pixel read
if(color == 255) //see remark below
break;
float vectorx = sin(color/255.0f * 2.0f * PI);
float vectory = cos(color/255.0f * 2.0f * PI);
ballx += vectorx; //push ball away from one unit
bally += vectory; //
}
}
いくつかの特別なカラーインデックスはまた、衝突以外の何かのために使用することができ、カスタムカラーの範囲(例:240から255)は同様に特区を検出するために予約することができspinners
、triggers
、bumpers
、holes
、...
ご覧のとおり、これは非常に簡単です。フレームごとに「読み取られる」ピクセルは数個しかありません。このため、物理シミュレーションを実際の高フレームレートで実行できます(例:200 fps)。高いフレームレートを使用すると、シミュレーションがスムーズになり、「トンネリング」が減少します(これは、ボールが速すぎてトラフエレメントを衝突せずに通過するときに発生します)。そのシンプルさはまた、386 computers
(286
色の循環、VGAのスクロール、スプライトのマスキングなどの他のいくつかのトリックの中でも)昔もスムーズなピンボールゲームを可能にし(さらには高速に)しています。
今日、ほとんどのピンボールゲームは、このように作られていません。代わりに、プレイフィールドはポリゴンまたはスプライトを使用する2D / 3Dシーンであり、視覚的なプレイフィールドの単純化された形状を表すいくつかの単純化された線、ベジエ曲線、または球に対して衝突が行われます。
例(ビジュアルピンボールから):
一部のゲーム会社は独自の物理エンジンを使用していますが、Box2D
またはのような物理エンジンを使用する方法も簡単Bullet
です。私が目にしたほとんどのiPhoneピンボールゲームは、既存の物理エンジンといくつかの3Dアセットを使用していました。
ピンボールには、穴や壁だけでなく、反応要素(打撃)や不均一な表面など、非常に豊富な物理学のセットがあり、ボールの速度が低下して速度が戻ります。
良いピンボールを作成したい場合は、3D衝突検出を使用するか、すべての衝突可能なオブジェクトが距離と速度のパラメーターを持つメソッドを持ち、変更された速度を返すセルフテーラードシステムを使用します。
最初にピンボールゲームを作成する場合、バウンディングボックス1よりも多くのbounding-CIRCLE-collision-detectionが必要になる可能性が高いです:-)
本格的なピンボールに関係する物理の複雑さを考えると、既存の2D物理エンジン。Box2DはJavaScriptでかなりの評判があります。他にもあるかもしれませんが、私は良い(そして無料の)ものに出くわしませんでした。
Rq1:あなたは確かに(私がするように)ゲームの更新と描画の間の古典的な分割を使用します。そして、タイマー(setInterval / setTimeout)やRequestAnimationFrameを使用して、定期的にupdateを呼び出してから描画します。ピンボールは、1つのタイマーが更新を駆動し、もう1つがドローを駆動するタイプのゲームである可能性があります。そのため、それぞれのレートを個別に調整して、幅広いデバイスで作業できます。デバイスが遅すぎる場合は、単にドロップ(更新+描画)できないので、2つの更新の間の時間(dt)が長くなりすぎると、物理エンジンが衝突を見逃す可能性があります。