En savoir plus sur la cinématique linéaire

Imaginer une animation en termes de vecteurs est intuitif, mais comprendre les mathématiques vectorielles est une douleur. Dans ce didacticiel, j'espère soulager cette douleur et apporter une solution aux problèmes d'animation à l'aide d'une classe Vector2D écrite personnalisée. Nous aborderons quelques concepts fondamentaux de la cinématique linéaire dans l'approche eulérienne: déplacement, vitesse et accélération. Ensuite, nous allons construire une application simple avec elle.


Aperçu du résultat final

Jetons un coup d'œil au résultat final sur lequel nous allons travailler. Cliquez sur le panneau Flash ci-dessous et contrôlez la flèche en appuyant sur les quatre touches directionnelles..


Étape 1: quantité de vecteur

Toutes les quantités vectorielles ont deux composantes: magnitude et direction.


Étape 2: Modification de la quantité de vecteur

Un changement dans les quantités vectorielles fait référence à l'un des cas suivants:

  1. Changement de direction
  2. Changement de magnitude
  3. Changement de magnitude et de direction

Étape 3: Déplacement en tant que quantité vectorielle

Le déplacement, la vitesse et l'accélération sont des quantités vectorielles. Leurs définitions sont les suivantes:

  • Déplacement - Vecteur du plus court chemin pointant de l'origine à la destination. Je définit l'origine comme le point (0, 0) et la destination comme l'emplacement de la particule par rapport à ce point. Fondamentalement, il fait référence au système de coordonnées cartésiennes tel qu’implémenté par Flash..
  • Vélocité - La vélocité est le changement de déplacement dans le temps.
  • Accélération - L'accélération est le changement de vitesse dans le temps.

L'animation ci-dessous montre le déplacement que nous allons implémenter dans Flash plus tard..


Étape 4: Vitesse en tant que quantité vectorielle

La vélocité est illustrée par l'animation ci-dessous. Notez que la vitesse est constante, ce qui signifie que l'accélération est absente dans ce scénario. Si la vitesse est nulle, le déplacement restera constant.


Étape 5: Accélération en tant que quantité vectorielle

L'accélération est illustrée par l'animation ci-dessous. Remarque: la cinématique implique constant accélération. Si l’accélération change avec le temps, elle relève du thème dynamique. La dynamique est l’étude des forces qui font que l’accélération varie dans le temps. Une de ces forces est la gravité et j'ai écrit un article sur l'animation.


Étape 6: Commencez à construire un projectile

Maintenant que vous avez une brève compréhension des grandeurs de la cinématique linéaire et que vous pouvez les associer à des vecteurs, nous pouvons commencer à construire notre classe de projectiles. Nous voudrions que le projectile puisse capturer toutes ces quantités: déplacement, vitesse et accélération - afin qu'il puisse être manipulé sur chaque image..

Vous trouverez ci-dessous les données que nous enregistrerons dans notre classe de projectiles:

 var privé déplacer: Vector2D; velo var privé: Vector2D; accès var privé: Vector2D;

Étape 7: Initialiser le projectile

Lors de l’initiation de cette classe de projectiles, nous initialiserons les variables mentionnées et en tirerons la représentation graphique..

 fonction publique Projectile () // dessine des graphiques this.draw (); // initie toutes les quantités vectorielles displace = new Vector2D (this.x, this.y); velo = nouveau Vector2D (0, 0); acc = nouveau Vector2D (0, 0);  function protégée draw (): void // dessin de la flèche arrow height: Number = 30; var width: Nombre = 60; graphics.beginFill (0x0000FF); graphics.moveTo (0, 0); graphics.lineTo (width / -3, height / -2); graphics.lineTo (width / 2, 0); graphics.lineTo (width / -3, height / 2); graphics.lineTo (0, 0); graphics.endFill (); 

Étape 8: Accesseurs des quantités vectorielles

Ce qui suit sont des accesseurs de nos variables privées - déplacer, velo, acc - dans la classe projectile.

 fonction publique setDisp (mag: nombre, angle: nombre): void displace.redefine (mag, angle);  fonction publique getDisp (): Vector2D return displace;  fonction publique setVelo (mag: nombre, angle: nombre): void velo.redefine (mag, angle);  fonction publique getVelo (): Vector2D return velo;  fonction publique setAcc (mag: nombre, angle: nombre): void acc.redefine (mag, angle);  fonction publique getAcc (): Vector2D return acc

Étape 9: Mise à jour des quantités vectorielles

