Recherche

Recherche personnalisée

dimanche 29 mars 2009

Tutorial 4 Porte (3/3)

Nous allons pour une dernière fois nous intéresser à notre porte. Cette fois le but est d'obtenir un script fonctionnel. Voici les éléments que nous devons prendre en compte :

* la porte doit pivoter sur un axe, comme une porte classique,
* toutes les dispositions doivent être opérationnelles (axe à droite ou à gauche),
* les deux sens d'ouverture doivent fonctionner (pousser ou tirer),
* la porte doit être commandée "à la voix" par l'intermédiaire du Chat avec les commande "ouvre" et "ferme",
* seul le propriétaire doit pouvoir commander la porte,
* un son doit accompagner le mouvement.

Nous allons analyser tous ces éléments pour déterminer les fonctions du LSL dont nous allons avoir besoin. La rotation de la porte représente notre première difficulté, déjà au niveau de la construction. En effet pour un prim l'axe de rotation est central alors que nous voulons que cet axe se situe à l'extrémité droite ou gauche de la porte. Il existe une façon simple de résoudre cette difficulté en utilisant un second prim qui sert d'axe. Il suffit ensuite de créer une liaison entre les deux. Mieux qu'un grand discours j'ai trouvé une video qui montre cette technique :



http://www.slbuilding.com/Open-Close_door.html



Maintenant que la question de la construction est réglée intéressons-nous à la rotation. Nous avons déjà rencontré un certain nombre de types avec "integer", "float", "string" et "vector". Un autre type est "rotation". Sans doute pensez-vous que la rotation est comme la position et la dimension et qu'on peut s'en sortir avec un vecteur. Après tout avec trois valeurs ont peut très bien gérer une rotation dans l'espace. Mais c'est compter sans les fantaisies des mathématiciens et leur invention des quaternions. L'explication de ces derniers dépasse largement le cadre de ce tutorial mais le type de base "rotation" de LSL représente un quaternion, autrement dit un ensemble de quatre valeurs qui décrit une rotation dans l'espace. cette approche est loin d'être intuitive mais est cohérente sur le plan mathématique. Pour ceux qui veulent tout savoir voici la page du wiki dédiée à ce type :



http://www.lslwiki.net/lslwiki/wakka.php?wakka=rotation



D'un point de vue pratique vous pouvez raisonner en coordonnées dites "eulériennes" avec la quantité de rotation par rapport aux trois axes x, y et z, dans un vecteur. Mais les problèmes arrivent lorsque vous voulez combiner des rotations, dans ce cas il faut passer aux quaternions. Heureusement il existe dans LSL des fonctions qui permettent un aller-retour entre ces représentations avec llEuler2Rot et llRot2Euler. Un autre élément à prendre en compte est que les fonctions qui concernent les rotations attendent des valeurs en radian alors que vous êtes habitué à entrer des valeurs en degrés lors de la construction. Il suffit de se rappeler 360° est égal à 2PI radians, 180° égal à PI radians... Pour notre porte un angle de 90° correspond donc à PI/2 radians. Pour ceux qui sont mal à l'aise avec les radian il existe des constantes pour la conversion : DEG_TO_RAD et RAD_TO_DEG. Mais elles ne présentent d'intérêt que pour des valeurs exotiques, dans notre cas nous pouvons raisonner directement en radian. Il existe une fonction qui nous donne la rotation actuelle d'un objet : llGetRot qui renvoie un type "rotation", donc un quaternion. Et une fonction qui applique une nouvelle rotation : llSetRot qui réclame aussi un quaternion.

J'ai dit que seul le propriétaire devait pouvoir manoeuvre la porte. Il faut savoir, même si cela doit blesser notre orgueil virtuel, que sur second life nous ne sommes que des numéros. Il existe une fonction qui renvoie la clef d'identification du propriétaire d'un objet : llGetOwner. Ce qui nous donne l'occasion de rencontrer un nouveau type : 'key", qui est un type "string" spécialisé, chaque chose dans second life possède une clef unique qui l'identifie. Nous avons ainsi déjà vu 6 des 7 types de LSL !

En ce qui concerne les sons un certain nombre de fonctions permettent de faire un peu ce que l'on veut. Vous trouvez tout ça dans le wiki :



http://www.lslwiki.net/lslwiki/wakka.php?wakka=sound



Pour notre porte nous pouvons choisir indifféremment llPlaySound ou llTriggerSound. La différence entre ces deux fonctions ne saute pas aux yeux spontanément. Elle réside simplement dans le fait que dans le cas de la première fonction le son suit l'objet si celui-ci est en mouvement alors que pour la seconde il continue d'être émis de la même localisation même si l'objet a bougé entre temps. Notre porte n'ayant pas pour mission d'aller bien loin cette subtilité ne nous concerne pas. Par contre il vous faut mettre un fichier son dans votre objet pour que ça fonctionne et faire correspondre le nom écrit dans le code !

Pour les autres éléments je les décrirai avec les commentaires sur le code :



// Position de l'axe
integer AxeADroite = TRUE;
// Porte poussée ou tirée
integer Pousser = TRUE;
// Porte ouverte ou fermée
integer PorteOuverte = FALSE;

bougerPorte(string message)
{
float angle;
// Détermination du sens de la rotation pour la fermeture
if((AxeADroite && Pousser) || (!AxeADroite && !Pousser))
{
angle = PI_BY_TWO;
}
else
{
angle = -PI_BY_TWO;
}
// Pour l'ouverture on inverse
if(message == "ouvre")
{
angle = -angle;
PorteOuverte = TRUE;
}
else
{
PorteOuverte = FALSE;
}
// Rotation
llTriggerSound("grincement", .5);
rotation rot = llEuler2Rot(<0,0,angle>);
llSetRot(llGetLocalRot()* rot);
}

