Effets 3D
Hier je surfais sur la toile, à la recherche d'informations pour la création d'un moteur 3D, et je suis tombé sur quelques effets sympa, que j'ai essayé de reproduire.

Voila ce que l'on va apprendre à réaliser dans ce tutorial : (Il est bien évident qu'une fois le principe compris, c'est a vous de l'exploiter pour l'améliore)


Note : Ce tutorial est destiné au utilisateurs de Flash ayant un minimum de base en ActionScript, je ne détaillerai donc pas tout.


Etape 1 : Création du document.

1) Créer un nouveau document flash : Fichier => nouveau => document Flash.

2) Modifier les propriétés du document : Modification => document (ctrl+j).
Modifier les dimensions (200px/200px) et la couleur de font (noir).

3) Enregistrer votre document. (sa peut paraître idiot comme instruction mais c'est une excellente habitude a prendre croyez moi. 7)

Voila l'étape la plus difficile est fini.................................C'est un blague bien sur. 11


Etape 2 : Création du clip.

1) Créer un nouveau movieClip : Insertion => Nouveau Symbole (ctrl+F8).
Puis modifier les propriétés comme ci-dessous :

Note : L'identifiant nous servira plus tard pour créer des copie du clip sur la scène via l'Action Script.

2) Cliquer sur la première image du scénario (Toujours dans la clip 'cercle'.) :

Puis dessiner un cercle. (Couleur du centre : gris, et couleur des contours : blanc.)
Note : Pour dessiner un cercle parfait il faut utiliser l'outil 'oval' (O) et maintenir enfoncer la touche 'maj'.
Enfin, modifier ses dimensions (H : 50px / L : 50px), et ses coordonnées, pour que celui-ci se trouve centré (X : -25px / Y : -25px).
Pour cela utiliser l'outil de sélection et double-cliquer sur le cercle que vous venez de dessiner.

Faites apparaître le panneau des propriétés (Si ce n'est pas déjà fait 7) et modifier les comme sur l'image.


3) Insérer une 2ème image-clef (Encore et toujours dans le clip 'cercle'), dans laquelle modifier la couleur de font du cercle. (rouge par exemple.)


4) Insérer un nouveau calque.

Puis cliquer sur la première image de celui-ci, et ajouter le code suivant dans la fenêtre 'action' :

code :
stop();
 


5) Encore une fois il est important de sauvegarder votre travail. (On n'est jamais à l'abri d'un pépin, supposez qu'un papillon battes des ailles, et qu'un ouragan se déclenche sur votre ville, provoquant une explosion de la centrale nucléaire la plus proche, et la paf ! (le chien 12) plus de courant.)
Hum, hum, bon d'acore l'exemple est bidon 11 (Surtout pour les utilisateurs d'ordinateur portable 11) mais c'était pour vous pousser a sauvegarder régulièrement !!!


Etape 3 : Le code.

1) Voila tout les éléments on été crée, il ne nous reste plus qu'à nous attaquer à la partie la plus 'difficile' de ce tuto : Le code.
En effet nous n'allons pas crée un véritable moteur 3D (Ce qui, entre nous, est au delà de mon niveau 1) mais plutôt d'en simuler un.
Tout notre code sera placé sur la première image du scénario de la scène principale.

2) On commence par créer quelques variables sur lesquels va se baser notre animation.
code :
var profondeur:Number = 1000;
var largeur:Number = 200;
var hauteur:Number = 200;
var centre_x:Number = 100;
var centre_y:Number = 100;
var frein:Number = 5;
 

Ici on veux que l'animation prenne toute la taille du document, et que son centre soit aussi le centre de notre document.
Je vous rappel que sur la scène principale, le point de coordonner (0;0) est le coin supérieur-gauche de votre document.
La variable 'profondeur' va être l'une des base les plus importante de notre 'simulation' d'effet 3D.
Nous verrons plus tard l'utilité de la variable 'frein'. (Qui ne porte pas se nom par hasard vous vous en doutez14)

3) On créer une liste de noms, vous pouvez les remplacer par n'importe quoi bien évidement (Ce seront les mots qui apparaitront dans les cercle) :
code :
var tab_nom_1:Array = Array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
 


