Wiem, że to jest starodawne pytanie, ale myślę, że w odpowiedziach udzielonych do tej pory coś pominęło. W pierwotnym pytaniu pocisk (lub cokolwiek innego) miał przyspieszyć w kierunku pozycji celu. Kilka odpowiedzi wskazało, że było to błędne, i powinieneś przyspieszyć w kierunku, w którym twoim zdaniem będzie cel w późniejszym czasie. Jest lepiej, ale nadal źle.
To, co naprawdę chcesz zrobić, to nie przyspieszać w kierunku celu, ale zbliżać się do celu. Sposobem na przemyślenie tego jest ustawienie pożądanej prędkości skierowanej na cel (lub rzut lokalizacji celu), a następnie ustalenie, jakie przyspieszenie najlepiej zastosować (biorąc pod uwagę wszelkie ograniczenia, jakie masz, tj. Pocisk prawdopodobnie nie może przyspieszyć bezpośrednio w odwrotnej kolejności), aby osiągnąć pożądaną prędkość (pamiętając, że prędkość jest wektorem).
Oto sprawdzony przykład, który zaimplementowałem dziś rano, w moim przypadku dla sztucznej inteligencji gracza w sportowej grze symulacyjnej, w której gracz próbuje ścigać przeciwnika. Ruch jest regulowany przez standardowy model „kick-drift”, w którym przyspieszenia są stosowane na początku pomiaru czasu w celu aktualizacji prędkości, a następnie obiekty dryfują z tą prędkością przez czas trwania pomiaru czasu.
Chciałbym opublikować pochodną tego, ale stwierdziłem, że nie ma obsługiwanego znacznika matematycznego na tej stronie. Gwizd! Musisz tylko zaufać, że jest to optymalne rozwiązanie, zważywszy na to, że nie mam ograniczeń co do kierunku przyspieszenia, czego nie ma w przypadku obiektu typu pocisk, więc wymagałoby to dodatkowych ograniczeń.
Kod jest w Pythonie, ale powinien być czytelny na dowolnym tle języka. Dla uproszczenia zakładam, że każdy krok ma długość 1 i wyrażam prędkość i przyspieszenie w odpowiednich jednostkach, aby to odzwierciedlić.
self.x = # current x co-ordinate
self.y = # current y co-ordinate
self.angle = # current angle of motion
self.current_speed = # current magnitude of the velocity
self.acc # Maximum acceleration player can exert on themselves
target_x = # x co-ordinate of target position or projection of it
target_y = # y co-ordinate of target position or projection of it
vx = self.current_speed * math.cos(self.angle) # current velocity x component
vy = self.current_speed * math.sin(self.angle) # current velocity y component
# Find best direction to accelerate
acc_angle = math.atan2(self.x + vx - target_x,self.y + vy - target_y)
Zauważ, że funkcja atan2 (a, b) oblicza odwrotną tan a / b, ale zapewnia, że kąty znajdują się we właściwej ćwiartce koła, co wymaga znajomości znaku zarówno a, jak i b.
W moim przypadku, gdy już mam przyspieszenie, stosuję to, aby zaktualizować prędkość o
vx_new = vx + self.acc * math.cos(acc_angle)
vy_new = vy + self.acc * math.sin(acc_angle)
self.current_speed = math.sqrt( vx_new**2 + vy_new**2)
self.angle = math.atan2(vy_new,vx_new)
Sprawdzam też nową prędkość względem prędkości maksymalnej zależnej od gracza i ograniczam ją. W przypadku pocisku, samochodu lub czegoś o maksymalnej prędkości obrotu (w stopniach na tyknięcie) możesz po prostu spojrzeć na aktualny kąt ruchu w stosunku do obliczonego ideału, a jeśli ta zmiana jest większa niż dozwolona, po prostu zmień kąt o jak najwięcej w kierunku ideału.
Dla każdego, kto jest zainteresowany wyprowadzeniem tego, zapisałem odległość między graczem a celem po upływie czasu, pod względem pozycji początkowej, prędkości, prędkości przyspieszenia i kąta przyspieszenia, a następnie wziąłem pochodną w odniesieniu do kąta przyspieszenia. Ustawienie tej wartości na zero powoduje, że minima odległości gracz-cel po odmierzeniu czasu są funkcją kąta przyspieszenia, co dokładnie chcemy wiedzieć. Co ciekawe, mimo że szybkość przyspieszenia była pierwotnie w równaniach, anuluje się, uniezależniając optymalny kierunek od tego, jak bardzo jesteś w stanie przyspieszyć.