そうでなければ、この分析は成り立たないので、あなたはあなたの船に物理的に正しい動きがあると仮定します。この問題を適切に解決するには、効率よりも強力なものが必要です。
各スラスタは、船の動きに線形と角度の2つの効果をもたらします。これらは独立して考えることができます。スラスタがf
方向dir
に力を生成し、ベクトルによって重心からオフセットされる場合r
(幾何学的な中心またはスプライトの中心ではない!)場合、線形コンポーネントへの影響は次のとおりです。
t = f * dir // f is a scalar, dir is unit length
角速度への影響はトルクによって与えられます:
tau = f * <dir.x, dir.y, 0> CROSS <r.x, r.y, 0> // cross product
t
力ベクトル(つまり、線形推力)です。 tau
は、質量慣性モーメントで除算すると、角加速度を与える符号付きスカラーです。ことが重要であるdir
とは、r
ローカル座標で、または両方のワールド座標の両方、すなわち、同じ座標空間の両方です。
船の全体的な線形加速度は、t
各スラスタのの合計を船の質量で割った値で与えられます。同様に、角加速度は、トルクの合計を慣性質量モーメント(別のスカラー)で割ったものです。合計トルクがゼロの場合、船は回転しません。同様に、総推力がゼロの場合は移動しません。リコールトルクはスカラーですが、推力(の合計t
)は2Dベクトルです。
この博覧会のポイントは、問題を線形プログラムとして書くことができるようになったことです。最初に、移動せずに船を回したい。各スラスタの変数$ x_1、x_2、... $があります。これは、スラスタが提供する推力の量です。制約の1つのセットは次のとおりです。
0 <= x_i < fmax_i //for each i
fmax
そのスラスタの最大の力はどこにありますか(これにより、より強いまたはより弱いものが得られます)。次に、我々は両方の平等を言う:
0 = Sum_i x_i * dir_i.x
0 = Sum_i x_i * dir_i.y
これは、総推力がゼロである(推力はベクトルなので、各部分がゼロであるとだけ言う)ことで、線形加速度を適用しないという制約をエンコードします。
今、私たちは船に向きを変えてほしい。おそらく私たちはできるだけ早くそれをしたいので、次のことをしたいのです。
max (Sum_i x_i * c_i)
where c_i = <dir_i.x, dir_i.y, 0> CROSS <r_i.x, r_i.y, 0>
の解決 x_i
上記の不等式と等式を満たしながらを上記の合計が最大化され、目的の推力が得られます。ほとんどのプログラミング言語には、LPライブラリが用意されています。上記の問題を入力するだけで、答えが得られます。
同様の問題により、方向転換せずに移動できます。正のx方向に移動したい座標系で問題を書き直したとします。制約は次のとおりです。
0 <= x_i < fmax_i //for each i
max Sum_i x_i * dir_i.x
0 = Sum_i x_i * dir_i.y
0 = (Sum_i x_i * c_i)
where c_i = <dir_i.x, dir_i.y, 0> CROSS <r_i.x, r_i.y, 0> // as before
スラスタは単一方向の推力しか生成できないという制約により、達成できる回転と線速度の種類には制限があります。これは解決策として現れます0 = x_1 = x_2 = ... = x_n
ます。つまり、どこにも行けないということです。これを緩和するために、各プレイヤーが両側に45度のスラスタを配置するために、小さく弱い(たとえば5%、10%)スラスタを追加することをお勧めします。これにより、ソリューションの柔軟性が向上します。これらは、メインスラスタの弱い二次的な影響に対処するために使用できるためです。
最後に、最大100個のスラスターまで、LPの解決はフレームごとに実行できるほど高速です。ただし、ソリューションは場所や現在の状態に依存しないため、形状が変化するたびに、合理的なコントローラー入力の組み合わせごとにソリューションを事前計算できます(これには、慣性モーメントまたは船の質量を変更する非スラスタを追加すること、その理由は、スラスタが重心に対して異なる場所にあるからです!)。これは24の可能性です(つまり、8方向の時間{左回転、回転なし、右回転})。