29 octobre 2008

Voyages

Je me promène sans bruit.
La lune pour seul amie.

Où me guide mes pas ?
Toujours plus loin au fond des bois.
Toujours plus loin au plus profond de moi.

Qui peut comprendre comprendre le chemin parcouru ?
Celui qui le parcours, le cœur léger et sans but.


Le chemin du serpent dans l'herbe,
Seul le serpent le comprend



26 octobre 2008

Firmament

Je suis assise et je regarde le ciel. La lune pleine illumine le ciel. Adossée au pied de l'arbre, je contemple le ciel. La lune argentée fait briller mes cheveux blancs.

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.
Tchouang Tseu


25 octobre 2008

Arguties

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 vent, tout ça pour quoi ??
On découpe, on dissèque, on classe, on range dans des boites... Si ça ne rentre pas alors cela est suspect.
Quand on rencontre quelqu'un pour la première fois.. on ne cherche pas à la connaitre, la première chose qui nous traverse la tête, c'est de la mettre dans une boite avec une étiquette dessus. Sympa, pas sympa, bizarre, étrange, non conforme, on stéréotype à tout va !!
Il n'est jamais trop tard pour changer nos habitudes....


Tout le monde discute et émet
Des catégories de contraires.
J'aimerais entendre un discours,
Qui n'entre dans aucune catégorie


24 octobre 2008

Pensée du jour

Une petit pensée que je laisse à vos meditations pour le Week end.... Ô toi lecteur de ce blog, qu'il te soit doux et agréable.....


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.

23 octobre 2008

La vie.... la mort...

Une petit histoire.......

On raconte que, un jour, en chine, l'empereur fit venir à lui un homme sage et pratiquant la voie.
Il lui demanda : "Toi qui es la sagesse incarnée, calligraphie-moi un poême, sur ce qu'est le bonheur absolu, apprends moi le secret du bonheur, de la félicité. Que je l'accroche à la porte de mon palais."

Le sage médita, et calligraphia :
Le grand père meurt
Le père meurt
Le fils meurt


A la vue de ce poeme, l'empereur se mis en colère, pensant que le sage se moquait de lui. Il voulait entendre parler de bonheur, et le vieil homme parlait de mort.

Alors le sage dit :
C'est pourtant cela, le secret du bonheur.... Nul ne doit survivre à ses enfants.

Et l'empereur comprit... et s'inclina devant le sage.

22 octobre 2008

Cours d'initiation au langage LSL (VI)

Interessons nous aujourd'hui au type list....

Ce type de variable est assez particulier car il permet d'agréger ensemble des variables de types différents. Une liste, le type list, est une suite d'éléments de types divers. Ainsi je peux trouver dans une liste des string, des integer, .....
Une liste est délimitée par des crochets, et les éléments sont séparés par des virgules.

Exemple de liste :

List ma_liste = [ 12, 2.36, "un message"];


Ici : un integer (12), un float (2.36), et une string ("une message"). Chaque type est écris avec ses propres conventions : la string est encadrée par les guillemets. Si il y avait un vector, on l'écrirait entre <>....


ma_liste = [];


Par cette instruction, on vide la liste.... c'est une liste mais qui ne contient rien, c'est donc une liste vide.


On ajoute une élément à une liste en utilisant l'opérateur += (qui correspend en fait à : ma_liste = ma_liste + .......).
On remarquera que, on ajoute, en fait, à une liste une autre liste.

ma_liste += ["un pitit texte"];
ma_liste += ["un autre pitit texte", 12, <0.0,0.0,>];



Parcourir une liste

On utilisera la fonction llGetListLength qui renvoie le nombre d'éléments d'une liste. Le premier élément d'une liste à pour index 0. Et donc, le dernier, la taille de la liste moins 1.
De même, pour obtenir un element de la liste, on utilisera la fonction llList2String

Prototype des fonctions :
integer llGetListLength( list src )
string llList2String( list src, integer index )


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);
}


Attention toutefois... Ma liste ne contient ici que des éléments de type string..... j'utilise donc la fonction llList2String. Mais pour un integer , je dois utiliser la fonction llList2Integer, et ainsi de suite.....


Il existe bien sur des fonctions pour savoir quel est le type de l'élément qui se situe à l'index idx.... Cela permet ensuite de choisir la bonne fonction llList2.... Je vous renvoie au wiki second life consacré au LSL, et qui reste LA référence et le livre de chevet de tout bon scripteur.



