Flash AS3 - Événements personnalisés

De EduTech Wiki
Révision datée du 17 décembre 2013 à 13:14 par Damien Gauthier (discussion | contributions) (→‎Version avec des classes)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à la navigation Aller à la recherche

Cet article est une ébauche à compléter. Une ébauche est une entrée ayant un contenu (très) maigre et qui a donc besoin d'un auteur.

Réalisation simplissime

La façon la plus simple de procéder est d'utiliser une chaîne de caractères coder directement dans les fichiers

import flash.events.Event;

//event listener, à attacher à un objet, mais cet objet peut être "stage" ou "MovieClip(root)"
addEventListener("OK", eventHandler);

function eventHandler(e:Event):void {
  trace(e.type);
}
  
// Il suffit d'ajouter ce code là où on veut déclencher un événement :
dispatchEvent(new Event("OK", true, true));

On peut compliquer (un peu) les choses en définissant le type de l'événement (ici "OK") dans une constante (pour ne pas avoir a se souvenir à chaque fois quelle chaîne de caractère on avait utilisée.

import flash.events.Event;

const MY_EVENT = "OK";

addEventListener(MY_EVENT, eventHandler);

function eventHandler(e:Event):void {
  trace(e.type);
}
  
// Il suffit d'ajouter ce code là où on veut déclencher un événement :
dispatchEvent(new Event(MY_EVENT, true, true));

Dans les deux cas, il renvoi OK.

Réalisation un peu plus complexe avec une classe

On se basera sur la connaissance de la création de classes présenté dans Flash AS3 - Programmer avec une classe.

Il s'agit ici de définir une classe "MyEvent" au dessus de la classe d'événement de base :

package {
  import flash.events.Event;
	
  public class MyEvent extends Event {
    public static const FALSE_EV:String ="événement false in MyEvent class";
    public static const CORRECT_EV:String = "événement correct in MyEvent class";

    // class constructor
    public function MyEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false){
      super(type, bubbles, cancelable);
    }

    // Créer une méthode clone() pour le cas où on voudrait redispatcher l'événement,
    // ca fonctionne sans, mais il semble que cela soit important 
    // pour le "bubbling" de l'événement.
    
    public override function clone():Event{
      return new MyEvent(type, bubbles, cancelable);
    }
  }
}

Ensuite, il vous suffit d'importer la classe MyEvent et de modifier un peu le code précédant

import MyEvent;
import flash.events.Event;

addEventListener(MyEvent.CORRECT_EV, eventHandler);
addEventListener(MyEvent.FALSE_EV, eventHandler);

function eventHandler(e:Event):void {
  trace(e.type);
}

dispatchEvent(new Event(MyEvent.CORRECT_EV, true, true));
dispatchEvent(new Event(MyEvent.FALSE_EV, true, true));

Exemples

Pour cet exemple, le but est que quand on clique sur un des quatre cercles, le score augmente de 1 et le rectangle se déplace.

