La gravité en action

L'étude des forces est d'un intérêt central dans la dynamique, l'étude des causes du mouvement et des changements de mouvement. Force gravitationnelle est un exemple; c'est ce qui fait que les satellites tournent autour des planètes et que nous restons au sol.

Dans ce tutoriel, nous allons construire une simulation de ce phénomène et pouvoir observer, expérimenter et jouer avec des particules sur la scène..

Parmi toutes les particules générées, une particule principale en attirera d'autres. Au fur et à mesure que ces particules se déplacent vers la principale, les utilisateurs peuvent cliquer sur cette particule principale pour la faire glisser, ce qui leur permet de rediriger leur parcours. Ces particules cesseront de bouger lorsqu'elles entreront en collision avec le bord de la balle principale, mais ne se chevaucheront pas.

La structure de ce tutoriel est organisée de manière à présenter brièvement une théorie en physique avant de présenter la mise en oeuvre de la simulation. Prendre plaisir!


Aperçu du résultat final

Jetons un coup d'œil au résultat final sur lequel nous allons travailler:

Cliquez et faites glisser le grand cercle vert pour le déplacer et observez la réaction des petits cercles bleus..


Étape 1: Force gravitationnelle, formule

Tout d’abord, une préface de physique. La force gravitationnelle attractive entre deux objets quelconques est exprimée par la formule suivante:

F: force d'attraction exercée sur l'objet d'intérêt (p2) par
une particule arbitraire (p1).

g: Constante gravitationnelle

m1: masse de p1

m2: masse de p2

r: distance entre p1 et P2

Prenez note de ce qui suit:

  1. La relation entre gravité et distance: F est inversement proportionnelle au carré de la distance séparant les deux particules. Cela signifie que plus A et B sont proches l'un de l'autre, plus la force d'attraction entre eux est grande et inversement. Si vous doublez la distance, la force diminue au quart de sa valeur initiale.
  2. La valeur de la constante gravitationnelle, G, est scientifiquement 6,67259 x 10-11 N * m2 / kg2. Cependant, 500 remplacera cette valeur dans l'environnement Flash.
  3. Nous pouvons relier la largeur des particules à leur masse. Pour cet exemple, j'ai défini la masse d'une particule comme étant la moitié de son rayon..

Étape 2: Newton 2Dakota du Nord Loi, équation

Pour traduire la force en cinématique, nous devons calculer l'accélération de la particule. La célèbre équation de Sir Isaac Newton est illustrée ci-dessous:

F: la force gravitationnelle s'exerçant sur l'objet d'intérêt (p2)

m: masse d'objet d'intérêt (p2)

une: accélération de l'objet d'intérêt (p2) sous influence de F

Ici, l'implication est qu'une force plus élevée appliquée sur la particule A entraîne une accélération plus élevée (en supposant que sa masse reste la même). Cette accélération va changer la vitesse de la particule.


Étape 3: démarrage du projet

L'implémentation se fera dans l'IDE FlashDevelop. Construisez votre fichier de projet.

  1. Démarrer un nouveau projet, PROJECT> NEW PROJECT?
  2. Sélectionnez dans une fenêtre pop-up, AS3 PROJECT
  3. Nommez votre projet. Dans mon cas, attracteur
  4. Sélectionnez l'emplacement de votre projet

Voir ce guide pour une introduction à FlashDevelop.


Étape 4: Les cours dont vous avez besoin

Il y a 4 classes à créer dans un dossier \ src \: Main.as, Vector2D.as, Ball.as & Math2.as. Il est conseillé de télécharger tous ces fichiers à partir du paquet source et d'essayer de les mapper avec les étapes à suivre pour obtenir une compréhension générale du mécanisme avant de les modifier. Leurs rôles sont exprimés comme suit:

Nom du cours But de l'organisation
Main.as Classe pour créer les balles visuellement et pour joindre une animation aux événements.
Vector2D Classe contenant toutes les fonctions de manipulation de vecteurs.
Ballon Classe qui contient des fonctions pour générer visuellement une balle, implémente la dynamique et la cinématique d'une balle.
Math2 Classe statique contenant une fonction facilitant la randomisation de l'emplacement initial des balles.

Étape 5: Valorisation aléatoire des valeurs