Recherche

Pour savoir si une valeur est presente dans une liste, nous utiliserons la fonction llListFindList.
Prototype : integer llListFindList(list source, list element)

Exemple :

list ma_liste = ["e1", "e2", "e3"];
integer idx = llListFind list(ma_liste, ["e2"]);


Notons que l'élément recherché est passé à la fonction sous la forme d'une liste de un seul élément. Dans le cas présent, idx vaut 1.



Transformer une list en string

prototype de la fonction : string llDumpList2String( list ma_liste, string separateur);
Exemple d'utilisation :

list ma_liste = ["e1", "e2", "e3", "e4"];
string s= llDumpList2String(ma_liste, "-");
llSay(PUBLIC_CHANNEL, s);


La fonction prend une string qui correspond au séparateur que l'on souhaite mettre entre les éléments. Ici, j'ai choisi - ..... D'où l'affichage suivant dans le chat :
e1-e2-e3-e4

Ceci est parfois tres utile pour le debuggage d'un script, de maniere à savoir ce que contient une liste...

Voilà, c'est tout pour aujourd'hui........ La prochaine fois on s'attaque aux choses sérieuses !! (encore que ...)
Si vous avez des questions, des remarques, n'hesitez pas bien sur à me laisser un message. Si vous avez aussi des envies de tuto, pareil.... mais attention, je ne developpe pas de script pour autrui.... rendre service oui, faire le boulot des autres qui le reprendront, voir même qui feront un objet payant sous sl avec ce code, non merci.... ou alors je prends 80% hihihi !!
Maintenant, si c'est uen commande, alors là, c'est autre chose.... laissez moi un IM sous SL

Donc, si vous voulez faire une alarme, très bonne idée, mais ne vous attendez pas à recevoir un code entier. Par contre je me ferais un plaisir de vous faire un petit tuto sur les sensors... avec un exemple simple, qui vous aidera a réaliser votre alarme.

Voila ! c'est tout pour ce soir......

21 octobre 2008

Cours d'initiation au langage LSL (V)

Bien, le cours du jour concernera le type de données string.
Il sera l'avant dernier cours à présenter les éléments de base du langage LSL, le dernier sera consacré au type list. Les prochains cours seront tous construits sur le même modèle : nous commencerons à étudier les évènements. Pour cela, explication sera donnée de l'évènement et de sa capture. Puis, je vous proposerai un petit script : cahier des charges de ce qu'il doit faire, le script, et l'explication des différentes parties du script.

Mais commençons par le commencement... le type string !



I - STRING : les chaines de caractères

Une chaine de caractères se repère très vite car elle est délimitée par des guillemets....
Dans l'exemple qui suit, "Bonjour à tous" est une chaine de caractères affectée à la variable msg.

string msg;
msg = "bonjour à tous";


L'opération la plus utilisée sur les chaine de caractères, est la concaténation : il s'agit de regrouper , de coller des chaines de caractères pour n'en former plus qu'une seule.

msg = "Bonjour " + "à tous";

Que l'on écrive : "Bonjour à tous" ou "Bonjour " + "à tous" cela revient à la même chose.
La concaténation de chaines se fait grâce à l'opérateur +


string msg1, msg2, msg;
msg1 = "Kikooooo";
msg2 = "les amis !!";

msg = msg1 + msg2;


Que vaut msg ?? il est la concaténation de msg1 et msg2, soit : Kikoooooles amis !! On remarque qu'il y a un problème d'espacement, ce qui est normal, vu que msg1 et msg2 ne contiennent pas d'espace. Pour que le message soit correct, je dois ajouter un espace entre msg1 et msg2...
Ce qui nous donne :

msg = msg1 + " " + msg2;

Et là, ca marche !!
Les guillemets sont les délimiteurs de la chaine... mais alors, comment faire si je veux une chaine de caractères qui contienne des guillemets ?? Il faudra pour cela utiliser le caractère d'échappement \, qui despécialisera les guillemets :

msg = "Comment ca \"lapin\" ?? ";

La chaine msg, si on l'affiche donnera : Comment ca "lapin" ??
Voici les caractères d'échappement du LSL :

\t tabulation
\n passage à la ligne
\" "
\\ \



Quelques fonctions sur les chaines......