4) Maintenant nous allons créer une fonction qui crée et place nos occurrences (les copies) du clip 'cercle' de la bibliothèque :

On créer la fonction 'creer_btns' à laquelle on passe 2 paramètres,
Le premier, 'chem1' sera l'adresse du clip conteneur de notre animation, dans notre exemple celle-ci aura pour valeur '_root' c'est à dire la racine de notre animation.
Le deuxième 'tab_nom' est un tableau contenant des noms. (Comme sont nom l'indique 5.)
code :
function creer_btns(chem1:MovieClip, tab_nom:Array):Void {
// les insctructions de la fonction
}
 
*

Note : En programmation, Il faut toujours essayer de nommer les variables judicieusement, pour qu'au premier coup d'œil on sache vaguement ce qu'elles contiennent, ainsi notre variable 'tab_nom' et le diminutif de 'tableau_de_noms', ce qui se passe d'explications.

Ensuite on créer une boucle 'For' qui va créer autant de clips que de lignes dans le tableau 'tab_nom'. (Pour obtenir le nombre de ligne on utilise la méthode : monTableau.length)
code :
var taille:Number = tab_nom.length;
for (var i:Number=0 ; i<taille ; i++) {
// mes insctructions
}
 


On va maintenant on créé une variable qui nous servira à contenir le niveau de notre clip, celle-ci contiendra un nombre entre 1 et la valeur de la variable 'profondeur'. (1000 dans notre cas.)
Pour cela on utilise la méthode 'Math.random()' qui nous renvoi un nombre à virgule entre 0 et 1 que l'on multiplie par la valeur de la variable 'profondeur'. Et pour obtenir un nombre entier on utilise la méthode 'Math.round()' qui arrondi notre nombre a l'entier le plus proche.
code :
var var_profondeur:Number = Math.round(Math.random()*profondeur);
 


On créer un clip 'conteneur' vide, que l'on nomme en fonction de 'i'. (si i=0 le clip sera nommé 'clip0', si i=1 => 'clip1' etc...)
code :
chem1.createEmptyMovieClip("clip"+i, var_profondeur);
 

Note : On remarque l'utilisation de 'chem1.' avant l'utilisation de la méthode de création du clip, cela signifie que l'on veux que le clip soit créé à l'intérieur du clip 'chem1' qui je vous le rappel est l'un des paramètres envoyé à la fonction. (Dans notre cas ce sera '_root'.)

Lors de la création dynamique de plusieurs clips en fonction d'une variable la modification des propriétés de ceux-ci nécessite de connaitre leur nom. Ce qui a première vue n'est pas si facile que sa.
Ex : Soient plusieurs clips "clip+i", si i=5, on veux donc travaille uniquement sur le clip 'clip5', il est bien évident que l'on ne peut pas écrire "clip"+i._x (_x retourne l'abscisse du clip). Pour cela on utilisera la syntaxe suivante clipConteneur["clip"+i]. En lisant cette ligne Flash travaillera sur un seul et unique clip (si i=5 alors il traduira cette ligne par clipConteneur.clip5).
Mais cette notation est lourde, pour simplifier l'écriture du code on va donc créer une variable raccourci :
code :
var chem2:MovieClip = chem1["clip"+i];
 


On va maintenant créer plusieurs variables incluse dans chaque clips.
Les 2 première sont les positions verticale et horizontale des clips quand ils seront au premier plan, on veux donc une valeur entre -largeur/2 et +largeur/2 (idem avec la variable 'hauteur').

Pourquoi ne pas prendre une valeur entre 0 et 'largeur' pour faire plus simple ?

