Ceci est la deuxième partie de ce tutoriel. Je vais vous montrer comment manipuler le mouvement des particules avec des déflecteurs.
Une connaissance préalable des bases du mouvement et des champs de vecteurs est requise. Je vous recommande vivement de compléter la première partie de ce didacticiel avant de poursuivre..
Jetez un coup d'œil au résultat final sur lequel nous allons travailler. C'est un exemple d'effet de sol, avec des particules qui rebondissent sur le sol.
À peu près comme les champs de gravité, un déflecteur prend en entrée les données de mouvement actuelles d'une particule. Ensuite, le déflecteur écrase le mouvement de la particule avec sa sortie, sauf que la sortie contient maintenant des données de vélocité en plus des données de position. Ainsi, dans l’espace 2D, la sortie d’un déflecteur est un vecteur 4D; les deux premières composantes du vecteur 4D représentent les composantes x et y du vecteur de position (notées X et y), respectivement, et les deux dernières composantes représentent les composantes x et y du vecteur vitesse (noté vx et vy).
Se souvenir du Champ
la classe et la La gravité
action de la première partie de ce tutoriel? Eh bien, la procédure est similaire. Tu crées Déflecteur
objets qui manipulent les mouvements de particules, puis les ajoutent à la Dévier
action, comme vous le feriez ajouter Champ
objets à la La gravité
action. Maintenant, regardons un exemple rapide.
Dans cet exemple, nous allons utiliser le LineDeflector
classe pour créer un effet de particules-rebond sur le sol. Un déflecteur de ligne simule essentiellement une ligne infiniment longue dans un espace 2D, avec un côté espace libre et l’autre côté plein; les particules sont uniquement autorisées dans l'espace ouvert et non autorisées dans l'espace solide. Lorsque des particules viennent du côté de l'espace libre, frappant la ligne, elles rebondissent. le Particle.collisionRadius
propriété, représentant le rayon d'une particule, est prise en compte.
Le déflecteur de ligne utilise un vecteur normal et un point traversé par la ligne dans un espace 2D pour déterminer la ligne. Voici une illustration pour vous donner une meilleure idée.
Créez un document Flash, tracez un cercle de rayon 10, puis convertissez-le en symbole exporté pour ActionScript avec un nom de classe. Cercle
.
Créez un fichier AS pour la classe de document. La classe crée un émetteur et un moteur de rendu. Si vous avez besoin d'un rappel sur l'utilisation de base de Stardust, vous pouvez consulter ce didacticiel..
package import flash.display.Sprite; import flash.events.Event; import idv.cjcat.stardust.common.emitters.Emitter; import idv.cjcat.stardust.common.renderers.Renderer; importer idv.cjcat.stardust.twoD.renderers.DisplayObjectRenderer; public class FloorEffect étend Sprite private var emitter: Emitter; convertisseur de rendu privé: Renderer; fonction publique FloorEffect () emitter = new CircleEmitter (); renderer = new DisplayObjectRenderer (this); renderer.addEmitter (émetteur); addEventListener (Event.ENTER_FRAME, mainLoop); fonction privée mainLoop (e: Event): void emitter.step ();
La classe d'émetteur est indiquée ci-dessous. Il jaillit essentiellement des particules de cercle et les particules sont affectées par un champ de gravité uniforme, pointant vers le bas.
package import idv.cjcat.stardust.common.actions.Age; import idv.cjcat.stardust.common.actions.DeathLife; import idv.cjcat.stardust.common.actions.ScaleCurve; importer idv.cjcat.stardust.common.clocks.SteadyClock; import idv.cjcat.stardust.common.initializers.Life; import idv.cjcat.stardust.common.initializers.Scale; import idv.cjcat.stardust.common.math.UniformRandom; import idv.cjcat.stardust.twoD.actions.Gravity; importer idv.cjcat.stardust.twoD.actions.Move; import idv.cjcat.stardust.twoD.emitters.Emitter2D; import idv.cjcat.stardust.twoD.fields.Field; import idv.cjcat.stardust.twoD.fields.UniformField; import idv.cjcat.stardust.twoD.initializers.DisplayObjectClass; importer idv.cjcat.stardust.twoD.initializers.Position; importer idv.cjcat.stardust.twoD.initializers.Velocity; import idv.cjcat.stardust.twoD.zones.LazySectorZone; import idv.cjcat.stardust.twoD.zones.SinglePoint; Classe publique CircleEmitter étend Emitter2D fonction publique CircleEmitter () super (new SteadyClock (1)); // initializer addInitializer (new DisplayObjectClass (Circle)); addInitializer (nouvelle vie (nouvelle UniformRandom (60, 10))); addInitializer (nouvelle position (nouveau SinglePoint (320, 100))); addInitializer (nouvelle Velocity (nouvelle LazySectorZone (8, 4))); addInitializer (nouvelle échelle (nouvelle UniformRandom (1, 0,4))); addInitializer (nouveau CollisionRadius (10)); // actions addAction (new Age ()); addAction (new DeathLife ()); addAction (new Move ()); addAction (nouvelle ScaleCurve (0, 10)); // champ de gravité var: Champ = nouveau UniformField (0, 0.5); var gravité: Gravity = new Gravity (); gravité.addField (champ); addAction (gravité);
Vous avez maintenant créé un effet avec des particules projetées du centre de la scène et entraînées par la gravité. Voici à quoi ça ressemble:
Étape importante Voir en ligne Ajoutez le code suivant dans le constructeur de l'émetteur. Il crée un déflecteur de ligne, l'ajoute au Déflecteur
action, puis ajoute l'action à l'émetteur, activant ainsi l'effet de déflecteur. Les deux premiers paramètres du constructeur pour LineDeflector
class est la coordonnée d'un point sur la ligne et les deux derniers paramètres sont les composantes x et y du vecteur normal de la ligne. le Deflector.bounce
propriété détermine le "rebondissement" de la ligne, 1 provoquant un rebond complet et 0 signifiant aucun rebond du tout.
// crée un déflecteur de ligne passant par le point (320, 320) et le déflecteur normal (0, -1): Déflecteur = new LineDeflector (320, 320, 0, -1); deflector.bounce = 0,6; var deflect: Deflect = new Deflect (); deflect.addDeflector (déflecteur); addAction (dévier);
Vous pouvez également dessiner une représentation visuelle de la ligne sur la scène pour avoir une meilleure apparence.
Bon, nous en avons fini avec cet exemple. Regardons maintenant notre résultat final.
Étape importante Voir en ligne Dans cet exemple, nous allons utiliser le BoundingBox
déflecteur pour contraindre les particules à l'intérieur d'une zone rectangulaire.
La classe de document reste la même que dans l'exemple précédent, mais nous allons changer la classe d'émetteur. C'est la classe d'émetteur de base de cet exemple. Par rapport à la classe emitter de l'exemple précédent, le SteadClock
est changé en ImpulseClock
pour créer instantanément 20 particules au début, la zone de position passe d’un point unique à une zone rectangulaire qui correspond à la taille de la Rapidité
l'initialiseur est un peu ralenti, la La vie
l’initialiseur est supprimé car nous voulons que les particules restent en permanence sur la scène, la Âge
et DeathLife
les actions sont à leur tour non requises et supprimées, et le ScaleCurve
est également supprimé. Certaines importations sont également ajoutées et supprimées. vous pouvez simplement copier le code ci-dessous pour plus de commodité.
package import idv.cjcat.stardust.common.clocks.ImpulseClock; import idv.cjcat.stardust.common.initializers.CollisionRadius; import idv.cjcat.stardust.common.initializers.Scale; import idv.cjcat.stardust.common.math.UniformRandom; import idv.cjcat.stardust.twoD.actions.Deflect; importer idv.cjcat.stardust.twoD.actions.Move; import idv.cjcat.stardust.twoD.deflectors.BoundingBox; import idv.cjcat.stardust.twoD.deflectors.Deflector; import idv.cjcat.stardust.twoD.emitters.Emitter2D; import idv.cjcat.stardust.twoD.initializers.DisplayObjectClass; importer idv.cjcat.stardust.twoD.initializers.Position; importer idv.cjcat.stardust.twoD.initializers.Velocity; import idv.cjcat.stardust.twoD.zones.LazySectorZone; import idv.cjcat.stardust.twoD.zones.RectZone; import idv.cjcat.stardust.twoD.zones.SinglePoint; Classe publique CircleEmitter étend Emitter2D private var impulseClock: ImpulseClock; fonction publique CircleEmitter () super (impulseClock = new ImpulseClock (20)); impulseClock.impulse (); // initializer addInitializer (new DisplayObjectClass (Circle)); addInitializer (nouvelle position (nouvelle RectZone (0, 0, 640, 400))); addInitializer (new Velocity (new LazySectorZone (3, 2))); addInitializer (nouvelle échelle (nouvelle UniformRandom (1, 0,4))); addInitializer (nouveau CollisionRadius (10)); // actions addAction (new Move ());
Comme dans l'exemple précédent, nous ajoutons maintenant le code suivant dans le constructeur de l'émetteur pour utiliser le Dévier
action, seulement que cette fois nous utilisons la BoundingBox
déflecteur pour contraindre les particules dans une région rectangulaire qui correspond à la taille de la scène.
// deflector var deflector: Deflector = new BoundingBox (0, 0, 640, 400); var deflect: Deflect = new Deflect (); deflect.addDeflector (déflecteur); addAction (dévier);
C'est tout. Rien n'a beaucoup changé, et maintenant nous avons des particules contraintes dans une boîte englobante. Testez le film et vous verrez le résultat.
Étape importante Voir en ligne Nous allons maintenant créer nous-mêmes des déflecteurs personnalisés. Comprenons d'abord le Déflecteur
classe nous sommes sur le point d'étendre.
le Déflecteur
classe est la classe de base pour tous les déflecteurs. Pour créer des déflecteurs personnalisés, vous devez étendre cette classe et remplacer le CalculateMotionData4D ()
méthode, puis retourne un MotionData4D
objet représentant la sortie vectorielle 4D du déflecteur. L’entrée à votre disposition, tout comme la Champ
classe, est inclus dans le Particle2D
objet passé dans la méthode en tant que paramètre. Vous pouvez utiliser ceci Particle2D
objet pour déterminer votre sortie. À propos, si cette méthode retourne un nul
la valeur, la Dévier
l'action suppose que vous ne voulez pas changer le mouvement de la particule actuelle, ignorez la particule, puis passez au traitement de la particule suivante.
Par exemple, le déflecteur suivant ferait pivoter le vecteur vitesse de chaque particule d'un degré dans le sens des aiguilles d'une montre.
package import idv.cjcat.stardust.twoD.geom.Vec2D; import idv.cjcat.stardust.twoD.particles.Particle2D; import idv.cjcat.stardust.twoD.deflectors.Deflector; importer idv.cjcat.stardust.twoD.geom.MotionData4D; Classe publique Rotator extended Deflector fonction protégée override CalculateMotionData4D (particule: Particle2D): MotionData4D var vitesse: Vec2D = new Vec2D (particule.vx, particule.vy); velocity.rotateThis (1); retourne un nouveau MotionData4D (particule.x, particule.y, vélocité.x, vélocité.y);
Dans cet exemple, nous allons étendre la Déflecteur
classer et créer notre propre déflecteur, simulant un tube, qui est essentiellement constitué de deux déflecteurs de ligne prenant en sandwich un espace libre en forme de tube.
Copiez le document Flash, ainsi que le Cercle
symbole et le document du premier exemple. Ici, nous allons créer une autre classe d'émetteur, toujours nommée Cercle émetteur
. Cette fois, l'émetteur émet des particules du centre de la scène et aucun champ de gravité n'est appliqué.
package import idv.cjcat.stardust.common.actions.Age; import idv.cjcat.stardust.common.actions.DeathLife; import idv.cjcat.stardust.common.actions.ScaleCurve; importer idv.cjcat.stardust.common.clocks.SteadyClock; import idv.cjcat.stardust.common.initializers.CollisionRadius; import idv.cjcat.stardust.common.initializers.Life; import idv.cjcat.stardust.common.initializers.Scale; import idv.cjcat.stardust.common.math.UniformRandom; import idv.cjcat.stardust.twoD.actions.Deflect; importer idv.cjcat.stardust.twoD.actions.Move; import idv.cjcat.stardust.twoD.deflectors.Deflector; import idv.cjcat.stardust.twoD.emitters.Emitter2D; import idv.cjcat.stardust.twoD.initializers.DisplayObjectClass; importer idv.cjcat.stardust.twoD.initializers.Position; importer idv.cjcat.stardust.twoD.initializers.Velocity; import idv.cjcat.stardust.twoD.zones.LazySectorZone; import idv.cjcat.stardust.twoD.zones.SinglePoint; Classe publique CircleEmitter étend Emitter2D fonction publique CircleEmitter () super (new SteadyClock (1)); // initializer addInitializer (new DisplayObjectClass (Circle)); addInitializer (nouvelle vie (nouvelle UniformRandom (60, 10))); addInitializer (nouvelle position (nouveau SinglePoint (320, 200))); // stage center addInitializer (new Velocity (new LazySectorZone (8, 4))); addInitializer (nouvelle échelle (nouvelle UniformRandom (1, 0,4))); addInitializer (nouveau CollisionRadius (10)); // actions addAction (new Age ()); addAction (new DeathLife ()); addAction (new Move ()); addAction (nouvelle ScaleCurve (0, 10));
Nous allons maintenant créer notre classe de déflecteurs de tubes. Les détails sont expliqués dans les commentaires.
package import idv.cjcat.stardust.twoD.particles.Particle2D; import idv.cjcat.stardust.twoD.deflectors.Deflector; importer idv.cjcat.stardust.twoD.geom.MotionData4D; Classe publique TubeDeflector. Deflector private var y1: Number; private var y2: Number; fonction publique TubeDeflector (y1: Number, y2: Number) // y2 devrait être plus grand que y2 si (y1> y2) // échange y1 et y2 si y1 est plus grand var temp: Number = y1; y1 = y2; y2 = temp; this.y1 = y1; this.y2 = y2; écrasement de la fonction protégée CalculateMotionData4D (particule: Particle2D): MotionData4D // composants de sortie, initialisée aux données de mouvement d'origine de la particule var x: Number = particule.x; var y: nombre = particule.y; var vx: Nombre = particule.vx; var vy: Number = particule.vy; // calcule le rayon réel de la collection var radius: Number = particle.collisionRadius * particle.scale; // indicateur indiquant si le déflecteur prend effet var var deflected: Boolean = false; si (particule.y < (y1 + radius)) //particle y-coordinate is less than lower limit //set proper new y-coordinate y = y1 + radius; //set flag deflected = true; else if (particle.y > (y2 - rayon)) // la coordonnée y de la particule est supérieure à la limite supérieure // définissez la nouvelle coordonnée y appropriée y = y2 - rayon; // set flag deflected = true; if (dévié) retourne un nouveau MotionData4D (x, y, vx, vy); else // ignore la particule et ne met pas à jour ses données de mouvement return null;
Vous devriez savoir ce que nous allons faire très bien maintenant. C'est vrai, nous allons ajouter le déflecteur à un Dévier
action et ensuite ajouter l'action à l'émetteur. Ajoutez le code suivant dans le constructeur de l'émetteur.
// crée un déflecteur de tube var déflecteur: Deflector = new TubeDeflector (100, 300); var deflect: Deflect = new Deflect (); deflect.addDeflector (déflecteur); addAction (dévier);
Vous pouvez maintenant tester le film. Encore une fois, vous pouvez également dessiner une représentation visuelle du déflecteur sur la scène pour une meilleure apparence.
Étape importante Voir en ligne C'est la fin du tutoriel complet. Dans la première partie, vous avez appris sur les champs gravitationnels. Dans la deuxième partie, vous avez appris le concept de déflecteur et l’utilisation réelle du Dévier
action. En outre, vous avez appris comment étendre la Déflecteur
classe pour créer des déflecteurs personnalisés. Vous pouvez maintenant effectuer une manipulation avancée du mouvement des particules dans Stardust..
Merci beaucoup d'avoir lu!