Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Déplacer un objet d'après les coordonnées de la souris - Suivre la souris

Compatible ActionScript 3. Cliquer pour en savoir plus sur les compatibilités.Compatible Flash CS3. Cliquer pour en savoir plus sur les compatibilités.Par gnicos (Nicolas Gauville), le 08 mai 2010

Dans ce tutoriel, nous allons utiliser l’ActionScript 3 pour réaliser une balle qui suit la souris de l’utilisateur, comme ceci (il faut survoler le swf pour que la balle puisse suivre le curseur) :

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Ce tutoriel demande peu de connaissances préalables. Pour le suivre confortablement il vous faudra déjà:
  • Savoir comment créer une application Flash
  • Savoir utiliser les outils de dessin de Flash (l'outil “ovale” en particulier)
  • Avoir des notions de base en Actionscript: Les variables et les fonctions

Un autre tutoriel disponible ici vous permettra de réaliser la même chose en utilisant, cette fois, la Programmation Orienté Objet (POO).



Etape 0 : l'idée

Pour qu'un objet (dans ce tutoriel, on prendra un MovieClip) suive la souris, c'est relativement simple : il suffit de faire tendre progressivement les coordonnées de l'objet vers celles de la souris. Ici, on mesurera simplement l'écart entre les deux coordonnées pour ensuite le réduire petit à petit, jusqu'à ce que le MovieClip ait adopté les mêmes coordonnées que le curseur de la souris de l'utilisateur.



Etape 1 : création de la Balle

On va commencer par créer notre balle. Sélectionnez l'outil ovale (touche O) et tracez une balle. Convertissez-la ensuite en symbole, en appuyant sur F8 après avoir sélectionné la balle. Dans la boite de dialogue qui s'affiche alors, donnez-lui un nom (Balle par exemple), et prenez soin de l'aligner au milieu en sélectionnant le carré du milieu dans l'intitulé “Alignement”. Vérifiez également que le type de symbole est bien défini sur “Clip” dans l'intitulé “Type”. Vous devriez donc obtenir ceci :

Une fois ceci fait, vous pouvez valider. Vous devriez donc avoir sur la scène un clip Balle, aligné en son centre. En le sélectionnant, vérifiez qu'il est aligné au centre, et que le repère du clip est donc au milieu de la balle, comme ceci :

De façon à pouvoir accéder simplement au clip en ActionScript, on va lui donner un nom d'occurrence. Sélectionnez la balle, si elle ne l'est plus, et dans l'onglet “Propriétés” indiquez “balle” dans le champ texte ”<Nom de l'occurrence>” comme ceci :

Ceci étant fait, on va pouvoir attaquer la partie ActionScript !



Etape 2 : préparer le terrain en ActionScript

On va d'abord déclarer les variables dont on va avoir besoin :

  1. On va d'abord déclarer une variable latence, qui sera la latence avec laquelle la balle suivra le curseur de la souris. Ainsi, plus la latence sera élevée et plus la balle mettra de temps à rejoindre la souris. Nous n'utiliserons pas de nombres à virgules (pas besoin d'autant de précision, et cela risquerait de ralentir l'exécution), on va donc utiliser une variable de type int. Dans cet exemple, on choisira une latence de 10.
  2. On va ensuite créer deux variables distance_x et distance_y qui prendront pour valeur la distance entre la souris et la balle. Ces variables auront, elles, besoin de précision si l'on veux que le déplacement soit fluide, on utilisera donc, cette fois, des variables de type Number.

On obtient donc ceci :

var latence:int = 10; //La variable latence, de type int, affectée à la valeur 10
//Les deux variables de distance, qu'on déclare pour usage ultérieur
var distance_x:Number;
var distance_y:Number;

On a maintenant les variables dont on aura besoin, on peut passer à la suite !



Etape 3 : rapprocher la balle de la souris

Pour rapprocher la balle du curseur, on va, à chaque frame, regarder l'écart entre la balle et le curseur de la souris, et réduire celui-ci de façon à ce qu'ils se rapprochent progressivement. Pour cela, on utilisera une fonction appelée par l'évènement ENTER_FRAME, qu'on nommera “onEnterFrame” pour plus de clarté. Cette fonction sera appelée à chaque frame (image), plusieurs fois par seconde. Si vous avez définit la cadence de votre animation à 50 images/seconde, la fonction “onEnterFrame” sera exécutée 50 fois par seconde.

Dans cette fonction, on commencera par chercher la distance entre la balle et le curseur de la souris sur les deux axes de la scène, x et y. Pour cela, on utilise les propriétés «stage.mouseX» et «stage.mouseY» qui indiquent la position du curseur de la souris sur la scène, auxquelles on soustrait la position du clip qui doit suivre la souris, et on obtient ainsi la différence de distance entre le clip et le curseur de la souris.

Si vous n'êtes pas familiers du système de coordonnées x et y qui repère les objets sur la scène, vous pouvez lire le début de ce tutoriel.

Avec tout ça, on a donc le code suivant :

var latence:int = 10; //La variable latence, de type int, affectée à la valeur 10
//Les deux variables de distance, qu'on déclare pour usage ultérieur
var distance_x:Number;
var distance_y:Number;
 
//On déclare la fonction onEnterFrame
function onEnterFrame ( e:Event ) : void
{
	//on calcule la distance entre l'objet et le curseur de la souris sur l'axe des x
	distance_x = stage.mouseX - balle.x;
	//on calcule la distance entre l'objet et le curseur de la souris sur l'axe des y
	distance_y = stage.mouseY - balle.y;
}
 
//On demande d'appeller la fonction onEnterFrame lors de l'evenement ENTER_FRAME
addEventListener ( Event.ENTER_FRAME, onEnterFrame );

On connait maintenant la distance à ajouter pour que l’objet rejoigne le curseur de la souris, mais si on veut que l’objet rejoigne progressivement le curseur, on doit éviter de l’ajouter d’un coup, et donc échantillonner le rapprochement de l’objet et du curseur. Pour cela, on va simplement diviser cette distance par la latence avec laquelle on veut que l’objet suive la souris, latence qu’on a justement gardé dans la variable «latence». Pour que l’objet se rapproche progressivement de la souris, on devra donc ajouter ( distance_x / latence ) sur l’axe x et ( distance_y / latence ) sur l’axe y.

On obtient donc le code suivant :

var latence:int = 10; //La variable latence, de type int, affectée à la valeur 10
//Les deux variables de distance, qu'on déclare pour usage ultérieur
var distance_x:Number;
var distance_y:Number;
 
//On déclare la fonction onEnterFrame
function onEnterFrame ( e:Event ) : void
{
	//on calcule la distance entre l'objet et le curseur de la souris sur l'axe des x
	distance_x = stage.mouseX - balle.x;
	//on calcule la distance entre l'objet et le curseur de la souris sur l'axe des y
	distance_y = stage.mouseY - balle.y;
 
	balle.x += distance_x / latence; //on ajoute le décalage divisé par la latence en x
	balle.y += distance_y / latence; //et en y
}
 
//On demande d'appeller la fonction onEnterFrame lors de l'evenement ENTER_FRAME
addEventListener ( Event.ENTER_FRAME, onEnterFrame );

A ce stade, notre script est fonctionnel ! On peut donc maintenant faire qu’un objet suive le curseur de la souris de l’utilisateur. Le .fla correspondant se trouve dans l'archive compressée disponible en bas de page.

Si vous avez encore du mal à comprendre le procédé, et pourquoi la balle se rapproche progressivement du curseur de la souris en rallentissant progressivement, lisez cette explication de Nataly.



Petit plus : restreindre les coordonnées de la Balle

Eviter que la balle sorte de la scène

On sait maintenant comment faire pour que la balle suive la souris, mais dans certains cas, on peut vouloir restreindre les coordonnées de la balle à un certain cadre. Pour cela, il suffit de vérifier que les coordonnées de la balle soient comprises entre l'intervalle des coordonnées du cadre. On a donc à vérifier les inéquations suivantes :

  • x_a_gauche_du_cadre < balle.x < x_a_droite_du_cadre
  • y_en_haut_du_cadre < balle.y < y_en_bas_du_cadre

Si l'on veut, par exemple, que la balle ne sorte pas de l'intervalle [0;400] en X et [0;300] en Y (comme c'est le cas dans l'exemple affiché au début du tutoriel, pour que la balle ne soit pas invisible si la souris est en dehors du fichier swf), on va donc faire :

if ( balle.x < 0 ) // si les coordonnées de la balle en x sont inférieures a 0
	balle.x = 0; // on la remet a 0
else if ( balle.x > 400 ) // si les coordonnées de la balle en x sont supérieures à 400
	balle.x = 400; // on la remet à 400
if ( balle.y < 0 ) // de même en y, avec 0 et 300
	balle.y = 0;
else if ( balle.y > 300 )
	balle.y = 300;

Le code est donc maintenant :

var latence:int = 10; //La variable latence, de type int, affectée à la valeur 10
//Les deux variables de distance, qu'on déclare pour usage ultérieur
var distance_x:Number;
var distance_y:Number;
 
//On déclare la fonction onEnterFrame
function onEnterFrame ( e:Event ) : void
{
	//on calcule la distance entre l'objet et le curseur de la souris sur l'axe des x
	distance_x = stage.mouseX - balle.x;
	//on calcule la distance entre l'objet et le curseur de la souris sur l'axe des y
	distance_y = stage.mouseY - balle.y;
 
	balle.x += distance_x / latence;
	balle.y += distance_y / latence;
 
	if ( balle.x < 0 ) // si les coordonnées de la balle en x sont inférieures a 0
		balle.x = 0; // on la remet a 0
	else if ( balle.x > 400 ) // si les coordonnées de la balle en x sont supérieures à 400
		balle.x = 400;// on la remet à 400
	if ( balle.y < 0 ) // de même en y, avec 0 et 300
		balle.y = 0;
	else if ( balle.y > 300 )
		balle.y = 300;
}
 
//On demande d'appeller la fonction onEnterFrame lors de l'evenement ENTER_FRAME
addEventListener ( Event.ENTER_FRAME, onEnterFrame );

Bien sur, le repère de la balle étant au milieu de celle ci, la moitié de la balle dépassera du cadre lorsque le curseur en sortira. Pour palier à cela, il faut alors ajouter la moitié de la taille de la balle pour rectifier les coordonnées comme ceci :

var latence:int = 10; //La variable latence, de type int, affectée à la valeur 10
//Les deux variables de distance, qu'on déclare pour usage ultérieur
var distance_x:Number;
var distance_y:Number;
 
//On déclare la fonction onEnterFrame
function onEnterFrame ( e:Event ) : void
{
	//on calcule la distance entre l'objet et le curseur de la souris sur l'axe des x
	distance_x = stage.mouseX - balle.x;
	//on calcule la distance entre l'objet et le curseur de la souris sur l'axe des y
	distance_y = stage.mouseY - balle.y;
 
	balle.x += distance_x / latence;
	balle.y += distance_y / latence;
 
	if ( ( balle.x - balle.width/2 ) < 0 ) // si la balle dépasse à gauche de la scène
		balle.x = balle.width/2; // on la colle au côté gauche
	else if ( ( balle.x + balle.width/2 ) > 400 ) // si la balle dépasse à droite de la scène
		balle.x = 400 - balle.width/2;// on la colle au côté droit
	if ( ( balle.y - balle.height/2 ) < 0 ) // de même en haut et en bas
		balle.y = balle.height/2;
	else if ( ( balle.y + balle.height/2 ) > 300 )
		balle.y = 300 - balle.height/2;
}
 
//On demande d'appeller la fonction onEnterFrame lors de l'evenement ENTER_FRAME
addEventListener ( Event.ENTER_FRAME, onEnterFrame );

Ce code produit l'animation affichée en haut de cette page.


Eviter que la balle sorte d'un rectangle donné

Avec un autre intervalle (pour qu'on puisse bien visualiser le cadre), on obtient alors le résultat suivant :

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

On a donc le code suivant :

var latence:int = 10; //La variable latence, de type int, affectée à la valeur 125
//Les deux variables de distance, qu'on déclare pour usage ultérieur
var distance_x:Number;
var distance_y:Number;
 
//On déclare la fonction onEnterFrame
function onEnterFrame ( e:Event ) : void
{
	//on calcule la distance entre l'objet et le curseur de la souris sur l'axe des x
	distance_x = stage.mouseX - balle.x;
	//on calcule la distance entre l'objet et le curseur de la souris sur l'axe des y
	distance_y = stage.mouseY - balle.y;
 
	balle.x += distance_x / latence;
	balle.y += distance_y / latence;
 
	if ( ( balle.x - balle.width/2 ) < 25 ) // si la balle dépasse à gauche du rectangle
		balle.x = 25 + balle.width/2; // on la colle au son côté gauche
	else if ( ( balle.x + balle.width/2 ) > 325 ) // si la balle dépasse à droite du rectangle
		balle.x = 325 - balle.width/2;// on la colle au son côté droit
	if ( ( balle.y - balle.height/2 ) < 25 ) // de même en haut et en bas
		balle.y = 25 + balle.height/2;
	else if ( ( balle.y + balle.height/2 ) > 225 )
		balle.y = 225 - balle.height/2;
}
 
//On demande d'appeller la fonction onEnterFrame lors de l'evenement ENTER_FRAME
addEventListener ( Event.ENTER_FRAME, onEnterFrame );



Sources

Vous pouvez télécharger les sources de ce tutoriel ici : Sources CS3

Conclusion

On a vu comment faire pour qu'un MovieClip suive la souris. Nous verrons plus tard d'autres mouvements possibles en fonction des coordonnées de la souris, voire d'autres objets.

Vous pouvez également voir comment refaire cet effet en utilisant, cette fois, la programmation orienté objet pour rendre ce script plus flexible. Ce tutoriel est disponible ici.