C'est une simple question de représentation mentale, souvenez vous on a définie un centre (avec les variable centre_x et centre_y) on calcule donc les coordonnées des clips en fonction de ce centre.
On doit aussi enregistrer la profondeur du clip. (Puisque l'on aura besoin de la récupérer pour la faire varier.)
Enfin la dernière, nous sert juste à enregistrer la valeur actuel de 'i' (Elle nous sera utile pour récupérer les valeurs des variables du clip sur lequel on a cliquer.)
code :
chem2.var_x = Math.round(Math.random()*largeur-largeur/2); 
chem2.var_y = Math.round(Math.random()*hauteur-hauteur/2); 
chem2.var_niv = var_profondeur; 
chem2.i = i;
 


Enfin on positionne le clip en fonction du centre et de ses coordonnées calculer plus haut.
code :
chem2._x = centre_x+chem2.var_x;
chem2._y = centre_y+chem2.var_y;
 


Maintenant que l'on a crée les variables et positionné le clip, il faut le remplir avec quelque chose. (Puisque voir se déplacer des clip vide, entre nous, c'est un peut difficile 11.)
On va donc y attacher le clip 'cercle' créé à l'étape 2, ainsi qu'un champs texte, dans lequel on va écrire la valeur de la ligne 'i' du tableau 'tab_nom'. (Qui je vous le rappel contient des nom)
code :
chem2.attachMovie("cercle", "cercle", 1); 
chem2.createTextField("texte", 2, -10, -10, 20, 20); 
chem2.texte.text = tab_nom[i]; 
chem2.texte.selectable = false;
 

Note : La propriété 'selectable' nous indique si le champ texte est sélectionnable, par défaut elle est égale à 'True' (vrai en anglais) on la place donc sur 'False' (faux en anglais aussi 5).
Note 2 : La première ligne d'une liste se récupère via l'instruction monTableau[0], or justement cela tombe bien, notre boucle 'For' fait démarrer la variable 'i' a 0