Pour faire cela sans événement il nous faudrait, soit mettre tout le code dans la Timeline principale (ce qui impose de copier le code sur chaque frame où on veut utiliser ce mécanisme), soit insérer dans le symbole cercle du code qui concerne le rectangle et le score (ce qui va compliquer si on veut d'un coup changer le rectangle en losange par exemple).

Avec des événements, chaque symbole se comporte un peu comme une boîte noire :

  • quand on clique sur le cercle, il nous renvoie un événement "Click sur le cercle" ;
  • pour ajouter 1 au score, on lui envoie l'événement "Score modifié" ;
  • quand le rectangle reçoit l'information "Score modifié", il change de place.

Tout ça se passe tout seul, sans intervention extérieur, la seule chose qu'il faut faire, c'est coordonner les événements par la Timeline principale.


Version simple avec code dans la Timeline

Code du symbole Circ :

/* ce symbole envoie un événement
* CIRC_CLICK quand on clique dessus
*/

const CIRC_CLICK = "Click sur le cercle";
addEventListener(MouseEvent.CLICK, startBubble);

function startBubble(e:Event){	
	var bubbles = true;
	var cancelable = false;
	dispatchEvent(new Event(CIRC_CLICK, bubbles, cancelable));
}

Tout ce que fait Circ, c'est que quand on clique dessus, il envoie un événement "CIRC_CLICK", qui va bubble-up jusqu'à la racine MovieClip(root).


Code du symbole Score :

/* ce symbole réagit à l'événement
* MOD_SCORE quand le score est modifié
*/

var score:int = new int();
const MOD_SCORE = "Score modifié";
addEventListener(MOD_SCORE, addScore)

function addScore(e:Event){				
	score = score+1;
	score_txt.text = "Clicks : "+String(score);
}

Tout ce que fait Score, c'est que quand il reçoit l'événement "MOD_SCORE", il ajoute 1 au score. L'événement continue alors sa route en bubble-up vers le rectangle.


Code du symbole Rect :

/* ce symbole réagit à l'événement
* MOD_SCORE qui bubble depuis le
* symbole score
*/

var oriPos:Number = x;
addEventListener(score.MOD_SCORE, changePos);

function changePos(e:Event) {	
	if(x == oriPos) {
	  x = x-50;
	} else {
	  x = oriPos;
	}
}

Tout ce que fait Rect, c'est que quand il reçoit l'événement "MOD_SCORE" (soit directement soit parce qu'il bubble-up depuis Score), il se déplace. L'événement continue alors sa route en bubble-up vers la racine MovieClip(root).


Code de la Timeline principale (qui coordonne les événements de Circ et Score) :

import flash.events.Event;

addEventListener(circ1.CIRC_CLICK, addScore);
		
function addScore(e:Event){	
	var bubbles = true;
	var cancelable = false;
	rect.score.dispatchEvent(new Event(rect.score.MOD_SCORE, bubbles, cancelable));
}

C'est la partie qui organise les événements. En fait, tout ce qu'elle fait c'est que quand elle reçoit l'événement "CIRC_CLICK" (qui bubble-up depuis le cercle), elle renvoie un événement "MOD_SCORE" au score pour qu'il ajoute 1 et qu'il bubble-up vers le rectangle.


On voit que chaque symbole est spécialisé et ne s'occupe que de "son propre travail", une fois celui-ci terminé il envoie un message (événement) pour prévenir que c'est fait. C'est la Timeline principale qui organise comment les événements se coordonnent.

Du coup, on pourra réutiliser le symbole cercle où on veut, la seule chose qu'il suffit de savoir c'est qu'il renvoie un événement "CIRC_CLICK" quand on clique dessus.

Version avec des classes

Pour plus d'informations sur les classes, voir la page Flash AS3 - Programmer avec une classe.

En fait, le code est quasiment identique à la version simple, il y a seulement 2 différences : l'utilisation du mot clé static et l'import des classes Circ et Score pour pouvoir accéder aux constantes "CIRC_CLICK" et "MOD_SCORE".

Code de la classe Circ :

package  {
	import flash.display.MovieClip;
	import flash.events.MouseEvent;
	import flash.events.Event;
	
	public class Circ extends MovieClip {
		
		/* ce symbole envoie un événement
		* CIRC_CLICK quand on clique dessus
		*/
		public static const CIRC_CLICK = "Click sur le cercle";
		
		public function Circ() {
			// constructor code
		   addEventListener(MouseEvent.CLICK, startBubble);
  		}
		
		private function startBubble(e:Event){			
			var bubbles = true;
			var cancelable = false;
			dispatchEvent(new Event(CIRC_CLICK, bubbles, cancelable));
		}
	}
	
}

Code de la classe Score

package  {
	import flash.display.MovieClip;
	import flash.events.Event;
	
	public class Score extends MovieClip {
		
		/* ce symbole réagit à l'événement
		* MOD_SCORE quand le score est modifié
		*/
		private var score:int = new int();
		public static const MOD_SCORE = "Score modifié";
		
		public function Score() {
			// constructor code
			addEventListener(MOD_SCORE, addScore)
		}
		private function addScore(e:Event){			
		  score = score+1;
		  score_txt.text = "Clicks : "+String(score);
		}
	}
	
}

Code de la classe Rect :

package  {
	import flash.display.MovieClip;
	import flash.events.Event;
	import Score;
	
	public class Rect extends MovieClip {
		
		/* ce symbole réagit à l'événement
		* MOD_SCORE qui bubble depuis le
		* symbole score
		*/
		
		var oriPos:Number = new Number();
		
		public function Rect() {
			// constructor code
		 oriPos = x;
		 addEventListener(Score.MOD_SCORE, changePos);
		}
		private function changePos(e:Event) {			
		  if(x == oriPos) {
			  x = x-50;
		  } else {
			  x = oriPos;
		  }
		}
	}
}

Code de la classe DocumentClass :

package  {
	import flash.display.MovieClip;
	import flash.events.MouseEvent;
	import flash.events.Event;
	import Circ;
	import Score;

	public class DocumentClass extends MovieClip {
		
		public function DocumentClass() {
			// constructor code
			addEventListener(Circ.CIRC_CLICK, addScore);
		}
		
		function addScore(e:Event){			
			var bubbles = true;
			var cancelable = false;
			rect.score.dispatchEvent(new Event(Score.MOD_SCORE, bubbles, cancelable));
		}
	}
	
}

Références