Pfadfolge mit Asteroiden-ähnlicher Bewegung. Zeit, den Pfad zu vervollständigen

7

Ich lerne gerade, wie das geht, aber es ist am besten, das Problem vorher zu posten. (Posting auf Physics und GameDev, da ihr eure Mathematik kennt)

Es ist ziemlich schwer zu erklären. Dieses spezielle Problem dreht sich um das Problem der Schaffung eines Leitsystems für raketengetriebene Fahrzeuge.
Denken Sie: "Ich möchte, dass das Schiff aus dem Spiel" Asteroids "einem bestimmten Pfad folgt und berechnet, wie viel Zeit die gesamte Reise im Voraus dauern wird."

Ein Fahrzeug hat seine eigenen Eigenschaften wie Masse, lineare und Winkelbeschleunigung. Es kann nur in Vorwärtsrichtung beschleunigen. Auch ein ziemlicher Schmerz in der ... es ist die maximale Verfahrgeschwindigkeit begrenzt.

Hoffentlich klärt das Bild einige Dinge: Geben Sie hier die Bildbeschreibung ein

Das Problem liegt im allerersten Schritt. Das Programm wird gestartet, während sich das Fahrzeug bereits mit zufälliger Geschwindigkeit bewegt und in zufällige Richtung zeigt. Um sich vollständig in Richtung des Zielpunkts zu bewegen, muss sich das Fahrzeug zuerst dem Vektor "U" zuwenden. Dabei bewegt es sich jedoch immer noch, sodass sich der Vektor "U" ändert. Auf dem Bild können Sie sehen, dass sich die Drehrichtung ändern kann, keine Sorge, es ist kein Problem.

Also das Problem. Ich habe versucht, nur Vektormathematik zu verwenden, aber ohne Erfolg, da die Variable, die ich zu berechnen versuche, auf Gleichungen beruht, die diese Variable betreffen. Ich bin zu dumm, um nur die Variable, an der ich interessiert bin, auf eine Seite der Gleichung zu bringen. Ich denke, die Lösung würde eine Funktion der Entfernung vom Fahrzeug zum Objekt im Laufe der Zeit beinhalten.

[Bearbeiten 1]

In deinem Interesse, in Ihrem Interesse. Hier ist der Teil, in dem ich stecken bleibe. Geben Sie hier die Bildbeschreibung ein

Von Anfang an. Wir haben das Fahrzeug auf der Ausgangsposition "A", das mit der Geschwindigkeit "V1" fährt, und das Ziel auf der Ausgangsposition "B" mit der Geschwindigkeit "V2" (besser nur für den Fall)

Daraus können wir den Brennvektor "U" berechnen, an dem wir uns ausrichten müssen, um mit der Geschwindigkeit von "Vmax" auf das Ziel zuzugehen.

Je größer der Winkel zwischen der Überschrift "Cf" des Fahrzeugs und dem Vektor "U" ist, desto länger dauert es, bis sich das Fahrzeug dreht. Das heißt, das Fahrzeug legt beim Wenden mehr Distanz zurück (oberstes Bild). Dies bedeutet, dass sich der Winkel beim Drehen usw. usw. ändert.

Auf dem zweiten Bild in roter Box. oben berechnen wir das Punktprodukt, unten multiplizieren wir die Größen der Vektoren. Da der Cf-Vektor die ganze Zeit die Länge 1 hat, können wir ihn schonen.

Das Wichtigste, wonach ich suche, ist die Variable "t". Derzeit habe ich keine Ideen mehr.

Gabriel Rej
quelle
@GameAlchemist Ich interessiere mich für Ihre Methode. Möchten Sie etwas Zeit für die Ausarbeitung verwenden? Wenn die Leistung in der Simulation besser ist und die Mathematik optimal genug ist, würde ich nichts falsches daran sehen, noch etwas zu approximieren :)
Gabriel Rej
Es scheint ein wirklich komplexes mathematisches Problem zu sein. Ich würde empfehlen, es auf Mathematics Stack Exchange
Nikoliazekter
Welche Spiel-Engine?
Vadim Tatarnikov
@ VadimTatarnikov Einheit
Gabriel Rej
Erste Semplifikation: Da B die Kostengeschwindigkeit V2 hat, setzen Sie das System in eine Referenz, die B als statischen Punkt macht. Dann betrachte V2 = (0,0,0) und newV1 = V1-V2.
dnk drone.vs.drones

Antworten:

1

Ich habe das schon mal gemacht. Die einfachste Methode besteht darin, das Projektil zu simulieren, Punkte entlang seiner Flugbahn aufzuzeichnen und den dem Ziel am nächsten gelegenen Punkt zu notieren. Was ich dann mache, ist, den Ort des Ziels + (Zielgeschwindigkeit * Zeit, die benötigt wird, um den nächsten Punkt zu erreichen *) zu erhalten, um den Ort zu erhalten, an dem es sich befinden würde, wenn das Projektil es erreicht. Alles, was Sie dann tun müssen, ist Math.atan2, die neue Koordinate mit der Koordinate Ihres Schiffes, um den Winkel zu erhalten, in dem Sie sich befinden müssen, um es zu treffen (oder Sie können eine Markierung auf dem HUD an der neuen Position zeichnen, wenn Sie dies bevorzugen).

