簡體   English   中英

2D: Moving Turret's Projectile Intercept 移動目標

[英]2D: Moving Turret's Projectile Intercept moving target

所以我正在制作太空游戲,宇宙飛船上有炮塔。

那些炮塔需要用恆定速度的彈丸射擊移動目標。 AkA 它需要攔截並擊中目標。

當我的船和 npc 船不在同一個方向或幾乎同一個方向移動時,它工作得很好。 當他們向同一方向移動時,炮塔會在 npc 船的稍后方發射射彈。 但是一旦我轉彎,它就會始終如一地擊中 npc 船。

另外,當我站着不動時,npc 船在我面前微微開火,但當我站着不動時,我的船一直在撞擊 npc 船。

這是我的代碼:

Vector2 toTarget = (targetShip.GlobalPosition) - GlobalPosition;
            Vector2 targetVel = (targetShip.dir * targetShip.speed);
            Vector2 gunVelocity = (Player.currentShip.dir * Player.currentShip.playerSpeed);
            Vector2 vr = targetVel - gunVelocity;

            float t = AimAhead(toTarget, vr);

            if(t > 0f)
            {
                Vector2 aimPoint = targetShip.GlobalPosition + vr * t;
                dir = aimPoint - Player.currentShip.GlobalPosition; 
                GlobalRotation = Mathf.LerpAngle(GlobalRotation, dir.Angle(), turnRate * delta);
            }
            else
            {
                Vector2 aimPoint = targetShip.GlobalPosition;
                dir = aimPoint - Player.currentShip.GlobalPosition;
                GlobalRotation = Mathf.LerpAngle(GlobalRotation, dir.Angle(), turnRate * delta);
            }

前方目標 function:

 float a = vr.Dot(vr) - (projectile.speed * projectile.speed );
        float b = 2 * vr.Dot(toTarget);
        float c = toTarget.Dot(toTarget);

        float det = b * b - 4 * a * c;

        if (det > 0f)
        {
            return 2 * c / (Mathf.Sqrt(det) - b);
        }
        else
        {
            return -1f;
        }

對於簡單的線性運動,這看起來是正確的:

float a = vr.Dot(vr) - (projectile.speed * projectile.speed);
float b = 2 * vr.Dot(toTarget);
float c = toTarget.Dot(toTarget);

從那里我會這樣做:

var bb = b * b;
var a2 = 2 * a;
var ac4 = 4 * a * c;

並使用此檢查:

if (bb >= ac4 && a2 != 0.0)

顯然bb >= ac4等同於您正在使用的支票。

那么為什么a2.= 0.0 好吧,如果你猜對了前三行,我想你知道我們正在使用二次方程的解。 一個二次方程有兩個解,分別是(-b + sqrt(bb - ac4))/a2(-b - sqrt(bb - ac4))/a2即二次方程的±:

二次公式

我不想被零除。

好的,所以我們有兩種可能的解決方案。 這就是我進行的方式:

var r = Mathf.Sqrt(bb - ac4);
var times = new float[]{(-b + r)/a2, (-b - r)/a2};
var time = float.PositiveInfinity;
foreach (var candidate_time in times)
{
    if (candidate_time < 0.0)
    {
        continue;
    }

    if (candidate_time < time)
    {
        time = candidate_time;
    }
}

if (float.IsInfinity(time))
{
    return -1f;
}

return time;

這是基於擊中移動目標的實現,該目標遵循您可以在其他地方找到的線段定義的路徑。 對於這個簡單的案例,我可以做更多的事情。

啊一個有趣的錯誤...

Vector2 aimPoint = targetShip.GlobalPosition + vr * t;

應該:

Vector2 aimPoint = targetShip.GlobalPosition + targetVel * t;

現在一切正常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM