2Dタワーディフェンス-敵への弾丸


14

敵に弾丸を打つための良い解決策を見つけようとしています。ゲームは2Dタワーディフェンスです。タワーは弾丸を撃ち、保証された敵を攻撃することになっています。

私はこの解決策を試しました-http://blog.wolfire.com/2009/07/linear-algebra-for-game-developers-part-1/

弾丸の起源と敵を同様に差し引くために言及されたリンク(ベクトル減算)。私はそれを試してみましたが、敵の周りに弾丸がついてきます。

float diffX = enemy.position.x - position.x;
float diffY = enemy.position.y - position.y;

velocity.x = diffX;
velocity.y = diffY;

position.add(velocity.x * deltaTime, velocity.y * deltaTime);

私はベクトルに精通していますが、このソリューションを機能させるためにどのステップ(ベクトル演算)を行うべきかはわかりません。


回答:


11

あなたの推論は完璧でした。ベクトルを使用して、私の位置からターゲットに移動しました。これがベクトルの目的です。あなたは単に速度を忘れてしまった!

速度はベクトルです。速度と方向です。ただし、差ベクトルの正規化を忘れて弾丸速度(スカラー)を掛けると、ターゲットに近づいた場合(差ベクトルが小さい場合)、弾丸が遅くなります。一方、遠くにいる場合、弾丸の速度は大きくなります。

これが根本的な問題です。ベクトルの方向大きさの両方を計算する必要があります。


助けてくれてありがとう。差分ベクトルを計算した後、スカラーを使用しようとしましたが、うまくいきましたが、良くありません。差分ベクトルを計算し、正規化してから速度をスカラー化するかどうかを確認しようとしました。今は良く見えます。はい、私はこのゲームでいつかホーミングミサイルが必要だと思います。再度、感謝します。
田州

1
この答えは他の誰にも意味がありませんか?
BlueRaja-ダニーPflughoeft

@Fxlll:わかりました、私はあなたが言っていることを見ると思います。開始/終了時の答えとは関係のない綿毛がたくさんあり、あなたの英語にも混乱しました(おそらくあなたのせいではないでしょう)。この回答を整理するための編集提案を提出しました。
BlueRaja-ダニーPflughoeft

@BlueRaja-Danny Pflughoeft、あなたの努力に感謝します!
FxIII

7

ターゲットが安定したペースで安定した方向に移動しており、弾丸の軌跡が安定したペースで直線である場合、二次方程式を使用して、ターゲットが交差する正確なスポットを予測し、タワーの銃をそのスポットに向けることができます。

弾丸がマークに命中することは確実であり、発砲から衝突までにかかる正確な時間を計算できるため、衝突の検出は不要で、単に銃を発砲し、計算された期間を待機し、ヒットを登録します。

二次方程式の擬似コードは次のとおりです。

Vector totarget =  target.position - tower.position;

float a = Vector.Dot(target.velocity, target.velocity) - (bullet.velocity * bullet.velocity);
float b = 2 * Vector.Dot(target.velocity, totarget);
float c = Vector.Dot(totarget, totarget);

float p = -b / (2 * a);
float q = (float)Math.Sqrt((b * b) - 4 * a * c) / (2 * a);

float t1 = p - q;
float t2 = p + q;
float t;

if (t1 > t2 && t2 > 0)
{
    t = t2;
}
else
{
    t = t1;
}

Vector aimSpot = target.position + target.velocity * t;
Vector bulletPath = aimSpot - tower.position;
float timeToImpact = bulletPath.Length() / bullet.speed;//speed must be in units per second

擬似コードのおかげで、この状況で二次方程式がどのように機能するかを確認します。再度、感謝します。
田州

問題は、ユーザーが弾丸に向かって移動し、ヒットする直前に弾丸の痕跡から逃げることができることです。この場合、このソリューションで十分でしょうか?
マーティン。

いいえ、最初の文で修飾されています。これはすべてのゲームではなく、ターゲットが一定の速度でのみ移動するゲームです。一定速度とは、方向と速度の両方を意味します。たとえば、Defense Gridスタイルのゲームゲームではこのアプローチを使用できます。
スティーブH

3

弾丸が到達するまでにオブジェクトの位置を「予測」する必要があります。これを行うには、オブジェクトの速度/速度(できれば一定です;))と方向ベクトルを使用します。

正確な式が私の頭の上のものかどうかはわかりませんが、次のようなものだと思います:

NewPosition = OldPosition +(速度* DirectionVector);

パスが設定されている場合は、オブジェクトの方向が変わったときに再計算する必要があります。このNewPositionを敵の位置ベクトルとして使用すると、弾丸は「ホーミング効果」なしでオブジェクトに当たるはずです。ホーミングは、元のベクトルが計算されてから敵オブジェクトが移動したという事実により発生します。オブジェクトが一方向に十分に長く移動している場合にのみ追いつくことができます。

お役に立てれば :)


3
または、チートして自動的にヒットし、移動するスプライトを視覚的なフィードバックとして使用できます。または、50000²mphで弾丸を発射するだけです。
ジョナサンコネル

1

平方根と2の累乗の使用を避けることができます。

var distX:Float = target.x - x;
var distY:Float = target.y - y;
_velX = distX / timeTravel;
_velY = distY / timeTravel;

// Take out if you want a nice slow down as approaches effect.  
timeTravel -= 1.0; // make sure u have a positive timeTravel.
x += _velX;
y += _velY;

if (distX < 0)
    distX = -distX;

if (distY < 0)
    distY = -distY;

if (_velX < 0)
    _velX = -_velX;

if (_velY < 0)
    _velY = -_velY;

// Should both snap @ the same time.
if (distX < _velX)
x = target.x; // snap & see what happens.

if (distY < _velY)
y = target.y; // snap & see what happens.

// TODO: call your onHitTarget here ...
// Hopefully this shall provide 10x the performance 
// of using Math.sqrt and all the extra multiplications.

すべてメモリから書き込まれます。ちなみに、動作する要素を使用します。これが初めての場合は、行ごとにテストしてください。FloatはAS3の数値です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.