llStringLength compte le nombre de caractères d'une chaine

string msg = "Youppi c'est les vacances !!";
llWhisper(PUBLIC_CHANNEL, msg + " contient exactement " + (string)llStringLength(msg) + " caractères...");


Nous lirons sur le chat : Youppi c'est les vacances !! contient exactement 28 caractères...
Une petite remarque.... que viens faire ici (string) ??
La fonction llStringLength renvoie un nombre entier.... or, un nombre n'est pas une chaine de caractères.... Je dois donc convertir l'entier en string par l'opération de cast (cf un des précédent cours...). Ici je caste en string donc : (string).
Il s'agit la d'une erreur fréquente... le compilateur refuse de faire son travail et nous donne une erreur dans le message que l'on veut écrire sur le chat..... bien souvent, c'est parce que la chaine que l'on veut écrire, contient un morceau qui n'est pas du type string... L'ajout du cast (string) résoud bien souvent le problème.



llGetSubString permet d'extraire d'une chaine une sous chaine.
Prototype de la fonction : string llGetSubString(string msg, integer debut, integer fin)
Par exemple : dans l'exemple suivant, on va extraire juste le mot "les"..... (le mot "les", pas le mot laid, ou le Molay, car pour ce dernier, c'est impossible depuis 1314... hihi)

string msg = "Youppi c'est les vacances !!";
msg = llGetSubString( msg, 13, 15 );
llSay(PUBLIC_CHANNEL, msg);


La première lettre de la chaine est indicée 0...... donc je prends les caractères en commençant au caractère d'index 13 et termine au 15 inclus...



llSubStringIndex permet de savoir si une chaine donnée est incluse dans une plus grande.. et si oui à quel endroit....
Elle renvoie donc un entier correspondant à l'index de la sous chaine, et elle renvoie -1 si elle ne trouve pas.
Prototype : integer llSubStringIndex(string msg, string sous_chaine);

Exemple : ma chaine contient-elle le mot Ouma ??

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 !!");


Si j'exécute ce code..... je peux lire dans le chat : Ouma est la !! hihi.... J'aime faire participer, à leur insu, mes amies à mes cours !!


Autre exemple d'application de cette fonction : beaucoup d'objets fonctionnent avec une notecard qui contient des informations pour paramétrer l'objet. En général, on note des informations sur une ligne, et chaque ligne contient ainsi plusieurs paquets de paramètres.
Illustrons cela par un exemple : nous ne verrons pas ici la lecture de la notecard, mais seulement le traitement de la ligne....
Ma notecard contient un nom d'avatar puis un point virgule, puis un nombre. Et ainsi de suite sur chaque ligne....

par exemple :
Deirdre;25
Yoyo; 27
Ouma;32
Lala; 36
Nounours;34




Dans mon script, je récupère une ligne de cette notecard dans une variable ligne. Je veux ensuite affecter le nom à la variable nom, et le nombre à la variable nombre....... Pour cela, je vais agir de la manière suivante : créer deux sous chaines : de 0 à index de ";" et de index de ";" à fin.... Mon pivot est donc l'adresse du ";".

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);



Pour le nom, llSubStringIndex(ligne, ";") me donne l'index du ";". Or je ne veux pas de lui dans le nom... d'où le -1 qui recule l'indice....
De même, pour le nombre, je me place apres l'index pour commencer à le lire....
Remarquez aussi que je vais jusque llStringLength(ligne), qui correspond a la longueur de ma chaine. J'aurais pu aussi écrire :

nombre = llGetSubString(ligne, llSubStringIndex(ligne, ";") + 1, -1);

Ici, -1 signifie : le dernier caractère de la chaine. Cette version est préférable, car elle evite l'appel à une nouvelle fonction, et rendre le code plus aisé à lire, à partir du moment où on sait ce que ce -1 veut dire bien sur.


Il existe d'autres fonctions concenrant le traitement des string. Je n'en ai présenté ici que quelques unes, pour donner une idée de leur utilisation.
C'est tout pour aujourd'hui.

16 octobre 2008

Poême Zen....

Je dédis ce petit poême Zen  à Lanna, ma Senseï.
Elle comprendra :)


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

Que cette pensée t'apporte la paix et la sérénité Ô Senseï.....
Et n'oublie pas que :

La noirceur de l'ombre des pins
dépend de la clarté de la lune
Kodo Sawaki