Lors de l'actualisation de chaque image, nous devons mettre à jour la vitesse (en utilisant l'accélération) et à mettre à jour le déplacement (en utilisant ladite vitesse). Ceci peut être réalisé en utilisant les fonctions suivantes. Pour une explication détaillée sur l’ajout de Vector, visitez ce superbe post de Daniel Sidhon.

 fonction publique applyVelo (): void this.displace = this.displace.add (velo);  fonction publique applyAcc (): void this.velo = this.velo.add (acc);  // met à jour la position de l'image-objet par déplacement. fonction publique animate (): void this.x = this.displace.x; this.y = this.displace.y; 

Étape 10: Mise à jour de l'orientation de Sprite

Nous devrons également mettre à jour l'orientation du Sprite. Ceci peut être réalisé par le rotation propriété de Sprite.

 fonction publique orient (): void this.rotation = Math2.degreeOf (velo.getAngle ()); 

J'ai également mis en place un Math2 classe statique, dans laquelle j'ai écrit une fonction permettant de convertir facilement des unités de degrés et de radians de l'angle.

 Fonction statique publique radianOf (deg: Number): Number return deg / 180 * Math.PI;  fonction statique publique degreeOf (rad: Number): Number return rad / Math.PI * 180; 

Étape 11: La classe principale

Maintenant que nous avons établi nos classes Projectile et Math2, nous pouvons commencer à coder notre classe principale. Nous aurons également besoin d'une classe Vector2D bien qu'une explication détaillée ne soit pas incluse en raison de l'article susmentionné sur Vectors de Daniel Sidhon. Je suppose que les lecteurs comprennent la classe Vector2D après l'avoir lue. Cependant, si des éclaircissements sont nécessaires, n'hésitez pas à me poser des questions..

Tout d’abord, nous devons connaître les variables privées de cette classe.

 private var b1: Projectile; // indicateurs de pression de touches private var UP: Boolean = false; private var DOWN: Boolean = false; private var LEFT: Boolean = false; var privé RIGHT: Boolean = false;

Étape 12: initialisation principale

À l’initialisation de Main, fonction init sera lancé. Cette fonction créera un nouveau projectile et définira sa vitesse initiale. Ensuite, les auditeurs d'événements seront affectés.

 fonction privée init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); // point d'entrée b1 = new Projectile (); stage.addChild (b1); // définition de la vitesse initiale b1.setVelo (5, Math2.radianOf (30)); // définition des écouteurs d'événement b1.addEventListener (Event.ENTER_FRAME, proj_enterFrame); stage.addEventListener (KeyboardEvent.KEY_DOWN, handle_keyDown); stage.addEventListener (KeyboardEvent.KEY_UP, handle_keyUp); 

Étape 13: auditeurs d'événement de clavier

J'ai défini le contrôle utilisateur en appuyant sur les touches fléchées Haut, Gauche, Bas et Gauche. En appuyant sur ces touches et en les relâchant, les variables de drapeau de Main (étape 11) deviennent vraies et fausses. Sur la base de ces indicateurs, les quantités de vecteur seront manipulées sur chaque image. Notez également que j'ai divisé les contrôles en manipulateurs d'axe horizontal et vertical.

 fonction privée handle_keyDown (e: KeyboardEvent): void if (e.keyCode == Keyboard.UP) UP = true; sinon si (e.keyCode == Keyboard.DOWN) DOWN = true; if (e.keyCode == Keyboard.LEFT) LEFT = true; else if (e.keyCode == Keyboard.RIGHT) RIGHT = true;  fonction privée handle_keyUp (e: KeyboardEvent): void if (e.KeyCode == Keyboard.UP) UP = false; sinon si (e.keyCode == Keyboard.DOWN) DOWN = false; if (e.keyCode == Keyboard.LEFT) LEFT = false; else if (e.keyCode == Keyboard.RIGHT) RIGHT = false; 

Étape 14: Écouteurs d'événements EnterFrame

Lors du rafraîchissement de chaque image, le code suivant sera exécuté. C'est long, mais ne t'inquiète pas; viens de lire.

 fonction privée proj_enterFrame (e: Event): void // définir l'accélération var accMag: Number = 0.1; si (UP) b1.setAcc (accMag, Math2.radianOf (-90)); b1.applyAcc ();  else if (DOWN) b1.setAcc (accMag, Math2.radianOf (90)); b1.applyAcc ();  if (LEFT) b1.setAcc (accMag, Math2.radianOf (180)); b1.applyAcc ();  else if (DROIT) b1.setAcc (accMag, Math2.radianOf (0)); b1.applyAcc ();  // décélère lorsque vous appuyez sur rien pour simuler un frottement. if (UP + DOWN + LEFT + RIGHT == 0) var currentVeloMag: Number = b1.getVelo (). getMagnitude (); var currentVeloAng: Number = b1.getVelo (). getAngle (); if (currentVeloMag> 1) b1.setAcc (accMag * -1, currentVeloAng); b1.applyAcc ();  b1.applyVelo (); // restriction de l'image-objet aux limites de l'étape b1.getDisp (). x = Math2.implementBound (0, stage.stageWidth, b1.getDisp (). x); b1.getDisp (). y = Math2.implementBound (0, stage.stageHeight, b1.getDisp (). y); b1.animate (); b1.orient (); 

