2016-05-20 17 views
2

Ich werde versuchen, damit sehr beschreibend zu sein. Ich bearbeite gerade ein Spiel und das Szenario ist ein 3D-Bereich.Langsam einen Anfangswinkel bewegen, bis er einen Endwinkel erreicht

Ich habe einen Anfangswinkel, geschrieben als Richtungsvektor, und einen anderen Vektor, der verschiedene Koordinaten hat. Wie wir wissen, ist der Winkel zwischen zwei Vektoren durch die Formel: Theta = ACos (DotProduct (vec1, vec2)/(VectorLength (vec1) * VectorLength (vec2)))

Also lassen Sie uns das Szenario beschreiben: Ich programmiere gerade eine Art stationäre Waffe, eine Sentry Gun, dieses Ding bewegt langsam seinen "Kopf" und schießt Geschossen auf Feinde. Dieses Ding mit der Winkeldrehung ist mein Problem.

Stellen wir uns das vor: Ich habe meine Sentry Gun auf einem leeren 3D-Bereich, und ein "Feind" spawnt drüben. Ich kann momentan den Richtungsvektor des Sichtwinkels meiner Wache und den Richtungsvektor zwischen meiner Wache und dem Spieler bekommen. Lassen Sie uns raten, dass der Trennungswinkel bei Verwendung der beschriebenen Formel 45 Grad beträgt. Meine Sentry Gun denkt (ruft eine Funktion) alle 0,1 Sekunden, und ich möchte seinen Kopf bewegen 5 Grad bei jeder Denkfunktion, bis es den Spieler erreichen (dh beide Vektoren sind fast gleich), und das bedeutet, es wird erreiche den Spieler (wenn der Spieler auf seiner Position bleibt ...) in 0.9 Sekunden (5 Grad von 45)

Wie kann ich den Sichtwinkel der Sentry langsam bewegen, bis sie ein Ziel erreicht? In 2D ist leicht, aber ich weiß, ich kämpfe mit einem 3D-Szenario, und ich bin derzeit damit verloren.

Jede Hilfe wäre willkommen, und über die Codierung werde ich mit einem Pseudocode dankbar sein. Vielen Dank! (Und sorry für mein Englisch)

+0

Wenn Sie dies in 2D lösen können, können Sie es in 3D lösen, indem Sie die dritte Koordinate ignorieren, die Sie in Ihren 2D-Formeln verwenden möchten, sofern sie nicht in drei Richtungen rotiert. – rcdmk

+0

Um es langsam rotieren zu lassen, können Sie eine Beschleunigungsformel verwenden: 'position = currentPosition + (finalPosition - currentPosition)/easingFactor', wobei' easingFactor' eine ganze Zahl ist, die die Verzögerung definiert. – rcdmk

+0

Sie wollen den Vektor berechnen, der normal zu der Ebene ist, die ** vec1 ** und ** vec2 ** enthält - dies definiert die Achse, um die Sie den Sichtlinienvektor der Sentry-gun drehen werden. Die Formel, um eine Rotation (von etwa 5 ° **) um einen beliebigen 3D-Vektor durchzuführen, ist etwas kompliziert und wird überall im Web erklärt. Zum Beispiel: [hier] (http://inside.mines.edu/fs_home/gmurray/ArbitraryAxisRotation/). Wenn Sie jedoch den Winkel nicht benötigen, um zwischen ** vec1 ** und ** vec2 ** linear zu variieren, würde eine fudged-Lösung wie @ rcdmk's ausreichen, die linear variierenden Koordinaten anstelle des Winkels. –

Antwort

1

Was Sie brauchen, ist SLERP genannt - sphärische lineare Interpolation

Ihr Startrichtungsvektor p0 ist, Ziel Richtung p1, Omega ist Ihr Theta und t Parameter variiert im Bereich 0 ..1 mit benötigt Schritt

Delphi Beispiel für 2D-Fall (es ist leicht zu kontrollieren)

var 
    p0, p1: TPoint; 
    i, xx, yy: Integer; 
    omega, InvSinOmega, t, a0, a1: Double; 
begin 
    P0 := Point(0, 200); 
    P1 := Point(200, 0); 
    omega := -Pi/2; 
    InvSinOmega := 1.0/Sin(omega); 
    Canvas.Brush.Color := clRed; 
    Canvas.Ellipse(120 + P0.X, 120 + P0.Y, 120 + P0.X + 7, 120 + P0.Y + 7); 
    Canvas.Ellipse(120 + P1.X, 120 + P1.Y, 120 + P1.X + 7, 120 + P1.Y + 7); 

    for i := 1 to 9 do begin 
    t := i/10; 

    a0 := sin((1 - t) * omega) * InvSinOmega; 
    a1 := sin(t * omega) * InvSinOmega; 
    xx := Round(P0.X * a0 + P1.X * a1); 
    yy := Round(P0.Y * a0 + P1.Y * a1); 

    Canvas.Brush.Color := RGB(25 * i, 25 * i, 25 * i); 
    Canvas.Ellipse(120 + xx, 120 + yy, 120 + xx + 9, 120 + yy + 9); 
    end; 

enter image description here

+0

Jesus, das ist wunderbar. Habe das vorher nicht bemerkt. Schlimme Sache ist, ich bin ein bisschen verwirrt damit. Ich sollte Slerp() auf jede Koordinate anwenden? Bedeutung .. sowas wie ReturnVector.x = Slerp (Start.x, Ende.x, 0.5/* Beispiel * /) ReturnVector.y = Slerp (Start.y, Ende.y, 0.5) ReturnVector.z = Slerp (Start.z, End.z, 0.5) ? – PM32

+0

Ja, Sie haben Recht. Aber es wäre besser, Koeffizienten einmal für gegebenes t zu berechnen und sie auf jede Koordinate anzuwenden – MBo