Warum bewegt sich mein Objekt bei 45 Grad schneller als bei 90 Grad?

32

Ich habe Objekte in meinem Spiel, die sich um 45 Grad schneller als um 90 Grad bewegen.

Jedes Objekt hat

  • Punktposition (x, y)
  • Vector2D (x, y) Richtung
  • Int Geschwindigkeit

Und was ich während eines Updates mache, ist, dass die neue Position wie folgt berechnet wird:

position.x += direction.x * speed
position.y += direction.y * speed

Wie korrigiere ich das? Ich möchte, dass es sich in jedem Winkel mit der gleichen Geschwindigkeit bewegt.

Jason94
quelle
8
Normalisieren Sie Ihren Richtungsvektor vor der Verwendung. Problem gelöst.
verzögerte
1
Musste Google Normalisierung :) fand diese nützliche Website fundza.com/vectors/normalize/index.html
Jason94
Wenn Sie dieses Objekt mithilfe von Benutzereingaben steuern, müssen Sie die 12,3,6,9-Anweisungen einhalten, wie hier für XNA-Entwickler erläutert: xona.com/2010/05/03.html . Es kann etwas sein, was Sie wollen (wie in einem RPG-Spiel) oder nicht (wie in einem Spiel im Geometry Wars-Stil).
Xonatron
Im alten Spiel Descent war dies ein Feature .
J. Holmes
@ 32bitkid Ja, siehe auch Doom straferunning
Bobobobo

Antworten:

55

Dies kann mit dem Satz von Pythagoras erklärt werden , der die folgende Formel ist:

a² + b² = c²

Wenn Sie sich nach rechts bewegen, verwenden Sie (x: 1, y: 0), was uns ergibt

c² = 1 + 0 = 1
c = sqrt(1) = 1.00

Wenn Sie nach oben und rechts gehen, verwenden Sie (x: 1, y: 1), was uns ergibt

c² = 1 + 1 = 2
c = sqrt(2) = 1.41

Wie Sie sehen, ist die Länge diagonal länger als die Länge auf den Kardinalachsen.

Wie bereits erwähnt, sollten Sie Ihren Richtungsvektor einfach normalisieren. Wenn Sie XNA verwenden, geschieht dies folgendermaßen:

var normalizedDirection = direction;
normalizedDirection.Normalize();
position += normalizedDirection * speed
William Mariager
quelle
Ich gebe dir +1 für deine Hilfe in meiner Frage :)
Martin.
12

Normalisieren Sie Ihren Richtungsvektor vor der Verwendung.

Wie von MindWorX erklärt, kann dies einfach verstanden werden. Wenn Sie sich Sorgen über Ihre Richtungsvektoren machen, die Ihnen möglicherweise Kummer bereiten, stellen Sie sicher, dass es sich um Einheitsvektoren handelt (Größe / Länge von 1).

Length(Vector2(1, 1)) == 1.4142135623730951 // first hint of grief
Length(Vector2(1, 0)) == 1

Vector2(1, 1) * 2 == Vector2(2, 2)
Vector2(1, 0) * 2 == Vector2(2, 0)

Length(Vector2(2, 2)) = 2.8284271247461903 // second hint
Length(Vector2(2, 0)) = 2

Wenn normalisiert:

normal(Vector2(1, 1)) == Vector2(0.707107, 0.707107)
Length(Vector2(0.707107, 0.707107)) == 1 // perfect
gebremster Kaviar
quelle
14
Keine hilfreiche Antwort. Wenn der Fragesteller gewusst hätte, was "Richtungsvektor normalisieren" bedeutet, hätte er die Frage nicht gestellt.
Kristopher Johnson
@KristopherJohnson es war nicht klar, der Fragesteller wusste nicht, wie man einen Vektor normalisiert. Obwohl der Fragesteller einfallsreich genug scheint, dass es sowieso keine Rolle spielt.
Verlangsamter
2
@KristopherJohnson: Wenn der Fragesteller nicht wusste, was "normalisieren Sie Ihren Richtungsvektor" bedeutet, muss er das nur für Google eingeben, den Namen seiner Sprache anhängen und einen Code mit Erklärungen abrufen.
Lie Ryan
6

Wie berechnest du deine Richtung? Wenn 45 Grad sind (1,1), ist es sicherlich schneller als 90 Grad (1,0).

Ich schlage vor, Sie verwenden so etwas:

direction.x = Math.Cos(angleInRadians);
direction.y = Math.Sin(angleInRadians);

Um den Winkel im Bogenmaß zu erhalten, müssen Sie Ihre Gradzahl mit multiplizieren PI / 180oder noch besser mit MathHelper. Z.B.

angleInRadians = 45.0 * Math.PI / 180.0; // first method
angleInRadians = MathHelper.ToRadians(45f); //second method
Blödmann
quelle
6

Jason,

Anstatt drei Objektattribute zu haben,

  • Punktposition (x, y)
  • Vector2D (x, y) Richtung
  • Int Geschwindigkeit

es ist oft viel einfacher, richtung und geschwindigkeit zu einem geschwindigkeitsvektor zu kombinieren. Dann haben Sie nur zwei Attribute,

  • Punktposition (x, y)
  • Vector2D (x, y) Geschwindigkeit

Position wird aktualisiert

Wenn Sie die Position des Objekts aktualisieren müssen, ist dies so einfach wie:

position.x += velocity.x * Δt;
position.y += velocity.y * Δt;

wo Δtist dein Zeitdelta - oder Zeitunterschied - oder Zeitschritt.

Aktualisieren von Position und Geschwindigkeit

Auf diese Weise ist es auch sehr einfach, mit Beschleunigungen umzugehen (z. B. durch Schwerkraft). Wenn Sie einen Beschleunigungsvektor haben, können Sie die Geschwindigkeit und die Position wie folgt zusammen aktualisieren:

position.x += (velocity.x * Δt) + (0.5 * acceleration.x * Δt * Δt);
position.y += (velocity.y * Δt) + (0.5 * acceleration.y * Δt * Δt);

velocity.x += acceleration.x * Δt;
velocity.y += acceleration.y * Δt;

(Dies ist im Grunde die Formel s = vt + ½at² aus Physik 101.)

Eine Geschwindigkeit anwenden

Wenn Sie eine bestimmte Geschwindigkeit in einer normalisierten Richtung anwenden möchten, können Sie die Geschwindigkeit folgendermaßen einstellen:

velocity.x = normalizedDirection.x * speed;
velocity.y = normalizedDirection.y * speed;

Geschwindigkeit ableiten

Und wenn Sie umgekehrt vorgehen müssen - die Geschwindigkeit und Richtung von einem gegebenen Geschwindigkeitsvektor ableiten - können Sie einfach den Satz von Pythagoras oder die .Length()Methode verwenden:

speed = velocity.Length();

Und sobald die Geschwindigkeit bekannt ist, kann die normalisierte Richtung berechnet werden, indem die Geschwindigkeit durch die Geschwindigkeit dividiert wird (wobei darauf zu achten ist, dass keine Division durch Null erfolgt):

if (speed != 0) {
    normalizedDirection.x = velocity.x / speed;
    normalizedDirection.y = velocity.y / speed;
} else {
    normalizedDirection.x = 0;
    normalizedDirection.y = 0;
}
Todd Lehman
quelle