3d oyunda bir hedefe ateş Algoritması


11

İniş Freespace'i hatırlayanlarınız için, güdümlü olmayan füzeler veya lazerler çekerken düşmana nişan almanıza yardımcı olmak için güzel bir özelliği vardı: geminin önünde, kovaladığınız geminin önünde, vurmak için nereye ateş edeceğinizi söyleyen bir artı işareti vardı hedef.

Https://stackoverflow.com/questions/4107403/ai-algorithm-to-shoot-at-a-target-in-a-2d-game?lq=1 adresinden gelen yanıtı kullanmayı denedim ancak 2B için denedim uyarlamak.

Önce XoZ düzlemi için kesişim noktasını çözmek için hesaplamayı ayrıştırdım ve x ve z koordinatlarını kaydettim ve sonra XoY düzlemi için kesişim noktasını çözdüm ve daha sonra klip alanına dönüştürdüğüm ve bunlara bir doku koyduğum bir son xyz'ye y koordinatını ekledim koordinatlar. Ama tabii ki olması gerektiği gibi çalışmıyor ya da başka bir soru sormazdım.

XoZ düzleminde x ve XoY'de x bulduktan sonra fark ettiğimden x aynı değil, bu yüzden bir şeyler yanlış olmalı.

    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);

İlk kez targetVelocity.y aslında targetVelocity.z (targetPos için aynıdır) ve ikinci kez aslında targetVelocity.y'dir.

XoZ'dan sonraki son pozisyon

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

ve XoY'den sonra

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

2 uçağa ayırma ve iyi hesaplama hesaplama yaklaşımım var mı? Yoksa 3D için tamamen farklı bir yaklaşım var mı?

  • sqr () kare değil sqrt - bir karışıklık kaçınarak.

1
"Hedefe liderlik etmek", aradığınız kelime öbeği olabilir.
MichaelHouse

Yanıtlar:


12

2 2d fonksiyonlarına ayırmaya gerek yoktur. Üzerinde çalıştığınız ikinci dereceden denklem 3B de iyi çalışıyor. İşte 2d veya 3d için sözde kod. Bir kulenin (kule savunması) mermiyi vurduğunu ima eder:

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' sormak istediğiniz vektör olabilir.


Sen bir dahisin ve kıçımı kurtardın !! Lanet Olmak için 15 itibar gerekiyor ....
Sebastian Bugiu

@SebastianBugiu bunu senin için yaptım.
AgentFire

@SebastianBugiu Teşekkürler, bu konsepti öğrendiğim için çok memnun oldum ve size yardımcı olduğu için çok mutluyum. Bir diğer zarif özelliği ise çarpışma algılama algoritmalarıyla uğraşmanıza gerek kalmamasıdır. CD kodunun yazılmasına gerek yoktur. Hedef ve mermi yolları tahmin edilebilir olduğundan, etki timeToImpactsıfıra kadar geri sayıldığında ortaya çıkacaktır .
Steve H

1

Aynı konuda iyi bir blog yazısı da var: http://playtechs.blogspot.kr/2007/04/aiming-at-moving-target.html . Ayrıca yerçekimi içeren daha karmaşık örnekler içerir.

Yazar daha basit bir kodlama yaptı, bu da daha kompakt bir kodla sonuçlandı:

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;
}

Güncelleme: Orijinal yazar sadece daha büyük kökleri hesaba kattı. Ancak daha küçük köklerin negatif olmaması durumunda, etki süresi daha kısa olduğu için daha iyi bir çözümle sonuçlanır. Kodu buna göre güncelledim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.