Bon les clips sont créés, mais il on tous la même taille (Logique ce sont des copies parfaites.) et vous serez (j'espère) d'accords avec moi que pour donner un effet d'éloignement ce n'est pas le top 5.
On va donc arranger cela en modifiant les propriétés '_xscale' et '_yscale' des clips. (Elle modifient le % de la taille, par défaut elle sont à 100(%).)
code :
chem2._xscale = Math.ceil(chem2.var_niv/(profondeur/100)); 
chem2._yscale = Math.ceil(chem2.var_niv/(profondeur/100));
 

Note : 'chem2.var_niv' varie entre 0 et la valeur de la variable profondeur, il faut donc divisé cette valeur par profondeur/100 pour obtenir une valeur entre 0 et 100

Maintenant il reste une étape à initialiser, c'est les actions à exécuter quand on clic sur le clip :
On déplace la tête de lecture de ce clip sur la deuxième image. (Le cercle à fond rouge dans notre cas.)
Puis on supprime la temporisation que désigne la variable 'interval' pour éviter de créer 2 fois une même temporisation. (Ce qui aurai pour effet de doubler la fréquence d'exécution de la fonction temporisé.)
Puis on recréer une temporisation de la fonction 'deplacement' tout les 40 millisecondes à laquelle on envoi 3 paramètres. ('chem1' pour l'adresse du clip conteneur; Le numéro d'index du clip sur lequel on a cliquer; et enfin la taille du tableau 'tab_nom', soit le nombre de clips)
code :
chem2.onRelease = function():Void { 
        this.cercle.gotoAndStop(2); 
        clearInterval(inteval); 
        inteval=setInterval(deplacement,40,chem1,this.i,tab_nom.length); 
};
 



Récapitulatif de la fonction créé :
code :
function creer_btns(chem1:MovieClip, tab_nom:Array):Void {
        var taille:Number = tab_nom.length;
        for (var i:Number=0; i<taille; i++) {
                var var_profondeur:Number = Math.round(Math.random()*profondeur);
                chem1.createEmptyMovieClip("clip"+i, var_profondeur);
                var chem2:MovieClip = chem1["clip"+i];
                chem2.var_x = Math.round(Math.random()*largeur-largeur/2);
                chem2.var_y = Math.round(Math.random()*hauteur-hauteur/2);
                chem2.var_niv = var_profondeur;
                chem2.i = i;
                chem2._x = centre_x+chem2.var_x;
                chem2._y = centre_y+chem2.var_y;
                chem2.attachMovie("cercle", "cercle", 1);
                chem2.createTextField("texte", 2, -10, -10, 20, 20);
                chem2.texte.text = tab_nom[i];
                chem2.texte.selectable = false;
                chem2._xscale = Math.ceil(chem2.var_niv/(profondeur/100));
                chem2._yscale = Math.ceil(chem2.var_niv/(profondeur/100));
                chem2.onRelease = function():Void {
                        this.cercle.gotoAndStop(2);
                        clearInterval(inteval);
                        inteval=setInterval(deplacement,40,chem1,this.i,tab_nom.length);
                };
        }
}
 


5) On créer une deuxième fonction prévu pour être exécutée en boucle pour simuler notre effet 3D : la fonction 'deplacement'.
On a vue dans la fonction 1 que l'on avait besoin d'envoyer 3 paramètres important à la fonction 'deplacement', il faut donc crée des variables réceptrices.
code :
function deplacement(chem:MovieClip, var_i:Number, nbr:Number):Void {
// instructions
}
 


La première étape consiste à récupérer le chemin pour accéder aux variables du clip sur lequel on a cliquer, pour cela aucun problème puisque l'on a pensé à envoyer la valeur de la variable 'i' du clip sur lequel on a cliquer.
code :
var chem1:MovieClip = chem["clip"+var_i];
 


A ce niveau une petite vérification s'impose, il faut regarder si le clip est arriver au premier plan, c'est a dire que sont niveau est maximal. Si c'est le cas on supprime la temporisation 'interval'.
code :
if (chem1.var_niv != profondeur) {
        // instruction
} else { 
        clearInterval(inteval); 
}
 


Si le clip sur lequel on à cliquer n'est pas au premier plan alors il faut déplacer tout les clips, pour cela je vous propose de crée un effet de vitesse qui ralentie.
Je m'explique, on calcul la distance restante à parcourir, puis on demande au clip d'en parcourir la moitié.
A la prochaine exécution de la fonction on lui demande de faire pareil, mais comme la distance qu'il restera a parcourir a été diviser par 2 le clip avancera 2 fois moins vite, et ainsi de suite.
Si on applique cette méthode telle quelle, le clip n'arrivera jamais à destination, en effet il parcourra toujours la moitié de la distance restante, pour palier a ce petit problème de logique mathématique (Qui peut donner mal à la tête 11) on utilisera la méthode 'Math.ceil()' qui nous renvoi l'arrondi supérieur.
Le déplacement du clip se fera donc toujours d'un nombre entier, et quand la distance restante sera inférieur à 1 alors le clip arrivera à la position final
C'est ici qu'apparaît l'utilité de la variable 'frein', c'est elle qui va fixer le % de chemin restant à parcourir. (frein=2, la moitié; frein=3, le tiers, etc...)
code :
var vitesse:Number = Math.ceil((profondeur-chem1.var_niv)/frein); 
var vitesse_x:Number = Math.ceil(chem1.var_x/frein); 
var vitesse_y:Number = Math.ceil(chem1.var_y/frein);
 


Une fois les vitesses calculées, il faut modifier les variables et les propriétés des clips, on créer donc une boucle 'For' pour traiter tout les clips (Le nombre de clips est contenu dans la variable 'nbr').
code :
for (var i:Number=0; i<nbr; i++) {
// instructions
}
 


On édite les variables des clips. (On créer aussi un autre raccourci toujours pour simplifier l'ecriture du code.)
code :
var chem2:MovieClip = chem["clip"+i]; 
chem2.var_niv += vitesse; 
chem2.var_x -= vitesse_x; 
chem2.var_y -= vitesse_y;
 


Comme l'on augmente la valeur de la variable de niveau de tout les clip, il faut faire en sorte que les clip qui dépassent le premier plan soient remis en arrière plan. (On en profite aussi pour replacer la tête de lecture du clip 'cercle' sur l'image 1.)
code :
if (chem2.var_niv>profondeur) { 
        chem2.cercle.gotoAndStop(1); 
        chem2.var_niv -= profondeur; 
}
 


Il ne nous reste plus qu'à déplacer les clips :
Modifier sont niveau :
code :
chem2.swapDepths(chem2.var_niv);
 

Modifier sa taille :
code :
chem2._xscale=Math.ceil(chem2.var_niv/(profondeur/100)); 
chem2._yscale=Math.ceil(chem2.var_niv/(profondeur/100));
 

Note : on peut aussi écrir cette double instruction comme ceci :
chem2._xscale = chem2._yscale = Math.ceil(chem2.var_niv/(profondeur/100));
Ce qui va diviser sont temps d'exécution par 2. (Puisque avant on fessais faire à l'ordinateur 2 fois le même calcul.)

Enfin la dernière difficulté, donne l'imprétion que les clips viennent de loin (notion de fuyantes) on calcule le % du chemin parcouru et on le réutilise dans le positionnement des clips.
code :
var coef:Number = (chem2.var_niv/profondeur); 
chem2._x = centre_x+coef*chem2.var_x; 
chem2._y = centre_y+coef*chem2.var_y;
 


Récapitulatif de la deuxième fonction créé :
code :
function deplacement(chem:MovieClip, var_i:Number, nbr:Number):Void {
        var chem1:MovieClip = chem["clip"+var_i];
        if (chem1.var_niv != profondeur) {
                var vitesse:Number = Math.ceil((profondeur-chem1.var_niv)/frein);
                var vitesse_x:Number = Math.ceil(chem1.var_x/frein);
                var vitesse_y:Number = Math.ceil(chem1.var_y/frein);
                for (var i:Number=0; i<nbr; i++) {
                        var chem2:Number = chem["clip"+i];
                        chem2.var_niv += vitesse;
                        chem2.var_x -= vitesse_x;
                        chem2.var_y -= vitesse_y;
                        if (chem2.var_niv>profondeur) {
                                chem2.cercle.gotoAndStop(1);
                                chem2.var_niv -= profondeur;
                        }
                        chem2.swapDepths(chem2.var_niv);
                        chem2._xscale=Math.ceil(chem2.var_niv/(profondeur/100));
                        chem2._yscale=Math.ceil(chem2.var_niv/(profondeur/100));
                        var coef:Number = (chem2.var_niv/profondeur);
                        chem2._x = centre_x+coef*chem2.var_x;
                        chem2._y = centre_y+coef*chem2.var_y;
                }
        } else {
                clearInterval(inteval);
        }
}
 


6) Maintenant il sufi d'exécuter la fonction 'creer_btns' pour lancer l'animation. (Et de lui passer les bons paramètres.)
code :
creer_btns(_root, tab_nom_1);
 