Für meine Zwecke ist dies effizient genug und kann mehrere Ziele gleichzeitig bearbeiten, ohne dass die Leistung beeinträchtigt wird. Wenn Sie möchten, dass es effizienter ist, multiplizieren Sie einfach die Geschwindigkeit des Projektils und setzen Sie weniger Punkte entlang seiner Flugbahn.

* Beachten Sie, dass die Zeit, die benötigt wird, um den nächstgelegenen Punkt zu erreichen, der Index dieses Punkts im Array ist.

Bearbeiten: Wie gewünscht, finden Sie unten einen groben Pseudocode für das, was ich getan habe. Beachten Sie, dass die Art und Weise, wie ich mein Projektil simuliere, wahrscheinlich anders sein wird, als Sie Ihr Projektil simulieren müssen.

Beachten Sie auch, dass die folgenden Funktionen zum Schiff gehören und 'dies' ein Verweis auf die Schiffsinstanz ist. Dies ist auch eine Art modifiziertes Java: P.

list<Point> targetPoints = new list<Point>();
list<Double> targetRotations = new list<Double>();

//the function you call in your update step:
public void doTargetting(list<Asteroid> targets, int targettingRange) {
    targetPoints.clear(); //reset the list of targets
    targetRotations.clear();

    if(targets.size() == 0)
        return;
    int maxPoints = 50, stepsPerPoint = 3;

    list<Point> mypoints = simulateCurve(maxPoints, stepsPerPoint, myProjectile);
    for(Asteroid a in targets)
    {
        if(distance(a, this) < targettingRange) {
            list<Point> apoints = simulateCurve(maxPoints, stepsPerPoint, a);
            doTargettingFor(a, this, mypoints, apoints);
        }
    }
}

//physics stuff:
public list<Point> simulateCurve(int maxPoints, int stepsPerPoint, GameObject obj) {
    list<Point> points = new list<Point>();
    double velx = obj.velx, vely = obj.vely;
    double accellx = obj.accellx, accelly = obj.accelly;
    double maxSpeed = obj.maxSpeed; //if you want a max speed
    double burnout = obj.burnout; //a point at which the projectile runs out of thruster juice
    double loss = 1 - obj.friction; //velocity loss in each step, because space dust or something?
    double x = 0, y = 0;

    points.add({x, y});

    int spl = 0; //counter for steps per line
    for(int i=0; i<maxPoints*stepsPerPoint; i++) {
        if(burnout != 0 && i < burnout) {
            velx += accellx; 
            vely += accelly;
        }

        velx *= loss;
        vely *= loss;

        double mag = Math.hypot(velx, vely);
        if(maxSpeed != 0 && mag > maxSpeed) {
            double mul = maxSpeed/mag;
            velx *= mul;
            vely *= mul;
        }

        x += velx;
        y += vely;

        spl++;
        if(spl > stepsPerLine) {
            spl = 0;
            points.add({x, y});
        }
    }

    return points;
}

//targetting stuff:
public void doTargettingFor(GameObject a, Ship me, list<Point> mypoints, list<Point> apoints) {
    int closestIndex = 0;
    double closest = MAX_VALUE; //a really really big number
    for(int i=0; i<points.size(); i++) {
        double distance = Math.hypot((apoints[i].x+a.x) - (mypoints[i].x+me.x), (apoints[i].y+a.y) - (mypoints[i].y+me.y));
        if(distance < closest) {
            closest = distance;
            closestIndex = i;
        }
    }

    if(closest < a.radius) //note that this handy little statement checks if you're on target and will hit ;). I used this to change the colour of the marker on the HUD to help you 'lock on' as it were.
    {
    }

    //this bit looks complicated but it really isn't. I'm taking the simulated points of the asteroid and adding it to the asteroid's current coordinates, then doing the same for the projectile
    targetPoints.add({apoints[closestIndex].x + a.x, apoints[closestIndex].y + a.y});
    targetRotations.add(Math.atan2((apoints[closestIndex].y + a.y) - (mypoints[closestIndex].y + me.y), (apoints[closestIndex].x + a.x) - (mypoints[closestIndex].x + me.x)));

}
Merivo
quelle
Möchten Sie hier einen Ausschnitt Ihres Codes veröffentlichen oder etwas, das genau verdeutlicht, wie Sie es gemacht haben?
Majte
1
Nun, in meinem Fall hatte ich die Physik hinter allen Spielobjekten geschrieben, daher war es für mich ziemlich einfach, sie zu simulieren. Ich kann es wohl als Pseudocode zusammenfassen. Geben Sie mir ungefähr eine halbe Stunde Zeit, um es zu schreiben und zu überprüfen.
Merivo
Ok, ich habe es jetzt überprüft und es scheint in Ordnung zu sein.
Merivo
Gut gemacht. Ich mag diesen Ansatz und habe eine ähnliche Implementierung, daher wollte ich ihn hier nicht veröffentlichen, da er das wiederholen würde, was Sie bereits gepostet haben. Vielen Dank!
Majte