8 octobre 2008

Cours d'initiation au langage LSL (IV)

Aujourd'hui, nous allons voir les fonctions LSL liées aux variables de type KEY, ainsi que quelques constantes utilisables à tout moment dans vos scripts, sans avoir besoin de les définir, cela est déjà fait dans le langage LSL.

Mais avant, voici quelques fonctions essentielles et les plus courantes du LSL...



I. Les fonctions de communication


Pour communiquer, un objet fait appel à un certain nombre de fonctions. Pour parler, on doit le faire dans un canal de chat. Le canal lisible par tous est le canal publique 0. Tout ce qui est dit sur ce canal est perceptible par tous, dans une limite de distance.


Une limite ??

Et oui, quand on chuchote, parle ou crie, on touche plus ou moins de personnes. Ainsi :


Chuchoterwhisper10m
Parlersay20m
Criershout100m



L'avatar ne peut que parler ou crier, mais un objet scripté peut en plus chuchoter.

Par contre, on peut choisir le canal sur lequel on parle. Si on ne précise rien, il s'agit du canal 0.
Si on veut parler sur un autre canal, on doit ecrire le numéro du canal précédé de /
Par exemple :

/100 kikooooo !

Ecrira donc "kikooooo !" sur le canal 100.

Toutefois, un avatar ne peut pas écouter sur ce canal, et toute phrase écrite dessus ne produit rien sur le chat (qui est le canal 0). Par contre un objet le peut (nous verrons comment plus tard). C'est de cette manière que l'on peut commander certain objet via le chat.

Si je veux faire cracher du feu à mon dragonnet, je lui parle sur le canal 28 (par exemple).
Ainsi : /28 flammeon, et il souffle, et /28 flammeoff, et il s'arrete. Personne ne m'a vu écrire un ordre, ni quel est cet ordre, ni le canal que j'utilise.

Ainsi donc, dans toutes les fonctions qui vont suivre, l'un des paramètres est ce canal.
Toutefois, pour plus de compréhension dans la lecture du script, on evitera d'écrire 0 pour indiquer le canal public.
Il existe des constantes que l'on utilisera. Ecrire le nom de la constante revient à ecrire la valeur à laquelle elle correspond, mais en rendant son script plus lisible.
  • PUBLIC_CHANNEL : le chat public, de valeur 0

  • DEBUG_CHANNEL : le canal utilisé pour le débuggage de script


1) Chuchoter, parler, crier.


llWhisper(integer channel, string message);
llSay(integer channel, string message);
llShout(integer channel, string message);


  • channel : le canal ou l'on parle

  • message : le message.


Par exemple :

llWhisper(PUBLIC_CHANNEL, "Bisous toi !!");
llSay(PUBLIC_CHANNEL, "Bonjour à tous !!");
llShout(PUBLIC_CHANNEL, "Lapin !!!!");



Note : Lapin ??
Ben oui.... vous savez comment on dit lapin à un sourd ?? non ?? on dit : LAPIN !!




2) Plus loin c'est possible ?

Et oui, un objet peut parler sur une sim entiere. Mais attention, il ne peut pas le faire sur le canal PUBLIC_CHANNEL. Imaginer le spam sur une sim où toutes les dix secondes, on aurait une voix qui parlait !!!

llRegionSay(integer channel, string message);



3) Plus prêt, dans le creux de l'oreille ? Rooooo !!

Encore oui !! Rooooo derechef !! Cela est possible.
L'objet parle dans le chat, mais seul son propriétaire peut entendre ce qu'il dit. Dans ce cas pas besoin de préciser le canal, il n'y a que le message en paramettre à cette fonction. Le message s'affiche dans votre fenetre de chat, dans une couleur jaune, indiquant que seul vous pouvait l'entendre


llOwnerSay(string message);


4) Il y a autre chose ?

Oui, mais nous verrons plus tard; Il s'agit de la petite boite de dialogue bleue, qui apparait dans le coin supérieur droit de la fenetre de SL.
Elle fait dejà l'objet d'un tutorial entier.



II. Tout (ou presque) sur les KEY



Petit retour sur les Key.
C'est un identifiant unique, ou UUID pour Universally Unique Identifier, qui caractérise chaque objet de SL. C'est en fait une STRING dont le format est défini d'une certaine manière. Un UUID est donc stocké dans une variable de type KEY.