default
{
state_entry()
{
// Récupération de la clef du propriétaire
key proprio = llGetOwner();
// Mise en place de l'écoute
llListen(PUBLIC_CHANNEL, "", proprio, "ouvre");
llListen(PUBLIC_CHANNEL, "", proprio, "ferme");
}

listen(integer channel, string name, key id, string message)
{
// Test pour voir s'il faut bouger la porte
if((message == "ouvre" && !PorteOuverte) || (message == "ferme" && PorteOuverte))
{
bougerPorte(message);
}
}
}



Ce code que je vous propose là est une possibilité parmi plein de possibles. Je l'ai rédigé pour faire apparaître un certain nombre d'éléments nouveaux. Il n'est pas forcément optimisé, considérez le surtout sous son aspect didactique. Le code débute par la déclaration de trois variables globales pour mémoriser les données structurelles de la porte (axe à droite ou à gauche, action pousser ou tirer) et la position de la porte 'ouverte ou fermée). Nous voyons pour la première fois apparaître les constantes TRUE et FALSE. Dans les langages évolués existe un type "boolean" qui peut adopter deux valeurs : vrai (TRUE) et faux (FALSE). Ce type n'existe pas dans LSL. Nous sommes obligés d'utiliser un type "integer" et ne retenir que deux valeurs : 0 (qui correspond à FALSE) et 1 (qui correspond à TRUE). Nous pourrions très bien dans le code écrire :

integer AxeADroite = 1;
integer Pousser = 1;
integer PorteOuverte = 0;

Mais il est plus explicite d'adopter l'écriture avec TRUE et FALSE pour une question de lisibilité du code. Je rappelle que ces variables sont globales et donc accessible de tout le code. Je passe directement à l'explication du bloc default. L'événement state_entry permet comme d'habitude de faire les initialisations. Ici on récupère la "key" du propriétaire de la porte. Ensuite on met en place l'écoute sur le canal public, pour le proprio, avec les deux commandes "ouvre" et ferme". Ensuite nous avons l'événement listen que vous connaissez déjà. Par contre le test pour la nécessité de manoeuvrer la porte comporte pas mal d'éléments nouveaux. D'abord le if. Comme vous devez vous en douter il introduit une condition, c'est un élément fondamental de la programmation. A ce niveau se situe une décision du genre si on a ça alors on fait ça, sinon on fait autre chose. Ce qui est dans la parenthèse qui suit le if est évalué pour savoir si sa valeur est vraie ou fausse. Nous faisons connaissance ici avec les opérateur booléens. Voici ce qu'en dit le wiki :



http://www.lslwiki.net/lslwiki/wakka.php?wakka=boolean



Vous pouvez voir que le signe && correspond à un "et" logique alors que le signe "||" correspond quant à lui à un "ou" logique. Enfin le signe "!" considère l'inverse de la valeur. Tout ce qu'il faut pour évaluer des conditions ! Dans notre cas nous devons savoir si la porte est ouverte ou fermée et si notre intention est de l'ouvrir ou de la fermer. Il est évident que nous n'allons pas ouvrir ou fermer deux fois la porte ! C'est l'objet de de test. S'il est positif alors le code nous renvoie à la méthode bougerPorte dont je n'ai pas encore parlé. J'aurais bien sûr pu mettre tout le code ici sans cet appel de méthode mais c'est une saine attitude de séparer le code en unités fonctionnelles. En voici un premier pas. La méthode bougerPorte est déclarée avant le bloc default. Elle comporte un paramètre de type "string" qui permet la transmission du message qui peut être "ouvre" ou "ferme". Dans cette méthode nous devons considérer les éléments structurels de la porte et son sens d'ouverture. Le résultat est un angle de rotation qui est soit PI/2, soit -PI/2. LSL propose une constante pour cette valeur : PI_BY_TWO. Je vous laisse analyser ce code ! Il est on ne peut plus logique. Lorsque l'angle a été déterminé, et après avoir au passage déclenché le son, nous créons un quaternion en partant d'un vecteur qui comporte l'angle sur l'axe z. Pour obtenir la rotation correcte de la porte il suffit de composer la rotation actuelle qui est donnée pas llGetRot avec la rotation déterminée. Pour obtenir cela il suffit d'une simple multiplication. Finalement c'est bien pratique les quaternions !

Nous en avons enfin fini avec cette porte. Je vous laisse faire des essais en bougeant la porte dans tous les sens ! Dans le prochain tutorial c'est promis il n'y aura plus de porte !

4 commentaires:

  1. Je vous remercie énormément pour toutes vos propositions sur ce site. Vos partages sont très intéressants et fort enrichissants. Félicitations à vous.

    voyance par mail gratuite ; Voyance gratuite par mail

    RépondreSupprimer
  2. Grâce à vous, j'ai pu apprendre beaucoup de choses intéressantes. J'espère en apprendre encore. Je vous félicite pour ces merveilleux partages. Continuez ainsi !

    voyance gratuite

    RépondreSupprimer
  3. Je suis ton blog avec beaucoup d’intérêt depuis peu.
    voyance par mail

    RépondreSupprimer
  4. C’est pour la première que je viens de visiter votre site et je le trouve vraiment intéressant ! Bravo !

    Voyance Email

    RépondreSupprimer