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!
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..
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:
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.
L'implémentation se fera dans l'IDE FlashDevelop. Construisez votre fichier de projet.
Voir ce guide pour une introduction à FlashDevelop.
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. |
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é;
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;
Les principales utilisations de Vector2D résident dans les fonctions suivantes, qui:
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;
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 ();
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;
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);
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;
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;
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);
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.
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;
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;
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);
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);
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;
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);
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 ();
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);
Enfin, appuyez sur Ctrl + Entrée pour prévisualiser l'animation.
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.