Jak obliczyć wektor przechwytywania?

11

Biorąc pod uwagę dwuwymiarową przestrzeń i 1 przyjazny statek kosmiczny, który stoi w miejscu, jeden przeciwnik porusza się NIE bezpośrednio na przyjazny statek o znanej rzeczywistej pozycji, prędkości i kierunku.

Przyjazny statek chce dostać się na zasięg ostrzału, aby walczyć z wrogiem.

Właściwie ustawiam tylko wektor bezpośredni na rzeczywistą pozycję poruszającego się statku i przeliczam go co każdą klatkę, co daje rodzaj „okrągłej” ścieżki lotu.

Chcę ustalić bezpośrednią i prostą ścieżkę do pozycji, którą przeciwnik (prawdopodobnie) będzie miał po osiągnięciu odległości strzelania, zakładając, że do tego czasu nie zmieni kursu.

Jako pierwsza i „prosta” implementacja wystarczyłoby założyć, że przyjaciel może przyspieszyć od 0 do maksimum w krótkim czasie.

Preferowana implementacja to taka, która bierze pod uwagę możliwości przyspieszania przyjaciela i wie, kiedy przechwycenie jest niemożliwe ze względu na prędkość. Powinien działać na każdą prędkość początkową, nie tylko z bezruchu. Plus byłby, gdyby nawet rozważał hamowanie (walka z prędkością światła jest bardzo nieefektywna energetycznie w danym wszechświecie)

NobbZ
źródło

Odpowiedzi:

5

Jeśli rozumiem twoje pytanie, nie chcesz, aby statek kierował się na cel, ale raczej lecieć w linii prostej, która przypadkowo przechwytuje cel. Tworzę grę w obronę wieży, która zasadniczo potrzebuje tej samej kuli, wieża chce wystrzelić broń, aby pocisk przechwycił poruszający się cel, o ile nie zmieni prędkości / kierunku. Sposób, w jaki to rozwiązałem, polegał na zastosowaniu równania kwadratowego. Oto pseudo kod:

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

Przekonałem się, że to działa tak dobrze, że nie potrzebowałem wykrywania kolizji dla strzału ... Byłem w stanie liczyć na każdy strzał trafiony w dziesiątkę niezależnie od odległości / kierunku / prędkości celu, o ile te czynniki pozostały stabilne.

Steve H.
źródło
Z twojego opisu wydaje się, że tego szukam, przynajmniej prosty sposób zakładający natychmiastowe przyspieszenie do maksymalnej prędkości. Przyjrzę się temu wieczorem. Czy mam rację, że Vector.Dot zwraca produkt kropkowy do wektorów?
NobbZ
Hmmm ... Zrobiłem to teraz w rubinie, ale wydaje się, że coś jest nie tak. Za każdym razem, gdy próbuję, pojawia się wyjątek, ponieważ wyrażenie w sqrt ocenia się na coś negatywnego i dlatego jest poza zakresem. Jak sobie z tym poradzić. Przepraszam za pytanie, ale mogę tylko tego użyć, ale nie rozumiem tu konceptów, dopóki ktoś nie da mi rady.
NobbZ
Przykład pochodzi z tej książki: amazon.com/...
Steve H
1
nie wiem, czy to pomaga, ale oto kod Pythona, który osiąga to samo. moddb.com/mods/wicmw/tutorials/…
Steve H
OK, nadal nie rozumiem matematyki dziury za nią, ale dzięki kodowi python, dokumentacja powiedziała mi, że jeśli w sqrt jest wartość ujemna, to mój przyjaciel musi powoli nadrobić zaległości. Po poprawieniu wartości testowych otrzymuję wyniki. Dziękuję za pomoc.
NobbZ
6

Sugeruję przyjrzeć się zachowaniom kierowania. Szczególnie pogoń . Kod źródłowy można znaleźć w implementacji OpenSteer lub poszukać książki takiej jak „ Programowanie sztucznej inteligencji gry przez przykład ” (ISBN 13: 978-1556220784)

grzmot
źródło
pogoń wydaje się potrzebować wiedzy o celu i kieruje się nim, ale tak naprawdę nie znam celu. Wiem, gdzie jest teraz wróg, znam jego prędkość i kierunek. Teraz chcę wiedzieć, w jakim kierunku musi iść, aby przechwycić wroga w drodze do celu tak szybko i szybko, jak to możliwe. Jak wspomniano wcześniej, przyspieszenie można na początku zignorować, zaoszczędziłoby to nawet dużo czasu przetwarzania w porównaniu z rzeczywistą wersją ... W nowym modelu muszę przeliczyć tylko wtedy, gdy wróg strzela „zmianą kursu” - nie zawsze, dla każdego ” przeniósł się ”- tak jak teraz to robię.
NobbZ,
Tak, to co opisujesz jest pościg. To nie zna cel .. to sprawia, że prognozy opiera się na „wrogów” aktualna pozycja, prędkość i kierunek
bummzack
Potem źle zrozumiałem opis, przyjrzę mu się jutro.
NobbZ
Właśnie skończyłem czytać dokument kilka minut temu, pogoń NIE jest tym, czego szukam. To jest jak moja rzeczywista implementacja, z wyjątkiem tego, że celuje w pozycję następnej klatki, wciąż muszę ponownie obliczać nowy kurs dla każdej klatki, a kurs powoduje pewną krzywą. Ale to, czego chcę, to bezpośrednia linia zakładająca, że ​​wróg nie zmieni prędkości ani kursu, dopóki oba się nie spotkają. Jeśli nadal nie jest to wystarczająco jasne, staram się rysować to, co chcę po pracy. Ale i tak dzięki za linki. Myślę, że mogę użyć tego gdzie indziej w projekcie.
NobbZ
@NobbZ Przykro mi, moja odpowiedź nie była pomocna. Być może powinieneś odpowiednio zmodyfikować swoje pytanie, ponieważ stwierdzenia takie jak: „Wiem, że w przypadku zmiany prędkości lub kursu przeciwnika wszelkie obliczenia muszą zostać powtórzone” mogą być mylące… gdybyś to zrobił, musiałbyś „pogoń” za kierowaniem.
bummzack