Parlons d'abord de la classe Math2. La fonction ci-dessous aidera à générer un nombre aléatoire dans la plage spécifiée. Accepte deux entrées, limite minimale et limite maximale dans la plage.

 fonction statique publique randomiseBetween (intervalle_min: int, intervalle_max: int): int var intervalle: int = intervalle_max - intervalle_min; var randomized: int = Math.random () * plage + plage_min; retour randomisé; 

Étape 6: Vector2D, Getters et Setters

La majeure partie des mathématiques utilisées se trouve dans Vector2D. Ce tutoriel suppose un niveau de connaissance de l’analyse vectorielle des utilisateurs. Les fonctions ci-dessous sont généralement utilisées pour obtenir et définir les composants vectoriels, plus une méthode pour réinitialiser tous les composants à zéro. Dans tous les cas, si vous êtes inconfortable avec Vectors, visitez un excellent post sur Les vecteurs euclidiens de Daniel Sidhion..

 fonction publique Vector2D (valueX: Number, valueY: Number) this._x = valueX; this._y = valeurY;  public function set vecX (valueX: Number): void this._x = valueX;  function publique get vecX (): Number return this._x fonction publique définie vecY (valueY: Number): void this._y = valueY;  fonction publique get vecY (): Number return this._y fonction publique setVector (valueX: Number, valeurY: Number): void this._x = valueX; this._y = valeurY;  fonction publique reset (): void this._x = 0; this._y = 0; 

Étape 7: Vector2D, Opérations

Les principales utilisations de Vector2D résident dans les fonctions suivantes, qui:

  • obtenir la magnitude du vecteur
  • obtenir l'angle fait par vecteur par rapport à l'origine
  • obtenir la direction vectorielle du vecteur
  • effectuer des opérations vectorielles simples d'addition, de soustraction et de scalaire
    multiplication
 fonction publique getMagnitude (): Number var lengthX: Number = this._x; var lengthY: Number = this._y; return Math.sqrt (lengthX * lengthX + lengthY * lengthY);  fonction publique getAngle (): Number var lengthX: Number = this._x; var lengthY: Number = this._y; renvoyer Math.atan2 (lengthY, lengthX);  fonction publique getVectorDirection (): Vector2D var VectorDirection: Vector2D = new Vector2D (this._x / this.getMagnitude (), this._y / this.getMagnitude ()); renvoyer Vector2D (vectorDirection);  fonction publique minusVector (vector2: Vector2D): void this._x - = vector2.vecX; this._y - = vector2.vecY;  fonction publique addVector (vector2: Vector2D): void this._x + = vector2.vecX; this._y + = vector2.vecY;  fonction publique multiply (scalar: Number): void this._x * = scalar; this._y * = scalaire; 

Étape 8: Dessin au ballon

le Ballon la classe est l'endroit où toutes les opérations intéressantes ont lieu. Pour commencer notre animation, nous devons dessiner une balle et définir plusieurs variables liées à la cinématique et à la dynamique. La fonction pour dessiner une balle est comme ci-dessous:

 fonction privée draw (rayon: numéro, couleur: uint): void graphics.beginFill (color, 1); graphics.drawCircle (0, 0, rayon); graphics.endFill (); 

Étape 9: Variables privées Ball.as

Les différentes variables liées à la cinématique et à la dynamique mentionnées sont les suivantes:

 var_disp privé: Vector2D; // vecteur de déplacement, par rapport à l'origine private var _velo: Vector2D; // vecteur vitesse privé var _acc: Vector2D; // vecteur d'accélération privé var _attractive_coeff: Number = 500; private var _mass: Number;

Étape 10: Initiation à la balle

Comme on appelle le constructeur de la classe Ball, les graphiques sont dessinés. Une fois tirée, la balle sera placée sur la scène de manière aléatoire. Nous allons également définir les variables privées. Toutes les quantités vectorielles seront également initialisées à 0, à l'exception du déplacement mesuré par rapport à l'origine.

 fonction publique Ball (radius: Number = 20, color: uint = 0x0000FF) this.draw (radius, color); this._mass = rayon / 2; // en supposant que la masse est égale à la moitié du rayon this.x = Math2.randomiseBetween (0, 550); this.y = Math2.randomiseBetween (0, 400); this._disp = new Vector2D (this.x, this.y); // définit le déplacement initial this._velo = new Vector2D (0, 0); this._acc = new Vector2D (0, 0); 

Étape 11: Calculer la force attractive

