2D Tower Defense - Eine Kugel für einen Feind

14

Ich versuche eine gute Lösung für eine Kugel zu finden, um den Feind zu treffen. Das Spiel ist 2D Tower Defense, der Tower soll eine Kugel abschießen und den Feind garantiert treffen.

Ich habe diese Lösung ausprobiert - http://blog.wolfire.com/2009/07/linear-algebra-for-game-developers-part-1/

Der erwähnte Link, um den Ursprung der Kugel und den des Feindes zu subtrahieren (Vektorsubtraktion). Ich habe es versucht, aber es folgt nur eine Kugel um den Feind.

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

Ich kenne Vektoren, bin mir aber nicht sicher, welche Schritte (Vektor-mathematische Operationen) durchgeführt werden müssen, um diese Lösung zum Laufen zu bringen.

Tashu
quelle

Antworten:

11

Ihre Überlegung war perfekt: Verwenden Sie einen Vektor, um von meiner Position zu meinem Ziel zu gelangen. Dies ist der Zweck eines Vektors ; Du hast einfach die Geschwindigkeit vergessen !

Geschwindigkeit ist ein Vektor: eine Geschwindigkeit und eine Richtung. Wenn Sie jedoch vergessen, den Differenzvektor zu normalisieren und ihn mit der Geschossgeschwindigkeit (einem Skalar) zu multiplizieren, sagen Sie im Grunde, dass sich das Geschoss verlangsamt , wenn Sie sich dem Ziel nähern (der Differenzvektor ist klein) . während, wenn Sie weit weg sind, die Kugelgeschwindigkeit größer ist.

Dies ist das zugrunde liegende Problem: Sie müssen sowohl die Richtung als auch die Größe des Vektors berechnen .

FxIII
quelle
Danke fürs Helfen. Ich habe versucht, Skalar zu verwenden, nachdem ich den Differenzvektor berechnet habe. Es sieht so aus, als hätte es funktioniert, aber es sieht nicht gut aus. Ich habe versucht zu sehen, ob ich den Differenzvektor berechne, normalisiere und dann die Geschwindigkeit skaliere. Es sieht jetzt besser aus. Ja, ich glaube, ich brauche die Zielsuchraketen später in diesem Spiel. Danke noch einmal.
Tashu
1
Macht diese Antwort für andere keinen Sinn?
BlueRaja - Danny Pflughoeft
@Fxlll: Ok, ich denke ich sehe was du versuchst zu sagen. Es gibt eine Menge Flusen, die nichts mit der Antwort am Anfang / Ende zu tun haben, und ich war auch verwirrt von deinem Englisch (was ich wahrscheinlich nicht deine Schuld ist) . Ich habe einen Bearbeitungsvorschlag eingereicht, um diese Antwort zu bereinigen.
BlueRaja - Danny Pflughoeft
@BlueRaja - Danny Pflughoeft danke für deine Mühe!
FxIII
7

Wenn sich das Ziel mit gleichmäßiger Geschwindigkeit in eine gleichmäßige Richtung bewegt und Ihr Geschossweg mit gleichmäßiger Geschwindigkeit in einer geraden Linie verläuft, können Sie mithilfe einer quadratischen Gleichung den genauen Schnittpunkt vorhersagen und die Waffe Ihres Turms auf diesen Punkt richten .

Da es eine Gewissheit ist, dass die Kugel ins Schwarze trifft und Sie die genaue Zeit berechnen können, die vom Abschuss bis zum Aufprall vergeht, ist keine Kollisionserkennung erforderlich. Einfach die Waffe abfeuern, die berechnete Zeitspanne abwarten und einen Treffer registrieren.

Hier ist der Pseudocode für die quadratische Gleichung:

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
quelle
Danke für den Pseudocode, ich werde ihn überprüfen, um zu sehen, wie die quadratische Gleichung in dieser Situation funktioniert. Danke noch einmal.
Tashu
Das Problem ist, dass der Benutzer sich auf die Kugel zubewegen und kurz vor dem Treffer der Kugel aus der Spur entkommen kann. Wäre diese Lösung in diesem Fall gut genug?
Martin.
Nein, wie im ersten Satz beschrieben. Dies gilt nicht für alle Spiele, sondern für Spiele, bei denen sich Ziele nur mit einer konstanten Geschwindigkeit bewegen. Konstante Geschwindigkeit bedeutet sowohl Richtung als auch Geschwindigkeit. Beispielsweise kann ein Spiel im Defense Grid-Stil diesen Ansatz verwenden.
Steve H
3

Sie müssen die Position der Objekte vorhersagen, bis die Kugel sie erreicht. Sie können dies unter Verwendung der Geschwindigkeit / Geschwindigkeit des Objekts (hoffentlich konstant;)) und seines Richtungsvektors tun.

Ich bin mir nicht sicher, wie die genaue Formel aussieht, aber ich denke, es ist ungefähr so:

NewPosition = OldPosition + (Geschwindigkeit * DirectionVector);

Wenn Sie einen festgelegten Pfad haben, müssen Sie neu berechnen, wann das Objekt die Richtung ändert. Verwenden Sie diese neue Position als Ihren feindlichen Positionsvektor, und die Kugel sollte auf das Objekt treffen, ohne dass der Zielsucheffekt auftritt. Die Referenzfahrt erfolgt aufgrund der Tatsache, dass sich das feindliche Objekt seit der Berechnung des ursprünglichen Vektors bewegt hat. Es kann immer nur aufholen, wenn sich ein Objekt lange genug in eine Richtung bewegt.

Hoffe das hilft :)

Jay
quelle
3
Oder du betrügst und triffst automatisch und verwendest das sich bewegende Sprite als visuelles Feedback. Oder feuern Sie einfach Ihre Kugeln mit 50000²mph ab.
Jonathan Connell
1

Sie können Quadratwurzel und Potenz von 2 vermeiden.

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.

Es ist alles aus dem Gedächtnis geschrieben. Verwenden Sie im Übrigen die Elemente, die funktionieren - testen Sie sie Zeile für Zeile, wenn Sie neu in diesem Bereich sind. Float ist die Nummer in AS3.

Chris
quelle