Étape 15: Mise à jour de la motion

La mise à jour de la motion doit être effectuée dans l'ordre suivant:

  1. Définir une nouvelle accélération en fonction de la pression de l'utilisateur.
  2. En utilisant l'accélération, mettre à jour la vélocité actuelle.
  3. En utilisant la vitesse actuelle, mettre à jour le déplacement actuel.
  4. Affiner le déplacement pour garder l'objet à l'intérieur des limites.

J'ai mis en évidence les codes pour faciliter l'identification de ces étapes.

 fonction privée proj_enterFrame (e: Event): void // définir l'accélération var accMag: Number = 0.1; si (UP) b1.setAcc (accMag, Math2.radianOf (-90)); b1.applyAcc ();  else if (DOWN) b1.setAcc (accMag, Math2.radianOf (90)); b1.applyAcc ();  if (LEFT) b1.setAcc (accMag, Math2.radianOf (180)); b1.applyAcc ();  else if (DROIT) b1.setAcc (accMag, Math2.radianOf (0)); b1.applyAcc ();  // décélère car rien n’est pressé pour simuler un frottement. if (UP + DOWN + LEFT + RIGHT == 0) var currentVeloMag: Number = b1.getVelo (). getMagnitude (); var currentVeloAng: Number = b1.getVelo (). getAngle (); if (currentVeloMag> 1) b1.setAcc (accMag * -1, currentVeloAng); b1.applyAcc ();  b1.applyVelo (); // restriction de l'image-objet aux limites de l'étape b1.getDisp (). x = Math2.implementBound (0, stage.stageWidth, b1.getDisp (). x); b1.getDisp (). y = Math2.implementBound (0, stage.stageHeight, b1.getDisp (). y); b1.animate (); b1.orient (); 

Étape 16: Ralentissement

Vous constaterez peut-être qu'il existe d'autres fonctions insérées entre ces codes en surbrillance. Que sont-ils? L’une consiste à appliquer un autre vecteur pour ralentir notre projectile car l’utilisateur n’appuie sur aucune touche. Ceci est appliqué avant d'ajouter la vitesse à notre déplacement.

 // décélère lorsque vous appuyez sur nothng pour simuler un frottement. if (UP + DOWN + LEFT + RIGHT == 0) var currentVeloMag: Number = b1.getVelo (). getMagnitude (); var currentVeloAng: Number = b1.getVelo (). getAngle (); if (currentVeloMag> 1) b1.setAcc (accMag * -1, currentVeloAng); b1.applyAcc (); 

Étape 17: restez à l'intérieur

La prochaine est de limiter notre projectile à rester toujours sur la scène, sinon il va voler hors de l'écran. Encore, ImplementBound est une fonction que j'ai incluse dans la classe statique Math2. Étant donné une limite supérieure, une limite inférieure et une valeur aléatoire, ImplementBound retournera une valeur qui est dans les limites.

Après avoir appliqué ces contraintes sur notre déplacement (et seulement après), nous actualisons la position du Sprite avec cette valeur de déplacement..

 // restriction de l'image-objet aux limites de l'étape b1.getDisp (). x = Math2.implementBound (0, stage.stageWidth, b1.getDisp (). x); b1.getDisp (). y = Math2.implementBound (0, stage.stageHeight, b1.getDisp (). y);

Étape 18: Orienter le sprite

Avant de laisser ce sprite tel quel, nous devons l’orienter de manière à ce qu’il pointe toujours dans la position qu’il dirige en utilisant function Orient.


Étape 19: Préparez-vous et partez!

Maintenant tout est prêt à partir. Lorsque vous lancez cette pièce en appuyant sur Ctrl + Entrée, vous verrez une flèche qui ralentit progressivement au fur et à mesure qu'elle avance en diagonale sur l'écran. Appuyez sur les quatre touches directionnelles pour déplacer la flèche. Ne vous inquiétez pas de perdre votre flèche. ça va rester dans votre vue.


Conclusion

Cet article devrait vous familiariser avec l’utilisation de vecteurs pour animer des mouvements. Une fois que vous avez compris la cinématique, continuez à lire mon article sur la dynamique. Faites-moi savoir comment ça se passe. Terima Kasih.