9 septembre 2008

LSL avancé : l'évènement listen

Avant de poursuivre les tutoriels pour les débutants en LSL, voici à la demande d'une amie un petit tutoriel sur l'évènement listen.


Comme tous les évènements, le listen se découpe en deux parties :

  1. On met en place une écoute, c'est a dire que l'on demande à notre script d'écouter.
  2. La gestion de l'écoute : dès que le script a entendu quelque chose, il fait appelle a l'évènement listen qui contient les instructions à effectuer.


Lancer une écoute


Cela se fait à partir de la fonction llListen :

integer llListen( integer canal, string nom, key id, string msg );


canal(integer) : le canal à écouter. Si on veut écouter le chat, on utilisera la constante PUBLIC_CHANNEL. En général, pour permettre le dialogue entre plusieurs objets, on utilisera un autre canal que ce dernier, pour éviter la saturation du script.

nom(string) : le nom de l'avatar, ou de l'objet, que l'on souhaite écouter. A condition bien sur qu'il parle sur le bon canal. Si on veut que notre script écoute tout sur un canal précis, on mettra comme valeur : "", soit la chaine vide.

id(key) : l'UUID de l'avatar, ou de l'objet. Même principe que pour le nom, sauf que là, on travaille avec l'UUID. Pour écouter tout le monde : on utilisera la clé vide : NULL_KEY.

msg(string) : un message particulier. Cela permet à notre script de déclencher l'évènement que si un message précis a été entendu.

A noter que l'appel à la fonction llListen renvoie un nombre entier qui référence l'écoute. Nous verrons plus loin à quoi cela peut servir.

Pourquoi mettre autant de filtres ?
Plus les filtres sont précis, et moins le script aura de travail à faire, donc moins de ressources consommées, ce qui allège la charge sur la sim.


Traiter l'écoute

Cela se fait avec l'évènement listen :

listen( integer channel, string name, key id, string message ){
//les instructions à effectuer...
}


parmi les paramètres que reçoit l'évènement listen, on trouve :

  • channel : le canal sur lequel se fait l'écoute
  • name, id : le nom et la clé qui ont été envoyé par llListen
  • message : le texte qui a été écouté




Premier exemple d'application

Le projet est de faire un objet perroquet, qui va répéter tout ce que je dis. On va donc se construire un perroquet (un bête cube pour aller plus vite).
Cahier des charges :
  • quand on clique sur lui, il écoute ce que dit son propriétaire.
  • Il répète ce qui est dit
  • si on lui dit : zut, il s'arrête



integer ecoute;
integer canal = PUBLIC_CHANNEL;
key avatar;


default
{

touch_start(integer total_number)
{
avatar = llGetOwner();
ecoute = llListen(canal, "", avatar, "");
}

listen(integer channel, string name, key id, string message)
{
if (message != "zut") llSay(canal, message);
else {
llSay(canal, "Je me tais à present...");
llListenRemove(ecoute);
}
}

}


Détaillons un peu ce code...

Lorsque l'on touche notre perroquet, on le met en route.... Il commence par récupérer l'UUID de son propriétaire, puis ouvre un canal d'écoute. L'UUID de l'avatar sert de filtre : il ne va pas écouter tout ce qui se passe sur le chat, mais seulement ce que son propriétaire dira. La fonction llListen renvoie un entier que l'on affecte a la variable ecoute, et qui correspond au numéro de l'écoute. Cela permettra ensuite de pouvoir supprimer cette écoute en question lorsqu'elle ne sera plus utile.

A chaque fois que le propriétaire parle dans le chat, le script déclenche un évènement listen. Si ce qui est dit est "zut", le perroquet annonce qu'il se tait (à la bonne heure). Puis il annule l'écoute (llListenRemove) : cela met le script en sommeil. Il faudra a nouveau cliquer sur le perroquet, pour lancer un nouvel évènement touch_star, qui initiera une nouvelle écoute.



Autre exemple


Imaginons cette fois-ci que nous avons chez nous plusieurs lampes. Nous avons des objets lampes, et un autre objet qui permet d'allumer ou d'éteindre toutes les lampes en même temps.

Comment cela va-t-il fonctionner ?

Nos lampes vont toutes avoir le même script : ce dernier sera à l'écoute d'un canal précis. Si on parle sur ce canal, la lampe s'allume ou s'éteint.
Nous avons aussi un autre objet "interrupteur". Lorsque l'on clique dessus, il donne l'ordre au lampe de s'allumer ou de s'éteindre.
Il va parler sur le canal choisi, et donner son ordre. Les lampes seront à l'écoute.

Donc deux scripts : un pour chacune des lampes, et un pour l'objet.


Script de l'interrupteur :


integer canal = -1234567;

default
{

touch_start(integer total_number)
{
llSay(canal, "clic");
}

}


A chaque fois que l'on clique sur lui, l'interrupteur dit "clic" sur le canal choisi (ici négatif : un avatar ne peut parler sur un canal négatif, on utilisera donc les canaux négatifs pour les dialogues d'objets par exemple)



Script pour les lampes :




integer canal = -1234567;
integer ampoule;


//fonction qui commandera allumage/extinction de la lampe
commande_ampoule(integer amp) {
//si amp == 0 : on éteint
//si amp ==1 : on allume
// à écrire donc..... je vais pas tout faire non plus :)
}


default
{

state_entry()
{
ampoule = 0;
llListen(canal, "", NULL_KEY, "clic");
}


listen(integer channel, string name, key id, string message)
{
ampoule = (ampoule + 1)%2;
commande_ampoule(ampoule);
}

}



A l'initialisation du script (state_entry), on donne à ampoule la valeur 0 ( 0 pour éteint, et 1 pour allumer). La variable ampoule représente l'état de l'ampoule. Puis on ouvre une écoute. On ne récupère une référence surcette écoute, car puisque la lampe sera toujours en attente d'un ordre, l'écoute ne sera jamais supprimée.
Par contre, l'écoute ne réagira que au mot "clic". Et sera sourd a tout autre.

Quand le clic retentit, l'évènement listen est lâché !! Tout d'abord, on change l'état de l'ampoule (on ajoute 1, et si le résultat est 2, on le passe a 0 ; tout cela est écrit avec modulo 2, qui permet de gérer plus proprement un état double).
Le nouvel état de l'ampoule est ensuite passé à la fonction commande_ampoule.... qui agit en conséquence.


Nous verrons dans un prochain tutoriel, l'utilisation de la tite boite de dialogue bleue, qui utilise l'évènement listen, raison pour laquelle j'ai tout d'abord commencé par lui.

Aucun commentaire: