Notre vie est éphémère
Pareille au reflet de la lune
Dans la goutte d'eau
Tombant du bec du héron
Dôgen Zenji
Sous la lune....
Notre vie est éphémère
Pareille au reflet de la lune
Dans la goutte d'eau
Tombant du bec du héron
key avatar;
integer ecoute;
default
{
state_entry()
{
avatar = llGetOwnerKey(llGetKey());
}
touch_start(integer total_number)
{
if (llDetectedKey(0) == avatar){
state bavard;
}
}
}
state bavard{
state_entry()
{
ecoute = llListen(PUBLIC_CHANNEL, "", avatar, "");
}
listen(integer channel, string name, key id, string message)
{
if( message != "zut") llSay(PUBLIC_CHANNEL, "Coco repete : " + message );
else {
llSay(PUBLIC_CHANNEL, "Coco est fatigué, Coco va dormir");
llListenRemove(ecoute);
state default;
}
}
}
Le chemin du serpent dans l'herbe,
Seul le serpent le comprend
Il n'y a rien de plus vaste sous le ciel,
Que la pointe d'un épi automnal
Et une grande montagne
Est une petit chose face au firmament.
Tout le monde discute et émet
Des catégories de contraires.
J'aimerais entendre un discours,
Qui n'entre dans aucune catégorie
Comme les montagnes dominent
Sur de vastes étendues,
C’est seulement grâce à elles
Que l’on peut chevaucher les nuages,
Ce sont elles qui confèrent l’inimaginable
Privilège de s’élever avec le vent.
List ma_liste = [ 12, 2.36, "un message"];
ma_liste = [];
ma_liste += ["un pitit texte"];
ma_liste += ["un autre pitit texte", 12, <0.0,0.0,>];
list ma_liste = ["e1", "e2", "e3"];
integer idx;
for(idx = 0; idx < llGetListLength(ma_liste); idx++){
llSay(PUBLIC_CHANNEL, llList2String(ma_liste, idx) + " a pour index : " + (string)idx);
}
list ma_liste = ["e1", "e2", "e3"];
integer idx = llListFind list(ma_liste, ["e2"]);
list ma_liste = ["e1", "e2", "e3", "e4"];
string s= llDumpList2String(ma_liste, "-");
llSay(PUBLIC_CHANNEL, s);
e1-e2-e3-e4
string msg;
msg = "bonjour à tous";
msg = "Bonjour " + "à tous";
string msg1, msg2, msg;
msg1 = "Kikooooo";
msg2 = "les amis !!";
msg = msg1 + msg2;
msg = msg1 + " " + msg2;
msg = "Comment ca \"lapin\" ?? ";
string msg = "Youppi c'est les vacances !!";
llWhisper(PUBLIC_CHANNEL, msg + " contient exactement " + (string)llStringLength(msg) + " caractères...");
string msg = "Youppi c'est les vacances !!";
msg = llGetSubString( msg, 13, 15 );
llSay(PUBLIC_CHANNEL, msg);
string msg = "Mais qui vois je la bas ?? Serait ce mon amie Ouma ??
integer idx = llSubStringIndex(msg, "Ouma");
if (idx == -1) llSay(PUBLIC_CHANNEL, "Ouma n'est pas la !!");
else llSay(PUBLIC_CHANNEL, "Ouma est la !!");
Deirdre;25
Yoyo; 27
Ouma;32
Lala; 36
Nounours;34
string ligne = "Deirdre;25";
string nom;
string nombre;
nom = llGetSubString(ligne, 0, llSubStringIndex(ligne, ";")-1);
nombre = llGetSubString(ligne, llSubStringIndex(ligne, ";") + 1, llStringLength(ligne));
llSay(PUBLIC_CHANNEL, nom + " a pour nmbre : " + (string)nombre);
nombre = llGetSubString(ligne, llSubStringIndex(ligne, ";") + 1, -1);
L'ombre des Bambous balaie les marches
Mais nulle poussière n'est soulevée.
Le clair de lune pénètre profondément la marre
Mais l'eau n'en garde nulle trace
La noirceur de l'ombre des pins
dépend de la clarté de la lune
Chuchoter | whisper | 10m |
Parler | say | 20m |
Crier | shout | 100m |
/100 kikooooo !
llWhisper(integer channel, string message);
llSay(integer channel, string message);
llShout(integer channel, string message);
llWhisper(PUBLIC_CHANNEL, "Bisous toi !!");
llSay(PUBLIC_CHANNEL, "Bonjour à tous !!");
llShout(PUBLIC_CHANNEL, "Lapin !!!!");
llRegionSay(integer channel, string message);
llOwnerSay(string message);
llGetKey( ) ==> key
llDetectedKey( integer number ) ==> key
default
{
touch_start(integer total_number)
{
key k = llDetectedKey(0);
llSay("j'ai été touché par " k);
}
}
llKey2Name( key id ) ==> string
default
{
touch_start(integer total_number)
{
llSay("Bonjour " llKey2Nam(llDetectedKey(0)));
}
}
llGetOwnerKey(key id) ==> key
llGetOwner() ==>key
key proprio;
default
{
state_entry()
{
// à l'entrée dans le script, on affecte à proprio
// la key du propriétaire de l'objet
proprio = llGetOwner();
}
on_rez(integer a)
{
// Si jamais on rez l'objet, on affecte à proprio
// la key du propriétaire de l'objet
proprio = llGetOwner();
}
touch_start(integer total_number)
{
if ( proprio == llDetectedKey(0))
{
llSay(PUBLIC_CHANNEL, "Bonjour mon Maître !!);
} else {
llSay(PUBLIC_CHANNEL, "Vous n'êtes pas mon Maître !!);
}
}
}
changed(integer change)
{
if (change & CHANGED_OWNER)
llResetScript();
}
while(condition){
instruction1;
instruction2;
....
}
integer n = 1;
// on commence à 1.
// on définit la variable à parcourir
// et on l'initialise de suite
while ( n <= 10 ){ if (n%2 == 0){
llSay(0, "le nombre "+ n + " est pair");
}else {
llSay(0, "le nombre " + n + " est impair");
}
n++;
}
for(nom de la variable et affectation; condition de fin; incrément){
instruction1;
instruction2;
....
}
integer n;// l'initialisation n'est pas nécessaire
for( n = 1 ; n <= 10 ; n++){ if (n%2 == 0){
llSay(0, "le nombre "+ n + " est pair");
}else {
llSay(0, "le nombre " + n + " est impair");
}
}
integer n;
for( n = 0 ; n <= 10; n+=2){ llSay(0; n);
}
integer n;
for( n = 10 ; n >= 0 ; n-=2){
llSay(0; n);
}
//définition des variables globales
// Définition des fonctions personnelles
// un état du script : etat1
state etat1 {
evenement1(){
fonction1();
fonction2();
}
evenement2(){
fonction3();
fonction4();
}
}
ma_fonction(){
instruction1;
instruction2;
....
}
dire_bonjour(){
llSay(0, "Bonjour à tous !!");
}
dire_bonjour();
ma_fonction( type1 variable1, type2 variable2, ...){
instruction1;
instruction2;
....
}
dire_bonjour2(string nom){
llSay(0, "Bonjour " + nom + " !! Comment vas tu ?");
}
dire_bonjour2("Nounours");
parite(integer i){
if (i%2 == 0){
llSay(0, "le nombre "+ i + " est pair");
}else {
llSay(0, "le nombre " + i + " est impair");
}
}
parite(25);
compare(integer i, integer j){
if ( i <=j ){ llSay(0, i + " est plus petit ou égal que "+ j);
} else {
llSay(0, i + " est plus grand que "+ j);
}
}
type ma_fonction(type1 variable1, type2 variable2, ...){
instruction1;
instruction2;
....
return valeur;
}
integer ajoute(integer i, integer j){
return i+j;
}
integer h;
h= ajoute(10, 25);
somme_entier_naturels_version1 ( n )
{
// Cette fonction va sommer tous les entiers de 1 à n (n étant un paramètre)
// On crée une variable résultat qui aura pour nom "somme"
somme = 0
POUR compteur DE 1 A n FAIRE
// On crée une variable compteur qu iprendra successivement
// les valeur entieres de 1 à n
// On fait la somme des entiers de 1 à n et on le stocke dans "somme"
somme = somme + compteur;
// Fin de la boucle "POUR", donc le programme restera dans cette boucle
// tant que compteur sera compris entre 1 et n.
// L'incrémentation de compteur se fait automatiqueemnt
// à la ligne "POUR compteur..."
FIN_POUR
// On retourne le résultat "somme" qui contient, grace à la boucle "POUR",
// la sommation des entiers de 1 à n
RETOURNER somme
}
integer somme_entier_version1(integer n){
integer somme = 0;
integer compteur;
for (compteur = 1; compteur <= n; compteur++){ somme = somme + n ;
// ou encore : somme += n;
}
return somme;
}
somme_entier_naturels_version2 ( n )
{
// Cette fonction va sommer tous les entiers de 1 à n (n étant un paramètre)
// On sait que la somme des entiers naturels de 1 à n est une formule mathématique!
// http://fr.wikipedia.org/wiki/Somme_(arithm%C3%A9tique)
// somme = n * (n + 1) / 2
// Pourquoi ne pas réutiliser ce résultat?
// On crée une variable somme, et on lui met la formule!
somme = n * (n + 1) / 2
// Et maintenant, on retourne le résultat!
RETOURNER somme
}
integer somme_entier_version2(integer n){
integer somme;
somme = n * ( n + 1) / 2;
return somme;
}
return n * ( n + 1) / 2;
integer i;
integer j;
i = 45;
j = 5;
i = i + j ;// maintenant i vaut 50 (= 45 + 5)
integer k = i/j;// k vaut 45/5 = 9
integer h = i % 10;// h est le reste de la division
// de 45 par 10.... donc h = 5
intger g = i - k*j;
integer i = 50;
float j = i;// j vaut 50.0, 50 en valeur flottante, la conversion est implicite
// car il n'y a pas de perte de données
j = 50.36;
i = (integer)j;//conversion explicite car i vaut 50, partie entière de j.
// Ici, on perd de l'information. Donc il faut
// expliciter le cast.
float i = 2/3;
float i = 2.0/3.0;
integer k = 2;
integer l = 3;
float i = (float)k / (float)l;
integer i = 5;
i++;// i++ équivaut à i = i+1; i vaut 6;
i--;// equivaut à i=i-1; i vaut 5
integer i = 20;
i += 5;// équivalent à i = i+5;
i -= 5;// équivalent à i = i-5;
i *= 5;// équivalent à i = i*5;
i /= 5;// équivalent à i = i/5;
i %= 5;// équivalent à i = i%5;
integer t = 78;
integer min = 78/60;// 1 min
integer sec = 78%60;// et 18 sec
if(la_condition){
instruction1;
instruction2;
} else {
instruction3;
instruction4;
}
i == 4 vrai si i vaut 4. Noter bien les deux ==
i > 4
i <>
Une opération de comparaison, ou plusieurs, avec des opérateurs logiques :
&& => ET, || => OU, ! => NOT
par exemple, je veux tester si i est compris entre 5 et 10....
Cela signifie que i est plus petit ou égal à 10 ET plus grand ou egal à 5. On écrira donc :
(i >= 5) && (i <= 10)
Par exemple :
if ((i >= 5) && (i <= 10)){ llSay(0, " Le nombre est compris entre 5 et 10");
}
ou encore
if ( i%2 ){
llSay(0, "Le nombre est pair");
}else {
llSay(0, "Le nombre est impair");
}
C'est tout pour aujourd'hui, vous pouvez aller prendre l'air, il fait si beau dehors ! Respirez à plein poumon.
Libellés :
LSL,
Second Life
10 septembre 2008
LSL avancé : la boite dialogue bleue
Comme promis, voici une petit tutoriel sur la petite boite de dialogue bleue qui apparait dans le coin supérieur droit de l'écran.
Cette fenêtre de dialogue est équipée de boutons permettant ainsi une interaction.
Il y a donc dans cette fenêtre 3 parties :
- le message, le texte de la boite de dialogue, présentant les boutons, donnant une information, ....
- des boutons (12 au maximum)
- un bouton "ignorer", permettant de fermer la fenêtre sans rien faire
La fonction qui va permettre la création de cette boite est la fonction llDialog :
llDialog( key avatar, string message, list buttons, integer chat_channel );
- avatar : le UUID de l'avatar qui verra apparaitre la boite de dialogue, sa clé
- message : le message de la boite de dialogue
- buttons : le texte des boutons, présenté sous la forme d'une liste
- chat_channel : le canal où se fera la trasnmition de l'information
Mais pourquoi donc parler de cette boite de dialogue juste après avoir parlé du listen ??
Ben, justement... La fonction llDialog fait parler notre avatar, c'est là son mode de fonctionnement. Lorsque l'on clique sur un bouton, notre avatar parle sur le canal choisi et dit le texte du bouton. Ainsi, il faut pour traiter l'information qu'il y ait derrière quelqu'un a l'écoute !! Donc un événement listen.
Donc llDialog s'utilise conjointement avec llListen / Listen, et aussi llListenRemove, car il n'est pas nécessaire de garder l'écoute en fonction une fois le message transmis.
Nous avons donc les étapes suivantes :
- création de l'écoute : llListen
- ouverture de la boite de dialogue : llDialog
- réception et traitement du message : evenement listen
- suppression de l'écoute
Concernant les boutons....
Le texte des boutons doit être passé à llDialog sous la forme d'une liste. L'ordre des éléments de cette liste a son importance : elle détermine l'ordre des boutons.
Si deux boutons ont le même nom, le message transmis sera le même, donc notre script ne pourra pas savoir quel bouton a transmis ledit message. Donc attention à choisir des textes tous différents pour les boutons.
L'ordre des boutons par rapport aux éléments de la liste est le suivant :
9 - 10 - 11
6 - 7 - 8
3 - 4 - 5
0 - 1 - 2
Premier exemple : un menu simple
Nous allons travailler sur un objet tout simple : un cube. Lorsqu'on clique sur lui, il nous propose de lui changer sa couleur. Nous supposerons que nous avons une fonction qui fera ce changement de couleur.
key avatar; //l'avatar qui clique sur l'objet
integer ecoute;
integer canal = 123456;
list menu = ["rouge", "noir", "blanc"];
string message_menu = "Choisissez ma nouvelle couleur";
changer_couleur(string couleur){
//a ecrire, on change la couleur des faces du cube
}
default
{
touch_start(integer total_number)
{
avatar = llDetectedKey(0);
ecoute = llListen(canal, "", avatar, "");
llDialog(avatar, message_menu, menu, canal);
}
listen(integer channel, string name, key id, string message)
{
if ( message == "rouge" ) changer_couleur("rouge");
else if (message == "noir") changer_couleur("noir");
else if (message == "blanc") changer_couleur("blanc");
llListenRemove(ecoute);
}
}
Lorsqu'on touche l'objet, l'évènement touch_start est déclenché. on récupère la clé de l'avatar, on ouvre une écoute, en précisant cette clé : ainsi, seule celui qui a cliqué sera écouté.
On fait ensuite appel a la la fonction llDialog. On lui passe comme paramètre la clé de l'avatar, de manière a ce que ce soit lui qui voit s'ouvrir la boite de dialogue, le texte de la boite et la liste des boutons, ainsi que le canal.
Puis, quand un bouton a été choisi, le script intercepte le message grace à son ecoute : on traite l'évènement listen. Le message envoyé est le texte du bouton. On fait donc un teste sur les valeurs possibles avec une série de IF.
Si la valeur est correcte : on change la couleur.....
Puis, le travail ayant été fait, on supprime l'écoute.
Second exemple : menu et sous menus
Nous allons complexifier l'exemple précédent : nous avons cette fois beaucoup de couleurs, et nous voulons les trier par famille. Famille des rouges, des bleus, des verts.
Il nous faut donc 4 menus :
- menu_principal : permet de choisir la couleur
- menu_rouge : choix de la couleur ou retour au menu principal
- menu_bleu et menu_vert, sur le meme principe que menu_rouge
Modifions le programme précédent :
key avatar; //l'avatar qui clique sur l'objet
integer ecoute;
integer canal = 123456;
list menu_principal = ["rouge", "bleu", "vert"];
string message_menu = "Choisissez ma nouvelle couleur";
list menu_rouge = ["vif", "magenta", "<<<", "sang"]; string menu_rouge = "Choisissez votre nuance de rouge : "; list menu_bleu = ["marine", "royal", "<<<", "cyan"]; string menu_bleu = "Choisissez votre nuance de bleu : "; list menu_vert = ["clair", "pomme", "<<<", "emeraude"]; string menu_vert = "Choisissez votre nuance de vert : "; changer_couleur(string couleur){ //a ecrire, on change la couleur des faces du cube } default { touch_start(integer total_number)
{
avatar = llDetectedKey(0);
ecoute = llListen(canal, "", avatar, "");
llDialog(avatar, message_menu, menu, canal);
}
listen(integer channel, string name, key id, string message)
{
//on traite le menu principal
if (message == "rouge") llDialog(avatar, message_rouge, menu_rouge, canal);
else if (message == "vert") llDialog(avatar, message_vert, menu_vert, canal);
else if (message == "bleu") llDialog(avatar, message_bleu, menu_bleu, canal);
//on traite pour le sous menu, le bouton <<< else if (message == "<<<") llDialog(avatar, message_menu, menu, canal); // les couleurs....
else if (message == "vif") {
changer_couleur("vif");
llListenRemove(ecoute);
}
else if (message == "magenta") {
changer_couleur("magenta");
llListenRemove(ecoute);
}
// on traite ainsi toutes les autres couleurs
// pour la derniere, on ecrit seulement else
// au lieu de else if
}
}
Ce script fonctionne comme le précédent : on capture la cle de celui qui a cliqué, on ouvre une écoute et on affiche la boite de dialogue, celle du menu principal.
Ensuite, en fonction de ce qui est cliqué, on agit de manières différentes :
- si on est sur le menu principal, on affiche à nouveau la boite de dialogue, mais avec le menu couleur choisi
- si on est sur un menu couleur et que le bouton de retour est pressé : on affiche à nouveau la boite de dialogue du menu principal
- sinon : on est sur une couleur, donc on effectue la tache demandée
Un dernier conseil pour finir : dans certains cas, on a plusieurs copies du meme objet l'une près de l'autre. Et il ne faudrait pas que tous ces objets se parlent sur le meme canal : dans certains cas, cela peut provoquer des interractions. Imaginer : vous commandez l'allumage d'une lampe, et toutes les lampes s'allument !!
Pour cela ajouter ceci au début de l'état default :
state_entry()
{
canal = (integer)llFrand(-100000) - 10000;
}
Cela positionne le canal d'écoute sur une valeur aléatoire grande et négative. La plage de valeurs étant importante, la probabilité que deux objets obtiennent le même canal est quasi nulle.
Voila de quoi agrémenter vos objets de zoulies boites de dialogue, pour encore plus d'interactivité.
Si vous avez des questions, ou envie de voir ici d'autres tutoriels, n'hésitez pas. Je ferais de mon mieux.
Libellés :
LSL,
Second Life
Initiation au langage LSL (II)
Bien après avoir vu les bases du LSL, allons un peu plus loin dans notre connaissance du langage.
Parlons un peu des différentes variables utilisables dans SL.
Notons tout d'abord que pour utiliser une variable, il faut l'avoir définie auparavant. Donc, on déclare une variable, on lui donne une valeur, et ensuite on l'utilise. Une variable se définit par deux paramètres : son type, qui définit quel type de données elle contiendra, et sa portée, qui définit à quel endroit du script elle pourra être utilisée.
I. Portée et définition d'une variable
Variables globales : elles sont accessibles à tout moment à l'intérieur du script. Leur portée est donc le script lui même.
Variables locales : elles sont définies à l'intérieur d'un bloc de code (délimité par des accolades). Elles ne peuvent donc être utilisées que dans ce bloc. Elles n'ont aucune existence en dehors de ce bloc. Si une variable locale a le même nom qu'une variable globale (c'est possible même si c'est un très mauvaise idée !! A éviter absolument), c'est la variable locale qui sera utilisée.
Variables paramètres : ces variables servent à définir les paramètres d'une fonction. Nous verrons cela en détail lorsque nous parlerons des fonction.
Les variables globales doivent être définies en début de script, avant même l'état default. Les variables locales sont définies dans le bloc de code où elles nous sont utiles, lorsque l'on en a besoin.
Pour définir une variable, il faut écrire son type suivit de son nom, et enfin un point virgule pour terminer l'instruction.
Par exemple :
integer un_entier;
string message;
Il est possible de donner une valeur à une variable au moment où on la définit. Ainsi, elle est initialisée dès sa création. Si on ne donne pas de valeur lors de la définition de la variable, le LSL lui donne une valeur par défaut : 0, pour les entiers, "" la chaine vide pour les chaines de caractères.
integer un_entier = 5;
string message = "Kikou !!!!";
En ce qui concerne le choix du nom de la variable, plusieurs points :
- donner un nom qui a du sens, éviter les noms comme : truc, machin, bidule, toto, foo, bar, deirdre, ....
- pas de caractères spéciaux dans le nom, ni d'espace : utiliser des lettres, des chiffres, ainsi que le underscore : _
II. Les différents Types du LSL
Le LSL est un langage fortement typé. C'est à dire que toute variable, pour pouvoir être utilisée, doit avoir été définie. Cette définition précise son type, c'est à dire le contenu qu'elle pourra recevoir.
On sera parfois obligé de convertir un type en un autre. Le transtipage, ou cast, est l'opération permettant de faire cela. Tout cela sera vu par la suite.
Voici les différents types de données pour le LSL :
- integer: nombre entier, signé, codé sur 32 bits. Ex : 0, 6, -56
- float: nombre flottant signé, un décimal en gros. Il doit s'écrire obligatoirement avec le point décimal et supporte la notation exponentielle. Ex : 0.0, 1.698, -6.25, 6.0E6, -6.3E-4
Notons au passage que si le float vaut 0, on doit écrire celui-ci 0.0, ou encore .0
- string : chaine de caractères. Elle doit être délimitée par des guillemets. Ex : "Kikou !!"
Si la chaine doit contenir des guillemets, on les précède de \. Ex : "J'adore ce genre de \"bidule\". "
- key : la key représente une chaine de caractères de format spécifique qui correspond à l'UUID, identifiant unique de tout objet sur SL.
- vector : 3 floats réunis pour définir un vecteur. On encadre par <>. Ex : <0.0,0.0,0.0> pour le vecteur nul.
- rotation : 4 floats réunis pour interpréter une rotation. Fonctionne comme le vector. Ex : <1.0,0.3,2.3,.2>
- list : liste d'éléments hétéroclites. On encadre par [ et ]. Ex : [ 0, -52.6, "kikouu !!"]
III. Conclusion
Pour conclure, je vous conseille ardemment de commenter votre code, c'est à dire de laisser quelques petites explications renseignant sur ce qu'un bout de code fait, à quoi sert cette fonction, pour quoi il pleut encore aujourd'hui, Henri IV savait-il seulement faire du cheval...
Le texte écrit en commentaire ne sera pas interprété par le script. Pour commenter une ligne de texte, il suffit d'écrire // avant le texte à mettre en commentaire. Tout ce qui suit // sur la même ligne est ignoré par le script.
Exemple :
// Ouiiii !!! Ceci est votre premier commentaire !! bravo !!
Pour résumer, voici le squelette général d'un script, modifié par ce que nous venons de voir :
//Début du script - Définition des variables globales
string ma_chaine_globale; // commentaire sur ce que va contenir cette variable
integer un_entier_global; // commentaire sur ce que va contenir cette variable
// Définition des fonctions
// on verra ca plus tard....
// un état du script : etat1
state etat1 {
evenement1(){
fonction1();
fonction2();
}
evenement2(){
fonction3();
fonction4();
}
}
Libellés :
LSL,
Second Life
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 :
- On met en place une écoute, c'est a dire que l'on demande à notre script d'écouter.
- 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.
Libellés :
LSL,
Second Life
Inscription à :
Articles (Atom)
Fille de la Lune
Archives du blog
Au fil du temps...
-
Build SL
(14)
-
Carnets de voyage
(25)
-
chant du dragon
(35)
-
CSI
(29)
-
De tout et de rien
(20)
-
Dragon
(1)
-
Eternal Blades
(22)
-
Humour
(16)
-
Informatique
(4)
-
java
(1)
-
Linux
(10)
-
LSL
(15)
-
Machinima
(17)
-
Musique
(6)
-
Opensim
(1)
-
OS Grid
(5)
-
Second Life
(107)
-
Steampunk
(1)
-
Vidéos
(45)
-
Zen
(12)
Qui suis je...
-
Deirdre Thor
- Arpenteuse de terres de Second Life, ou je build, je scripte, et pratique le noble Art du Sabre.
Afficher mon profil complet
Photos & Vidéos
Au fil des blogs...
Quelques liens...
Les plus consultés
-
Un petit texte de Tchouang Tseu... Notre société passe son temps à parler pour ne rien dire.. On fait des réunions, on bouge, on déplace du ...
-
Après un long moment sans avoir publié quoi que ce soit, et me revoilà avec un petit tuto sur l 'import de son dans SL . Voilà mon prob...
-
Nous allons commencer aujourd'hui une série de tutos sur la réalisation de vêtements pour SL. Pour ce faire, j'utiliserai photoshop....
-
Essayons aujourd'hui de décrypter la fenêtre de statistiques de SL. Cette fenêtre est très souvent utilisée pour mesurer le lag. Donc so...
-
Depuis le temps que je suis sur SL et que je pratique l'art du katana C:SI, je n'avais encore jamais écris d'article sur cela. E...
-
Je suis tombée sur un beau calendrier en forme de dodécaèdre... A la base un calendrier Ubuntu.... donc comme il était en creative commons, ...
-
Un nouveau petit tutorial de build... pour résoudre d'une première manière un problème auquel tout builder est confronté : les prims fan...
-
Poursuivons nos tutos de build avec le deuxième onglet de la fenêtre d'édition ! L'onglet Objet C'est l'onglet le plus impor...
Visites