web-dev-qa-db-fra.com

Comment calculer l'angle de rebond?

J'ai joué avec pendant un certain temps, mais je ne peux tout simplement pas le comprendre.

J'ai fait un char qui tire des missiles, et quand les missiles frappent les murs, je veux qu'ils rebondissent, mais je veux qu'ils rebondissent à l'angle droit.

Pour l'instant, je n'ai pas d'obstacles, les missiles rebondissent lorsqu'ils sortent du viewportRectangle que j'ai fait.

La solution que je recherche est-elle assez avancée?

Existe-t-il un moyen relativement simple de le faire?

62
Moulde

Je pense qu'un moyen plus facile de le faire est d'utiliser la vitesse du missile au lieu de calculer les angles. Disons que vous avez un missile qui a xVelocity et yVelocity pour représenter son mouvement horizontalement et verticalement. Ces vitesses peuvent être positives ou négatives pour représenter la gauche, la droite, le haut ou le bas.

  • Si un missile frappe une frontière supérieure ou inférieure, inversez le signe de yVelocity.
  • Si un missile frappe une frontière gauche ou droite, inversez le signe du xVelocity.

Cela gardera le même mouvement dans l'axe opposé.

Emprunter l'image de réponse de ChrisF , disons que le missile commence à la position I.

Angle of Reflection

Le xVelocity et le yVelocity étant tous deux positifs (dans les graphiques 2D, la droite et le bas sont généralement positifs), le missile se déplacera dans la direction indiquée. Disons simplement assigner des valeurs de

xVelocity = 3
yVelocity = 4

Lorsque le missile frappe le mur en position [~ # ~] c [~ # ~] , son xVelocity ne devrait pas changer, mais son yVelocity doit être inversé à -4 pour qu'il revienne vers le haut, mais continue vers la droite.

L'avantage de cette méthode est qu'il vous suffit de garder une trace du xPosition, yPosition, xVelocity et yVelocity d'un missile. En utilisant uniquement ces quatre composants et le taux de mise à jour de votre jeu, le missile sera toujours redessiné à la bonne position. Une fois que vous entrez dans des obstacles plus compliqués qui ne sont pas à angle droit ou qui se déplacent, il sera beaucoup plus facile de travailler avec des vitesses X et Y qu'avec des angles.

66
Bill the Lizard

Vous pourriez penser que parce que vos murs sont alignés avec les axes de coordonnées, il est logique d'écrire un code de cas spécial (pour un mur vertical, annulez la coordonnée x de la vitesse; pour un mur horizontal, annulez la coordonnée y de la vitesse ). Cependant, une fois que le jeu fonctionne bien avec les murs verticaux et horizontaux, la prochaine chose que vous penserez probablement est "qu'en est-il des murs à des angles arbitraires? Il convient donc de réfléchir au cas général depuis le début.

Dans le cas général, supposons que votre missile a une vitesse v et frappe un mur avec une surface normale n .

Missile with vector v about to obliquely hit a wall with surface normal n.

Divisez v en composants u perpendiculaires au mur et w parallèle à celui-ci.

Right-angled triangle with hypotenuse for v, short side u parallel to wall and long side w parallel to wall.

Où:

u = ( v · n / n · n ) n
w = v - u

Ici, v · n est le produit scalaire des vecteurs v et n . Voir le lien pour une explication sur la façon de le calculer. Le produit scalaire n · n est évalué au carré de la longueur de le vecteur normal; si vous gardez toujours vos normales sous la forme de vecteurs unitaires alors n · n = 1 et vous pouvez omettre la division.

Après avoir rebondi, la composante du mouvement parallèle au mur est affectée par le frottement f, et la composante perpendiculaire au mur est affectée par l'élasticité, qui peut être donnée sous la forme d'un coefficient de restitution r.

Ainsi, la vitesse après la collision est v ′ = f w - r u . Dans une collision parfaitement élastique et sans frottement, v ′ = w - u ; c'est-à-dire que le mouvement se reflète sur la normale au point de collision, comme dans le diagramme donné dans la réponse de Bill.

Cette approche fonctionne également de la même façon en trois dimensions.

(Évidemment, c'est une notion très simple de rebond; elle ne tient pas compte de angular momentum ou déformation. Mais pour de nombreux types de jeux vidéo, ce type de simplification est parfaitement approprié.)

188
Gareth Rees

Pour des particules parfaites (& lumière), l'angle de réflexion est égal à l'angle d'incidence, comme illustré par ce diagramme (de commons.wikimedia.org).

Angle of Reflection

Faites une recherche pour "angle de réflexion" (sans les guillemets) dans Google.

C'est un peu plus compliqué quand on prend en compte l'élasticité et les matériaux de l'objet et des obstacles;)

9
ChrisF

J'ai eu ce problème, la seule façon que j'ai trouvée était de séparer les axes de collision!

Essayez-le:

x += velocity * Math.cos(angle * Math.PI /180);
y += velocity * Math.sin(angle * Math.PI /180);

if (x < 0 || x > canvas.width) {
     angle = 180 - angle;   
}
else if (y < 0 ||y > canvas.height) {
     angle = 360 - angle; 
}

J'espère que ceci vous aide!

6
Diogenes Silveira

En marge de la question de physique que vous posez, je recommanderais le livre "Beginning Math and Physics for Game Programmers" de Wendy Stahler. Je l'ai trouvé très utile pour mes projets de programmation de jeux/physique.

Le code qui accompagne le livre est C++ mais si vous connaissez C #, il serait assez facile de faire la conversion.

Avoir un bon!

5
itsmatt

Pas compliqué du tout - pseudo-code:

angleObjectHitWall = a;
bounceAngle = 180-a;

Bien sûr, c'est un calcul très simple, et est totalement hors de propos une fois que vous commencez à prendre en compte des facteurs tels que le matériau, la gravité, les murs qui ne sont pas droits, etc.

3
Yuval Adam

180-a ne fonctionnera pas dans tous les cas, sauf si vous travaillez simplement un rebond sur une surface supérieure lorsque X augmente.

Une direction à suivre est les forums XNA ou récupérez un exemple de code XNA. C'est C # et c'est pour construire des jeux. Je ne dis pas que vous voulez construire vos jeux dans XNA, mais c'est un excellent outil et c'est gratuit.

3
Gregory A Beamer

C'est vraiment une question de physique, donc si vous n'êtes pas physicien (et puisque vous posez cette question, je vais supposer que vous ne l'êtes pas), il faudra beaucoup de lecture et de brainstorming pour bien faire les choses.

Je suggère de lire this wikipedia entry pour avoir une idée de base sur la profondeur de votre question.

Si vous voulez seulement le rendre "plausible", je ne m'inquiéterais pas trop et utiliserais la réponse de Bill the Lizard , cependant si vous voulez pour bien faire, vous aurez toute une aventure. Ne laissez pas cela vous faire peur! Bonne chance!

0
David Božjak