3Dゲームでターゲットを撃つアルゴリズム


11

Descent Freespaceを覚えている人にとっては、非ホーミングミサイルやレーザーを撃つときに敵を狙うのに役立つ優れた機能がありました。追跡している船の前に十字線があり、動いているところを撃つためにどこを撃つべきかを教えてくれました。目標。

私は/programming/4107403/ai-algorithm-to-shoot-at-a-target-in-a-2d-game?lq=1からの回答を使用しようとしましたが、それは2D用なので試してみましたそれを適応させます。

最初に計算を分解してXoZ平面の交点を解決し、x座標とz座標を保存してから、XoY平面の交点を解決し、y座標を最終的なxyzに追加してから、クリップスペースに変換してテクスチャを配置しました座標。しかし、もちろん、期待どおりに機能しないか、質問を投稿しなかったでしょう。

XoZ平面でxを見つけた後とXoYでxが同じではないので、何かが間違っていることに気づきます。

    float a = ENG_Math.sqr(targetVelocity.x) + ENG_Math.sqr(targetVelocity.y) -
            ENG_Math.sqr(projectileSpeed);
    float b = 2.0f * (targetVelocity.x * targetPos.x + 
            targetVelocity.y * targetPos.y);
    float c = ENG_Math.sqr(targetPos.x) + ENG_Math.sqr(targetPos.y);
    ENG_Math.solveQuadraticEquation(a, b, c, collisionTime);

初回のtargetVelocity.yは実際にはtargetVelocity.z(targetPosの場合も同じ)で、2回目は実際にはtargetVelocity.yです。

XoZ後の最終的な位置は

    crossPosition.set(minTime * finalEntityVelocity.x + finalTargetPos4D.x, 0.0f, 
                minTime * finalEntityVelocity.z + finalTargetPos4D.z);

XoY以降

    crossPosition.y = minTime * finalEntityVelocity.y + finalTargetPos4D.y;

私のアプローチは2つの平面に分離して何かを計算するのですか?または3Dの場合、まったく異なるアプローチがありますか?

  • sqr()はsqrtではなく方形です-混乱を避けます。

1
「リーディングターゲット」は、あなたが探しているフレーズかもしれません。
MichaelHouse

回答:


12

2つの2d関数に分解する必要はありません。作業しているその二次方程式は、3Dでもうまく機能します。2dまたは3dの疑似コードを以下に示します。タワー(タワーディフェンス)が発射体を撃っていることを意味します。

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 

「aimSpot」はあなたが尋ねているベクトルかもしれません。


あなたは天才であり、私のお尻を救った!! くそー私は
賛成

@SebastianBugiu私はあなたのためにそれをやった。
AgentFire

@SebastianBugiuおかげで、この概念を学んだときはうれしかったです。もう1つのエレガントな機能は、衝突検出アルゴリズムをいじる必要がないことです。CDコードを書き込む必要はありません。ターゲットと発射物の経路は予測可能であるtimeToImpactため、ゼロにカウントダウンすると影響が発生します。
スティーブH

1

同じ主題に関する優れたブログ投稿もあります:http : //playtechs.blogspot.kr/2007/04/aiming-at-moving-target.html。また、重力を含むより複雑なサンプルも含まれています。

著者はより単純化し、コードをよりコンパクトにしています。

double time_of_impact(double px, double py, double vx, double vy, double s)
{
    double a = s * s - (vx * vx + vy * vy);
    double b = px * vx + py * vy;
    double c = px * px + py * py;

    double d = b*b + a*c;

    double t = 0;
    if (d >= 0)
    {
        t = (b - sqrt(d)) / a;
        if (t < 0) 
        {
            t = (b + sqrt(d)) / a;
            if (t < 0)
                t = 0;
        }
    }

    return t;
}

更新:オリジナルの作者は、より大きなルートのみを考慮に入れました。しかし、小さいルートが非負である場合、影響の時間が小さいため、より良い解決策になります。対応してコードを更新しました。

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