Masque d'une Key : XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, soit donc une série de 5 nombres ecrits en base hexadécimale. Par exemple : 153f69ca-1de5-ffff-0000-125cb84a58e2.

Il existe pour les Keys une constante, la clé "nulle" :
  • NULL_KEY , de valeur : 00000000-0000-0000-0000-000000000000


llGetKey( ) ==> key

Cette fonction retourne la Key de l'objet qui la contient, ou pour etre plus précis, du prim dans lequel se trouve le script. Ainsi, un objet constitué de plusieurs prims possède une Key par prim le composant.



llDetectedKey( integer number ) ==> key

number représente la valeur de l'index de détection.
Cette fonction sert souvent pour connaitre la key d'un objet détecté.
Exemple d'utilisation : connaitre qui touche l'objet. L'index correspondant à un avatar est 0.


default
{

touch_start(integer total_number)
{
key k = llDetectedKey(0);
llSay("j'ai été touché par " k);
}
}



Créez un objet et copier ce script dedans. Puis cliquer sur l'objet, et vous obtiendrez une key qui est celle de votre avatar, votre UUID personnel.



llKey2Name( key id ) ==> string

Cette fonction renvoie de le nom correspondant à la prim ou à l'avatar dont la key est passée en paramètre.
Nous pouvons utiliser cette fonction avec celle vue précedemment. llDetectedKey donne la clé de celui qui touche, et passe cette clé à llKey2Name, qui la convertit en un nom.

Exemple :


default
{

touch_start(integer total_number)
{
llSay("Bonjour " llKey2Nam(llDetectedKey(0)));
}
}




llGetOwnerKey(key id) ==> key
llGetOwner() ==>key


La fonction llGetOwnerKey retourne la clé du propriétaire de l'objet que l'on passe à la fonction par sa key.
llGetOWner retourne la key du propriétaire de l'objet.

Arrêtons sur ce point. Imaginons un objet qui effectue une action quand on le touche. Je veux que seul le propriétaire de l'objet puisse le faire fonctionner. Pour cela il faut que je regarde si celui qui le touche est bien le propriétaire. Cela se fera par key interposées.



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 !!);
}
}
}



Encore une petite chose.
Si on donne notre objet à quelqu'un, le propriétaire change. Notre objet doit donc obéir à son nouveau propriétaire. Toutefois, la valeur retournée par llGetOwner n'est pas remise à jour immédiatement, ni automatiquement. D'où la présence de l'évenement on_rez, qui est appelé lorsque l'on pose l'objet au sol, ce qu'on appelle faire un rez de l'objet. C'est en général la technique la plus souvent utilisée.
Mais imaginons un objet que l'on porte sur soi.... On ne vas pas tout le temps le poser au sol, cela est casse pied. Pour l'utilisateur final qui se moque bien de savoir comment ca marche, ce n'est pas très pratique...

Alors ??

Et bien, on va utliser le bout de code suivant. Il suffit de l'ajouter dans le script et le tour est joué. L'evenement est appelé chaque fois que quelque chose change dans l'objet. Ici on ne s'interesse qu'au changement de propriétaire. Nous verrons cet evenement plus en detail plus tard.


changed(integer change)
{
if (change & CHANGED_OWNER)
llResetScript();
}



La fonction llResetScript permet de réinitialiser un script.
Dès que l'objet change de proprietaire, l'evenement changed est appelé, et fait un reset du script.

Il faut savoir que lorsque l'on utilise un objet, les variables qui le contiennent varient en fonction de ce que leur demande le script. Si je range l'objet dans mon inventaire, l'etat de ces variables est sauvegardé. Et lorsque je le sors, je le retrouve avec ces variables.
Ce qui signifie que si il y a une erreur de code dans mon script qui fait "planter" l'objet, le fait de le remettre dans mon inventaire et de le ressortir ne sert à rien. Si c'est un petit plantage de sl, là, cela fonctionne. Parfois, mon katana plante et ne fonctionne plus. Le seul moyen pour moi pour le refaire fonctionner est de le réinitialiser entièrement, en posant au sol la boite que j'ai achetée, qui me rend un katana tout neuf, avec des variables réinitialisées.




III. Conclusion


Voila pour aujourd'hui. La prochaine fois, nous étudierons en detail quelques fonctions très utiles concernant le type STRING, ainsi que le type LIST, si j'ai du courage !!