Obrona wieży 2D - Kula wroga

14

Próbuję znaleźć dobre rozwiązanie, by kula trafiła wroga. Gra polega na obronie wieży 2D, wieża ma wystrzelić kulę i trafić wroga gwarantowana.

Wypróbowałem to rozwiązanie - http://blog.wolfire.com/2009/07/linear-algebra-for-game-developers-part-1/

Wspomniany link odejmuje pochodzenie pocisku, a także wroga (odejmowanie wektorowe). Próbowałem tego, ale kula podąża za wrogiem.

float diffX = enemy.position.x - position.x;
float diffY = enemy.position.y - position.y;

velocity.x = diffX;
velocity.y = diffY;

position.add(velocity.x * deltaTime, velocity.y * deltaTime);

Znam wektory, ale nie jestem pewien, jakie kroki (operacje matematyczne wektorów) należy wykonać, aby uruchomić to rozwiązanie.

Tashu
źródło

Odpowiedzi:

11

Twoje rozumowanie było doskonałe: użyj wektora, aby przejść z mojej pozycji do celu. To jest cel wektora ; po prostu zapomniałeś prędkości !

Prędkość to wektor: prędkość i kierunek. Jeśli jednak zapomnisz znormalizować wektor różnicy i pomnożyć go przez prędkość pocisku (skalar), zasadniczo mówisz, że jeśli jesteś blisko celu (wektor różnicy jest mały), kula zwalnia ; podczas gdy jesteś daleko, prędkość pocisku jest większa.

To jest podstawowy problem: musisz obliczyć zarówno kierunek, jak i wielkość wektora.

FxIII
źródło
Dzięki za pomoc. Próbowałem użyć skalara po obliczeniu wektora różnicy, wygląda na to, że działał, ale nie wygląda dobrze. Próbowałem sprawdzić, czy obliczę wektor różnicowy, normalizuję, a następnie skalaruję prędkość. Teraz wygląda lepiej. Tak, myślę, że potrzebuję pocisków naprowadzających w tej grze nieco później. Dzięki jeszcze raz.
Tashu
1
Czy ta odpowiedź nie ma sensu dla nikogo innego?
BlueRaja - Danny Pflughoeft
@Fxlll: Ok, myślę, że rozumiem, co próbujesz powiedzieć. Na początku / na końcu jest dużo puchu niezwiązanego z odpowiedzią, a także twój angielski był zdezorientowany (co, jak rozumiem, prawdopodobnie nie jest twoją winą) . Przesłałem propozycję edycji, aby wyczyścić tę odpowiedź.
BlueRaja - Danny Pflughoeft
@BlueRaja - Danny Pflughoeft dzięki za twój wysiłek!
FxIII
7

Jeśli cel porusza się w stałym kierunku w stałym tempie, a ścieżka pocisku znajduje się w linii prostej w stałym tempie, możesz użyć równania kwadratowego, aby przewidzieć dokładne miejsce, w którym się przecinają, i wycelować działo wieży w tym miejscu .

Ponieważ jest pewne, że kula trafi w cel, a ty możesz obliczyć dokładny czas, jaki zajmie od wystrzału do uderzenia, nie będzie wymagane wykrywanie kolizji, po prostu odpal broń, poczekaj obliczony okres czasu, zarejestruj trafienie.

Oto pseudo kod dla równania kwadratowego:

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
Steve H.
źródło
Dzięki za pseudo kod, sprawdzę go, aby zobaczyć, jak równanie kwadratowe działa w tej sytuacji. Dzięki jeszcze raz.
Tashu
Problem polega na tym, że użytkownik może zbliżać się do kuli, a tuż przed trafieniem może uciec od śladu kuli. Czy w takim przypadku to rozwiązanie byłoby wystarczająco dobre?
Martin.
Nie, jak zakwalifikowano w pierwszym zdaniu. Nie dotyczy to wszystkich gier, ale gry, w której cele poruszają się tylko ze stałą prędkością. Stała prędkość oznacza zarówno kierunek, jak i prędkość. Na przykład gra w stylu Defense Grid może korzystać z tego podejścia.
Steve H
3

Musisz „przewidzieć” położenie obiektów, zanim pocisk do nich dotrze. Możesz to zrobić, używając obiektów prędkość / prędkość (mam nadzieję, że jest stała;)) i jej wektora kierunkowego.

Nie jestem pewien, jaka jest dokładna formuła z głowy, ale myślę, że to coś takiego:

NewPosition = OldPosition + (Speed ​​* DirectionVector);

Jeśli masz ustawioną ścieżkę, konieczne będzie ponowne obliczenie, gdy obiekt zmieni kierunek. Użyj tej NewPosition jako wektora wroga. Kula powinna trafić w obiekt bez efektu naprowadzania. Naprowadzanie następuje z uwagi na fakt, że obiekt wroga poruszył się od czasu obliczenia oryginalnego wektora, może to nadrobić tylko wtedy, gdy obiekt porusza się w jednym kierunku wystarczająco długo.

Mam nadzieję że to pomoże :)

Sójka
źródło
3
Lub możesz oszukiwać i automatycznie uderzać, a następnie użyć ruchomego duszka jako wizualnej informacji zwrotnej. Lub po prostu wystrzel swoje kule z prędkością 50000 m².
Jonathan Connell
1

Możesz uniknąć używania pierwiastka kwadratowego i potęgi 2.

var distX:Float = target.x - x;
var distY:Float = target.y - y;
_velX = distX / timeTravel;
_velY = distY / timeTravel;

// Take out if you want a nice slow down as approaches effect.  
timeTravel -= 1.0; // make sure u have a positive timeTravel.
x += _velX;
y += _velY;

if (distX < 0)
    distX = -distX;

if (distY < 0)
    distY = -distY;

if (_velX < 0)
    _velX = -_velX;

if (_velY < 0)
    _velY = -_velY;

// Should both snap @ the same time.
if (distX < _velX)
x = target.x; // snap & see what happens.

if (distY < _velY)
y = target.y; // snap & see what happens.

// TODO: call your onHitTarget here ...
// Hopefully this shall provide 10x the performance 
// of using Math.sqrt and all the extra multiplications.

Wszystko jest zapisane z pamięci. Nawiasem mówiąc, użyj elementów, które działają - przetestuj to linia po linii, jeśli jesteś w tym nowy. Liczba zmiennoprzecinkowa to liczba w AS3.

Chris
źródło