Dans le précédent tutorial je vous ai proposé un toboggan et je vous avais promis une version plus élaborée qui pallie les défauts les plus évidents. En particulier le fait que la ball ne soit pas solidaire du toboggan peut poser quelques problèmes lors des déplacements. Sans parler de la perte éventuelle de la ball.
Je vous propose donc une version plus élégante dans laquelle la ball est contenue dans le toboggan. Un clic sur celui-ci fait apparaître un menu avec trois options :
|
Glissade |
Stop |
Position |
|
Cette option permet de faire apparaître la ball |
Cette option fait disparaître la ball |
Cette option permet de mémoriser la position et la rotation de la ball |
D’autre part la ball ne peut survivre sans le toboggan. Celui-ci envoie une information cyclique, sans cette information la ball se suicide.
On se retrouve avec deux scripts : un dans le toboggan et un dans la ball.
Le toboggan doit savoir effectuer les opérations suivantes :
Ø créer une ball en la positionnant correctement,
Ø supprimer la ball,
Ø demander à la ball sa position et sa rotation et mémoriser ces informations,
Ø envoyer une information cyclique à la ball pour lui demander de survivre.
Voici le code correspondant à ces objectifs pour le toboggan :
integer
canal_ball
; // Canal pour parler a
la ball
integer
canal_de_ball
; // Canal pour parler
au toboggan
integer
canal_menu
; // Canal pour le
menu
integer
ecoute
; //
Ecoute
list
menu;
// Options
du menu
vector
offsetPos
; // Offset de
positionnement
rotation
offsetRot
;
// Offset
de rotation
// Initialisation du
script
initialisations
() {
canal_ball
=
37;
canal_de_ball
=
38;
canal_menu
=
47;
menu
=["Glissade"
, "Stop"
, "Position"
];
offsetPos
=
<0.0,0.0,1.0>;
}
// Initialisation de la ball
rez_ball( ) {
//
Suppression eventuelle
llSay
(
canal_ball
, "Meurs"
);
// Calcul
du deplacement et de la
rotation
vector tobPos
=
llGetPos
();
rotation tobRot
=
llGetRot
();
vector DestPos
=
(offsetPos
*
tobRot
) + tobPos
;
rotation DestRot
=
offsetRot
*
tobRot
;
//
Creation de la ball
llRezObject
(
"ball", DestPos
,
ZERO_VECTOR
, DestRot
,
canal_ball
);
//
Activation du timer
llSetTimerEvent
(
60.0);
}
// Etat par
defaut
default
{
//
Entree de l'etat
state_entry(
) {
initialisations
();
}
//
Reinitialisation
on_rez(
integer
start_param
) {
initialisations
();
}
//
Touche
touch_start
(integer
total_number
) {
//
Suppression de l'ecoute eventuelle
llListenRemove
(
ecoute
);
// Mise en
place de l'ecoute
ecoute
=
llListen
(canal_menu
, "", NULL_KEY
, "");
//
Affichage du dialogue
llDialog
(
llDetectedKey
(0), "Choisissez une
option", menu,
canal_menu
);
}
//
Stimulation reguliere de la
ball
timer
(
) {
// Message pour la
ball
llSay
(
canal_ball
, "Vis"
);
}
//
Ecoute
listen
(integer
channel,
string
name,
key
id,
string
message
) {
//
Affichage de l'option choisie
llWhisper
(
0, name
+
" a choisi
l'option '" + message
+
"'."
);
//
Suppression de l'ecoute
llListenRemove
(
ecoute
);
//
Selection selon
l'option
if
(message
==
"Glissade"
) {
//
Affichage d'initialisation
llWhisper
(
0, "Initialisation du
toboggan");
// Initialisation de
la ball
rez_ball(
);
}
else
if
(message
==
"Stop"
) {
//
Suppression de la ball
llSay
(
canal_ball
, "Meurs"
);
//
Arret du timer
llSetTimerEvent
(
0.0);
}
else
if
(message
==
"Position"
) {
// Ecoute
de la ball
ecoute
=
llListen
(canal_de_ball
, "", NULL_KEY
, "");
// Demande
positions
llSay
(canal_ball,
"Positions"
);
}
else
if
(llGetSubString
(message,
0, 0) == "<"
) {
//
Reception des
positions
list
pos
=
llParseString2List
(message,
["|"], []);
offsetPos
=
(vector
)llList2String
(pos
, 0) - llGetPos
();
offsetRot
=
(rotation
)llList2String
(pos
, 1) / llGetRot
();
llWhisper
(
0, "Memorisation de la position " + (string
)offsetPos
+
" "
+
(string
)offsetRot
);
}
}
}
Sept variables nous sont nécessaires :
|
Variable |
Type |
Rôle |
|
canal_ball |
integer |
Canal du toboggan vers la ball |
|
canal_de_ball |
integer |
Canal de la ball vers le toboggan |
|
canal_menu |
integer |
Canal pour le dialog |
|
ecoute |
integer |
Mémorisation de l’écoute pour sa suppression |
|
menu |
list |
Données du dialog |
|
offsetPos |
vector |
Offset de positionnement de la ball |
|
offsetRot |
votation |
Offset de rotation de la ball |
La méthode initialisations permet de renseigner la valeur des canaux du chat et les données du Dialog. Les offset ont au départ une valeur nulle et l’écoute sera renseignée au moment nécessaire, c’est-à-dire lors de la création de l’écoute.
Une méthode intéressante est rez_ball qui permet de créer la ball. On commence par supprimer une ball éventuellement présente en envoyant un message de suicide. On calcule ensuite la position et la rotation de la future ball en se basant sur les informations de positionnement et de rotation du toboggan et de la valeur des offset. Je laisse les formules mathématiques aux amateurs de quaternions et autres fantaisies de ce genre pour en venir directement à l’importante fonction llRezObject. Celle-ci permet de créer un objet, ou plus exactement une instance d’un objet, parce que l’objet correspondant doit déjà exister dans l’objet qui contient le script. En d’autres termes dans notre cas la ball est déjà contenu dans le toboggan, on se contente d’en créer une instance. Observez les paramètres de cette fonction :
|
Paramètre |
Type |
Fonction |
|
Inventory |
string |
Elément de l’inventaire à instancier |
|
Pos |
vector |
Position de création |
|
Vel |
vector |
Vélocité de l’objet créé |
|
Rot |
rotation |
Rotation de création |
|
Param |
integer |
Paramètre libre |
Dans notre cas le premier paramètre correspond au nom de la ball contenue dans le toboggan. Le second et quatrième paramètres nous permettent d’ajuster la position et la rotation de la ball. Nous ignorons le troisième paramètre parce que nous voulons une ball immobile. Enfin nous profitons du dernier paramètre pour transmettre le canal d’écoute.
Tous les Rezzers que vous rencontrez sur sl sont fondés sur cette fonction ou sa sœur llRezAtRoot. Par exemple une maison imposante est découpée en morceaux et recréée sur place avec un Rezzer. Vous pouvez aussi imaginer un aménagement d’appartement modulable…
Je dois toutefois préciser que ce rezzer m’a passablement occupé ces derniers temps et mes amis sur sl s’amusaient de me voir en train de m’énerver sur mon toboggan. J’avais beau analyser mon code je ne trouvais pas la faille. Jusqu’au moment où j’ai eu l’idée de faire un essai avec des objets simples plutôt qu’avec les prims torturées de mon toboggan. Et là grosse surprise : tout fonctionnait parfaitement ! J’avais passé beaucoup de temps à chercher des erreurs qui n’existaient pas… Moralité : si vous voulez créer un rezzer utilisez plutôt une prim sans trop de modifications sinon vous risquer de galérer comme je l’ai fait avec des positionnements aléatoires. Il m’a suffit d’ajouter un cube à mon toboggan et de le définir comme root et tout s’est bien passé ensuite…
La dernière action de la méthode initialisations est de déclencher un timer réglé à 60 secondes pour envoyer une impulsion régulière à la ball pour lui demander de vivre. Ce que vous retrouvez dans la fonction timer avec le message « Vis » sur le canal de la ball.
Le reste du code ne présente pas de nouveauté. L’événement touch_start commence par supprimer une écoute éventuelle, mets en route l’écoute pour le dialog, et affiche le dialog.
L’événement listen récupère l’action de l’utilisateur :
|
Option |
Action |
|
Glissade |
Mise en œuvre de la méthode rez_ball |
|
Stop |
Envoi du message « Meurs » à la ball |
|
Position |
Ecoute de la ball et envoi du message « Positions » à la ball |
Lors de l’écoute de la ball le seul message qui peut revenir est celui qui contient les coordonnées. On teste le message avec la fonction llGetSubString qui permet d’extraire une sous-chaîne d’une chaîne en transmettant l’index du caractère de début et l’index du dernier à extraire. Pour extraire le premier caractère il faut mettre 0 pour les deux paramètres. Les coordonnées sont transmises sous le format string séparées par le caractère « | ». La fonction llParseString2List permet de récupérer dans une list les éléments séparés par le caractère passé en paramètre (en fait une liste de séparateurs au format string). Il suffit ensuite d’extraire les coordonnées avec un cast (transformation de type) et de les combiner aux coordonnées du toboggan pour obtenir les offset et les mémoriser.
Suite au tutorial suivant...