Nous devons calculer la force sous-jacente qui anime nos particules. Devinez quoi, c'est la force de gravitation. La fonction ci-dessous vous aidera à calculer cette force. Notez qu’un plafond est appliqué sur l’accélération à 5. Les composantes horizontale et verticale de la force sont calculées à l'aide de la trigonométrie. l'animation ci-dessus peut aider à comprendre les mathématiques de cette.

 fonction publique get masse (): Number return _mass;  fonction privée getForceAttract (m1: Nombre, m2: Nombre, vec2Center: Vector2D): Vector2D / * calcule la force attractive en fonction de la formule suivante: * F = K * m1 * m2 / r * r * / var numérateur: Number = this._attractive_coeff * m1 * m2; Dénominateur var: Number = vec2Center.getMagnitude () * vec2Center.getMagnitude (); var forceMagnitude: Nombre = numérateur / dénominateur; var forceDirection: Number = vec2Center.getAngle (); // définition d'un plafond si (forceMagnitude> 0) forceMagnitude = Math.min (forceMagnitude, 5); // composante force dérivée, horizontale, verticale var forceX: Number = forceMagnitude * Math.cos (forceDirection); var forceY: Number = forceMagnitude * Math.sin (forceDirection); var force: Vector2D = nouveau Vector2D (forceX, forceY); force de retour; 

Étape 12: Calculer l’accélération

Une fois que le vecteur de force a été obtenu, nous pouvons calculer l'accélération résultante. Rappelles toi, F = ma, alors a = F / m.

 fonction publique getAcc (vecForce: Vector2D): Vector2D // définition de l'accélération due à la force var vecAcc: Vector2D = vecForce.multiply (1 / this._mass); retourner veccAcc; 

Étape 13: Ball.as Calculer le déplacement

Avec l'accélération calculée, nous pouvons calculer efficacement le déplacement résultant.

Rappelez-vous que la force calculée est en fait basée sur le déplacement entre le centre des billes.

 fonction privée getDispTo (ball: Ball): Vector2D var currentVector: Vector2D = new Vector2D (ball.x, ball.y); currentVector.minusVector (this._disp); return currentVector;  fonction publique attractedTo (ball: Ball): void var toCenter: Vector2D = this.getDispTo (ball); var currentForceAttract: Vector2D = this.getForceAttract (ball.mass, this._mass, toCenter); this._acc = this.getAcc (currentForceAttract); this._velo.addVector (this._acc); this._disp.addVector (this._velo); 

Étape 14: Ball.as Implémenter le déplacement

Ensuite, nous pouvons déplacer notre balle à son nouvel emplacement, via la fonction ci-dessous. Notez que le déplacement calculé n'est jamais implémenté directement sur l'emplacement actuel de la balle. Une telle conception doit permettre de vérifier: détection de collision entre les billes.

 fonction publique setPosition (vecDisp: Vector2D): void this.x = Math.round (vecDisp.vecX); this.y = Math.round (vecDisp.vecY); 

Rappelez-vous que la force est basée sur la distance entre les centres. Par conséquent, les billes vont pénétrer et continuer à se déplacer car la force d'attraction est plus élevée quand elles sont plus proches. Nous devons réinitialiser l'accélération et la vélocité à 0 lorsque les billes se touchent l'une l'autre. Cependant, nous devons trouver un moyen de détecter la collision entre deux billes.


Étape 15: Détection de la collision par balle

La collision peut être facilement vérifiée. La séparation entre deux billes ne doit pas être inférieure à la somme de leurs rayons. Voici la fonction de détection de collision:

 fonction publique collisionInto (ball: Ball): Boolean var hit: Boolean = false; var minDist: Number = (ball.width + this.width) / 2; if (this.getDispTo (ball) .getMagnitude () < minDist)  hit = true;  return hit; 

Étape 16: Ball.as calculer déplacer pour repousser

Habituellement, quand une collision a été détectée entre deux balles, leur état se chevauchent. Nous devons nous assurer qu'ils resteront simplement sur le bord et ne se chevaucheront pas. Comment? Nous pouvons déplacer l'une des balles loin de l'autre, mais nous devons d'abord calculer le bon déplacement pour l'ajuster. Voici le calcul du déplacement:

 fonction publique getRepel (ball: Ball): Vector2D var minDist: Number = (ball.width + this.width) / 2; // calcule la distance pour repousser var toBall: Vector2D = this.getDispTo (ball); var directToBall: Vector2D = toBall.getVectorDirection (); directToBall.multiply (minDist); directToBall.minusVector (toBall); directToBall.multiply (-1); retourne directToBall; 