7) Récapitulatif global (Avec commentaires.):
code :
// Creation de la fonction 'creer_btns'.
function creer_btns(chem1:MovieClip, tab_nom:Array):Void {
        var taille:Number = tab_nom.length;
        for (var i:Number=0; i<taille; i++) {
                var var_profondeur:Number = Math.round(Math.random()*profondeur);
                // Creation du clip conteneur.
                chem1.createEmptyMovieClip("clip"+i, var_profondeur);
                // Creation d'un racourci.
                var chem2:MovieClip = chem1["clip"+i];
                // Creation des variables de sauvegarde.
                chem2.var_x = Math.round(Math.random()*largeur-largeur/2);
                chem2.var_y = Math.round(Math.random()*hauteur-hauteur/2);
                chem2.var_niv = var_profondeur;
                chem2.i = i;
                // Positionement du clip.
                chem2._x = centre_x+chem2.var_x;
                chem2._y = centre_y+chem2.var_y;
                // On y attache le clip 'cercle'.
                chem2.attachMovie("cercle", "cercle", 1);
                // Creation du champs texte.
                chem2.createTextField("texte", 2, -10, -10, 20, 20);
                // Ecriture dans le champs texte.
                chem2.texte.text = tab_nom[i];
                // Rend le texte inpossible a selectioner.
                chem2.texte.selectable = false;
                // Redefinie la taille du clip (en %).
                chem2._xscale = chem2._yscale = Math.ceil(chem2.var_niv/(profondeur/100));
                // Definie les actions a executer lors du clic sur le clip.
                chem2.onRelease = function():Void {
                        // On place la tete de lecture du clip 'cercle' sur l'image 2.
                        this.cercle.gotoAndStop(2);
                        // On suprimer la temporisation 'interval' pour ne pas la declencher 2fois.
                        clearInterval(inteval);
                        // On recree la temporisation 'interval' qui executera la fonction 'deplacement', avec 3paramettres, toute les 40millisecondes.
                        inteval = setInterval(deplacement, 40, chem1, this.i, tab_nom.length);
                };
        }
}
// Creation de la fonction 'deplacement'.
function deplacement(chem:MovieClip, var_i:Number, nbr:Number):Void {
        // On cree un racourci.
        var chem1:MovieClip = chem["clip"+var_i];
        // On verifie si le clip n'est pas deja au premier plan.
        if (chem1.var_niv != profondeur) {
                // On calcule les vitesses de deplacement.
                // Note : La variable 'frein' diminue les vitesses et donc augmente le temps de deplacement des clips.
                var vitesse:Number = Math.ceil((profondeur-chem1.var_niv)/frein);
                var vitesse_x:Number = Math.ceil(chem1.var_x/frein);
                var vitesse_y:Number = Math.ceil(chem1.var_y/frein);
                // On edite les variables et les coordonees de touts les clips.
                for (var i:Number=0; i<nbr; i++) {
                        // Creation d'un racourci.
                        var chem2:MovieClip = chem["clip"+i];
                        // On edite les variables.
                        chem2.var_niv += vitesse;
                        chem2.var_x -= vitesse_x;
                        chem2.var_y -= vitesse_y;
                        // Si le clip a depasse le niveau de premier plan.
                        if (chem2.var_niv>profondeur) {
                                // On place la tete de lecture du clip 'cercle' sur l'image 1.
                                chem2.cercle.gotoAndStop(1);
                                // On edite la variable de niveau.
                                chem2.var_niv -= profondeur;
                        }
                        // On edite le niveau du clip .
                        chem2.swapDepths(chem2.var_niv);
                        // On modifie la largeur et la hauteur du clip (en %).
                        // Note : chem2.var_niv et profondeur, varient entre 0 et 1000, suite au letit calcul le valeur de sortie sont comprise entre 0 et 100.
                        chem2._xscale = chem2._yscale=Math.ceil(chem2.var_niv/(profondeur/100));
                        // On calcul le % du chemin parcouru.
                        var coef:Number = (chem2.var_niv/profondeur);
                        // On modifie les coordonees du clip.
                        chem2._x = centre_x+coef*chem2.var_x;
                        chem2._y = centre_y+coef*chem2.var_y;
                }
        } else {
                // On surprime la temporisation 'interval' puisque le clip est arrive au premier plan.
                clearInterval(inteval);
        }
}
// Declaration des variables globales.
var profondeur:Number = 1000;
var largeur:Number = 200;
var hauteur:Number = 200;
var centre_x:Number = 100;
var centre_y:Number = 100;
var frein:Number = 5;
// Creation du tableau des nom.
var tab_nom_1:Array = Array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
// Execution de la fonction 'creer_btns' a laquel on envoi le chemin du clip conteneur (ici la scene principale '_root') et le tableau des nom.
creer_btns(_root, tab_nom_1);
 

Note : Les lignes précédées de '//' sont des commentaires, vous pouvez donc les supprimer sans aucun risque.

8) Et pour finir la dernière étape, celle que vous attendiez tous, l'ENREGISTREMENT ce que vous avez fait tout au long de l'écriture du code bien évidement 14............12............. comment sa non ? 4 RHHAAA pas bien !)







Conclusion :
Voila il ne vous reste plus qu'à publier votre document.

idées :
-Pour transformer cette animation en menu, vous pouvez modifier le code pour qu'un clic sur un clip qui est déjà situer au premier plan déclenche une autre action (un getURL(); par exemple)
-Il y a aussi un petit problème dans le code a régler, en effet si l'on crée 2clip au même niveau, le dernier clip crée va écraser le précédent. je vous laisse donc imaginer un système pour éviter que cela se produise dans notre application.
0 commentaires / Ajouter commentaires.
Commentaires
Ajouter un nouveau commentaire.
Pseudo :
Email :
Site web :
Message :
:1::2::3:
:4::5::6:
:7::8::9:
:10::11::12:
:13::14::15:
:16::17::18:
Retour en haut. page d'administration. Valide XHTML 1.0 Valide CSS