Pourquoi mon objet se déplace-t-il plus vite à 45 degrés qu'à 90 degrés?


32

J'ai dans mon jeu des objets qui se déplacent plus rapidement à 45 degrés puis à 90 degrés.

Chaque objet a

  • Point (x, y) position
  • Direction Vector2D (x, y)
  • Vitesse int

Et ce que je fais lors d’une mise à jour, c’est que le nouveau poste est calculé comme suit:

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

Comment puis-je corriger cela? Je veux qu'il se déplace avec la même vitesse sous n'importe quel angle.


8
Normalisez votre vecteur de direction avant utilisation; problème résolu.
deceleratedcaviar

1
Il a fallu
Jason94

Et si vous utilisez les entrées de l'utilisateur pour contrôler cet objet, veillez à verrouiller les directions 12,3,6,9 comme expliqué ici pour XNA devs: xona.com/2010/05/03.html . Cela peut être quelque chose que vous voulez (comme dans un jeu de rôle) ou non (comme dans un jeu de style Geometry Wars).
Xonatron

dans l'ancien jeu Descent , c'était une fonctionnalité .
J. Holmes

@ 32bitkid Oui, voir aussi Doom straferunning
bobobobo

Réponses:


55

Ceci peut être expliqué avec le théorème de Pythagore , qui est la formule suivante:

a² + b² = c²

Dans votre cas, lorsque vous vous déplacez à droite, vous utilisez (x: 1, y: 0) ce qui nous donne

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

En montant et à droite, vous utilisez (x: 1, y: 1) ce qui nous donne

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

Comme vous pouvez le constater, la longueur en diagonale est supérieure à celle des axes cardinaux.

Comme d'autres l'ont mentionné, vous devriez simplement normaliser votre vecteur de direction. Si vous utilisez XNA, c'est comme ça:

var normalizedDirection = direction;
normalizedDirection.Normalize();
position += normalizedDirection * speed

Je vous donne +1 pour votre aide dans ma question :)
Martin.

12

Normalisez votre vecteur de direction avant utilisation.

Comme expliqué par MindWorX, ceci peut être simplement compris. Si vous vous inquiétez de ce que vos vecteurs de direction peuvent vous causer du chagrin, assurez-vous qu’ils sont des vecteurs unitaires (magnitude / longueur de 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

Si normalisé:

normal(Vector2(1, 1)) == Vector2(0.707107, 0.707107)
Length(Vector2(0.707107, 0.707107)) == 1 // perfect

14
Pas une réponse utile. Si le questionneur savait ce que voulait dire "normaliser votre vecteur de direction", il n'aurait pas posé la question.
Kristopher Johnson

@KristopherJohnson, il n'était pas clair que l'interrogateur ne sût pas comment normaliser un vecteur. Même si le questionneur semble avoir suffisamment de ressources pour que cela n’ait pas d'importance.
deceleratedcaviar

2
@KristopherJohnson: si le questionneur ne savait pas ce que "normaliserait votre vecteur de direction", il lui suffisait de taper cela pour google, d'ajouter le nom de sa langue et d'obtenir un code avec des explications.
Lie Ryan

6

Comment calculez-vous votre direction? Si 45 degrés est (1,1), alors il va certainement être plus rapide que 90 degrés (1,0).

Je vous suggère d'utiliser quelque chose comme ceci:

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

Pour obtenir l'angle en radians, vous devrez multiplier vos degrés avec PI / 180ou même mieux, utilisez MathHelper. Par exemple.

angleInRadians = 45.0 * Math.PI / 180.0; // first method
angleInRadians = MathHelper.ToRadians(45f); //second method

6

Jason

Plutôt que d'avoir trois attributs d'objet,

  • Point (x, y) position
  • Direction Vector2D (x, y)
  • Vitesse int

Il est souvent beaucoup plus facile de combiner la direction et la vitesse dans un vecteur vitesse. Ensuite, vous avez seulement deux attributs,

  • Point (x, y) position
  • Vitesse Vector2D (x, y)

Mise à jour de la position

Lorsque vous devez mettre à jour la position de l'objet, procédez comme suit:

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

Δtest votre delta temporel - ou différence de temps - ou pas de temps.

Mise à jour de la position et de la vitesse

Il est également très facile de gérer l’accélération (par exemple, par gravité). Si vous avez un vecteur d'accélération, vous pouvez mettre à jour la vitesse et la position ensemble comme ceci:

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;

(Ceci est essentiellement la formule s = vt + ½at² de Physics 101.)

Appliquer une vitesse

Si vous souhaitez appliquer une vitesse donnée dans une direction normalisée, vous pouvez définir la vitesse comme suit:

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

Dériver une vitesse

Et si vous devez faire l'inverse - en déduisant la vitesse et la direction d'un vecteur de vitesse donné - vous pouvez simplement utiliser le théorème de Pythagore ou la .Length()méthode:

speed = velocity.Length();

Et une fois que la vitesse est connue, la direction normalisée peut être calculée en divisant la vitesse par la vitesse (en évitant de diviser par zéro):

if (speed != 0) {
    normalizedDirection.x = velocity.x / speed;
    normalizedDirection.y = velocity.y / speed;
} else {
    normalizedDirection.x = 0;
    normalizedDirection.y = 0;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.