Étape 17: Ball.as met en œuvre le déplacement pour repousser

Après avoir calculé le déplacement correct, nous devons le mettre en œuvre. L'action est comme repousser une des balles. De plus, nous devons faire deux autres commandes supplémentaires. Rappelez-vous, nous avons affaire à un environnement dynamique. Même après avoir réglé le déplacement de la balle sur le bord, l’accélération due à la force et à la vitesse résultante l’anime, provoquant un mouvement indésirable de va-et-vient. Nous devons réinitialiser ces valeurs d'accélération et de vitesse.

 fonction publique repousséePar (balle: balle): void this._acc.reset (); this._velo.reset (); var repelDisp: Vector2D = getRepel (ball); this._disp.addVector (repelDisp); 

Étape 18: Ball.as Animate

Enfin, nous pouvons animer (rendre) notre balle comme si elle était attirée par une autre. Lorsque la collision est détectée, le déplacement sera ajusté de manière à ne pas pénétrer le bord. Cela se produira d’abord pour les balles lorsqu’elles entrent en collision avec le centre, puis pour les balles lorsqu’elles se heurtent les unes aux autres..

 fonction publique animate (centre: Ball, all: Array): void this.attreatedTo (centre); if (collisionInto (center)) this.repelledBy (center); pour (var i: int = 0; i < all.length; i++)  var current_ball:Ball = all[i] as Ball; if (collisionInto(current_ball) && current_ball.name != this.name) this.repelledBy(current_ball);  this.setPosition(this._disp); 

Étape 19: Variables privées Main.as

Passons à notre dernier cours, Principale. La classe principale est générée au début du projet. Les variables privées incluent la balle qui attire toutes les autres et le nombre de balles dans notre présentation Flash..

 var mainBall privé: Ball; private var totalBalls: int = 10;

Étape 20: Main.as Draw Balls

Tout d'abord, nous devrions initialiser les balles. Il y aura un ballon principal qui attirera tous les autres. Les autres sont nommés afin que le référencement puisse être facilement fait plus tard.

 fonction privée createBalls (): void mainBall = new Ball (50, 0x00FF00); this.addChild (mainballle); pour (var i: int = 0; i < this.totalBalls; i++)  var currentBall:Ball = new Ball(); currentBall.name = "ball" + i; this.addChild(currentBall);  

Étape 21: Main.as implémenter une interaction de balle

Ensuite, assignez des événements à la balle principale pour la rendre glissable lorsque vous cliquez dessus et arrêtez-la lorsqu'elle est relâchée..

 fonction privée init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); // point d'entrée createBalls (); mainBall.addEventListener (MouseEvent.MOUSE_DOWN, onMouseDown); stage.addEventListener (MouseEvent.MOUSE_UP, onMouseUp); animateAll ();  fonction privée onMouseUp (e: MouseEvent): void stopDrag ();  fonction privée onMouseDown (e: MouseEvent): void e.target.startDrag (); 

Étape 22: Main.as Animate Balls

Animation de balles qui sont attirées par le principal. Un événement EnterFrame est attribué à chaque balle.

 fonction privée animateAll (): void for (var i: uint = 0; i < totalBalls; i++)  //each ball is pulled by main_ball var current_ball:Ball = this.getChildByName("ball" + i) as Ball; current_ball.addEventListener(Event.ENTER_FRAME, enterFrame);   private function enterFrame(e:Event):void  var allObj:Array = new Array(); for (var i:int = 0; i <= totalBalls; i++)  var current_ball:Ball = this.getChildAt(i) as Ball; allObj.push(current_ball);  e.target.animate(mainBall, allObj); 

Étape 23: Testez le film

Enfin, appuyez sur Ctrl + Entrée pour prévisualiser l'animation.


Conclusion

Pour amener ce tutoriel un peu plus loin, les lecteurs peuvent étendre ce projet en mettant en œuvre d’autres forces linéaires..

Dans tous les cas, les simulations constituent un excellent outil pour proposer des idées difficiles à expliquer par du texte brut et des images dans un environnement de classe de physique, en particulier lorsque l'état de celui-ci change avec le temps..

J'espère que ce petit tutoriel vous aidera d'une certaine manière. Terima kasih ("merci" en Malaisie) d'avoir pris le temps de lire et d'avoir hâte d'entendre les commentaires de ses collègues lecteurs.