Script: déplacer un marqueur avec un véhicule
Avant d'entamer ce tutoriel, je vous recommande de relire les tutoriels suivants:
Mission du tutoriel
Déplacer un marqueur avec un véhicule au travers de l'éditeur
Dans ce point nous allons créer un petit script à placer dans l'initialisation du véhicule qui va déplacer un marqueur en même temps que le véhicule ce déplace. Je vous laisse imaginer à quoi cela peut servir.
Le marqueur de respawn d'un camp est un marqueur comme un autre... vous pouvez donc le déplacer avec un véhicule.
Commençons par placer un marqueur:
Ensuite on va placer un hunter et vous pouvez lui donner l'initialisation suivante:
Code : Tout sélectionner
nul = this spawn { while { alive _this } do { "marqueur_veh" setMarkerPos (position _this); sleep 2; }; };
Une fois que c'est fait, testez que tout fonctionne comme prévu. Si ce n'est pas le cas, vérifiez que vous n'avez pas fait de fautes de frappe et que toutes les parenthèses et accolades sont là où elles doivent.
Je vais détailler le contenu de cette ligne de code dans un instant.
Analysons le code pas à pas
Pour pouvoir analyser le code, je le réécris d'une manière plus lisible:
Code : Tout sélectionner
nul = this spawn {
while { alive _this } do {
"marqueur_veh" setMarkerPos (position _this);
sleep 2;
}; // Accolade de while
}; // Accolade de spawn
nul =
La commande
spawn renvoie une référence au script qu'elle exécute, ce qui permet, entre autre, à l'aide de la commande
scriptDone de savoir si l'exécution est finie.
Le problème, c'est que l'éditeur d'ArmA n'accepte pas que le code d'initialisation renvoie une valeur. Pour cette raison, on doit assigner la valeur renvoyée par la commande à une variable globale choisir arbitrairement.
"
nul" est donc notre variable globale et reçoit la valeur renvoyée par
spawn.
Si vous ne récupérez pas cette valeur, voici le message d'erreur que vous aurez:
Donc, si la dernière commande que vous utilisez dans votre code renvoie une valeur, il faut toujours l'assigner à une variable.
this spawn { ... };
Le mot clé "
this", qui signifie "ce/cet/cette" en anglais, représente le véhicule que vous éditez. Etant donné que nous voulons exécuter du code lié à l'objet qu'on est en train d'éditer, nous utilisons "
this".
La commande
spawn permet de lancer l'exécution d'un sous-script qui s'exécute dans son propre environnement.
Pourquoi utilisez cette commande ici?
Simplement parce que si vous lancez un script sans fin dans l'initialisation du véhicule, ce véhicule ne terminera jamais son initialisation et la mission ne démarrera jamais... c'est aussi simple que ça.
On doit donc quitter le contexte de l'initialisation et lancer un script secondaire.
Les accolades
{ } servent à délimiter le code du sous-script. Tout le code qui doit être exécuté par la commande
spawn DOIT se trouver entre ses accolades.
Le point virgule "
;" à la fin d'une commande sert à délimiter cette commande, si vous ne l'ajoutez pas, vous aurez des erreurs de script. Terminez TOUJOURS votre commande par un point virgule.
Maintenant, pourquoi écrire "this spawn { ... }".
Cette manière d'écrire indique à la commande
spawn qu'on lui passe comme paramètre la variable "this". Celle-ci étant le véhicule en cours, la commande spawn reçoit comme seul paramètre le véhicule.
while { alive _this } do { ... };
Examinons maintenant le contenu du script exécuté par
spawn.
La première commande est
while, qui permet d'exécuter du code en boucle. On peut la traduire par "Tant que".
alive est une commande qui renvoie une valeur booléenne (vrai ou faux) si l'argument qui lui est passé est en vie.
Dans notre cas, vous voyez que nous lui passons "_this". Attention!!! "_this" (notez l'underscore) est différent de "this".
Quand vous démarrez un script (comme ici avec
spawn, ou
call, ou
execVM) tous les paramètres passés à ce script sont contenus dans la variable spéciale "_this" qui est une variable locale au script (elle commence par un "underscore").
Si vous avez besoin de plus de détails sur les variables globales et locales, lisez le tutoriel qui y est consacré:
ICI.
Donc, étant donné que nous avons passé à
spawn la variable "this" contenant le véhicule, nous reçevons donc le véhicule dans "_this".
La commande "alive _this" renvoie donc "true" (vrai) lorsque le véhicule est en vie.
Le mot clé
do (qu'on peut traduire par "faire") permet d'indiquer quel code sera exécuté par la boucle si la condition est vraie.
Notre code se traduit donc par:
Tant que le véhicule est vivant, faire ceci.
"marqueur_veh" setMarkerPos (position _this);
"marqueur_veh" est une chaîne de caractère (on le sait parce que le mot est délimité par des guillemets). Les marqueurs sont un cas particulier.
Les fonctions des marqueurs demande comme paramètre le nom du marqueur sous forme d'une chaîne de caractère.
Comme nous souhaitons changer la position du marqueur avec celle du véhicule, il suffit de l'identifier par son nom.
setMarkerPos est une commande qui permet de modifier la position d'un marqueur. Cette commande accepte deux arguments. En début de commande, le marqueur sur lequel appliquer la commande et en fin de commande, la nouvelle position.
(
position _this) renvoie la position du véhicule. La commande
position attend un seul argument, l'objet dont elle doit renvoyer la position. Si l'objet n'existe pas, elle renvoie [0,0,0] (le coin inférieur gauche de la carte).
On lui passe évidemment "_this" qui représente notre véhicule.
Les parenthèses sont utilisées pour grouper des éléments. Dans notre cas, "
position" et "_this". Ca permet à ArmA de savoir dans quel ordre il doit exécuter les commandes. Ici, le moteur d'ArmA voit qu'ils sont en parenthèses, donc il exécutera d'abord "
position _this" et ensuite seulement
setMarkerPos.
Si on écrit:
"marqueur_veh" setMarkerPos position _this;
On peut avoir le risque que le moteur ne sache pas dans quel ordre exécuter les commandes.
Bon, en pratique le moteur sait généralement ce qu'il doit faire, mais parfois il se mélange les pinceaux et ça donne des erreurs bizarres...
Donc, si vous groupez des commandes, utilisez les parenthèses!!!!
En plus ça rendra votre code plus lisible et vous vous en féliciterez la prochaine fois que vous devrez relire votre code.
Et on termine évidemment par un point virgule "
;" pour clôturer la commande.
sleep 2;
La commande
sleep ordonne au script de faire un pause pendant X secondes (deux dans notre cas).
C'est utile pour éviter de surcharger le serveur avec des exécutions inutiles. Si le marqueur bouge toutes les 2 secondes c'est BIEN suffisant.
Si vous ne mettez pas cette commande, le code de la boucle
while sera exécuté TRES souvent, ce qui aura un impact très négatif sur les performances du serveur si vous avez beaucoup de véhicules avec des marqueurs (ou d'autres scripts tout simplement).
Donc, partout où c'est possible, pensez à introduire des commandes "
sleep" pour alléger le poids de vos scripts pour le serveur.
Déplacer le marqueur à l'aide d'un script dans le répertoire de mission
Nous abordons maintenant l'éternelle question... "To script or not to script".
Faut-il créer un fichier script ou appliquer le code dans l'éditeur.
Pour moi la réponse est simple, si vous répondez "Oui" à l'une de ces questions, vous créez un fichier script:
- Vous comptez utiliser ce code pour plusieurs objets?
- Vous avez des idées pour améliorer ce script dans le futur?
- Vous pensez réutiliser ce script dans d'autres missions?
Pour créer un fichier de script, ouvrez le répertoire de votre mission, celui où se trouve le fichier "mission.sqm" et créez un nouveau fichier avec un
éditeur de texte quelconque.
Nommez ce fichier "marqueur_mobile.sqf".
L'extension ".sqf" n'est pas obligatoire, mais si vous utilisez un outil qui fait de la coloration de syntaxe, il faudra l'utiliser. Donc je vous conseille fortement d'en prendre l'habitude.
Placez un nouveau marqueur nommé "marqueur_veh2" avec le texte qui vous convient.
Ensuite placez un nouveau véhicule dans l'éditeur et donnez lui l'initialisation suivante:
Analysons le code pas à pas
Il n'y a qu'une ligne de code et elle ressemble énormément à ce que nous avons déjà vu, donc je ne m'attarderai que sur les nouveautés.
[this, "marqueur_veh2"]
Lorsqu'un bloc commence par la parenthèse carrée "[" c'est le début d'un tableau de valeurs. La fin du tableau est indiquée par la parenthèse carrée de fermeture "]" et chaque élément du tableau est séparé par une virgule "
,".
Un tableau de valeurs est une liste de valeurs regroupées ensemble pour former une seule variable.
Dans notre cas, notre tableau de valeur contiendra deux valeurs:
- La variable "this" qui représente le véhicule que nous éditons
- La chaîne de caractère "marqueur_veh2" qui est donc l'identifiant du marqueur à utiliser
execVM "marqueur_mobile.sqf";
A l'image de
spawn, la commande
execVM permet d'exécuter un script dans un nouvel environnement d'exécution, ce qui évitera donc de bloquer l'initialisation du véhicule.
Et, tout comme spawn, on passe peut passer un paramètre à la commande, c'est la raison pour laquelle on lui passe un tableau de valeur, pour qu'elle puisse recevoir 2 valeurs.
La commande est suivie par le nom du script, avec son chemin depuis le répertoire racine de la mission.
Dans notre cas, le fichier est dans le même répertoire que le fichier "mission.sqm", on peut donc directement lui donner son nom.
Si le fichier se trouvait dans un sous répertoire "scripts", la commande deviendrait:
nul = [this, "marqueur_veh2"] execVM "
scripts\marqueur_mobile.sqf";
Donc, pour résumer, la commande
execVM reçoit 1 paramètre, qui est un tableau qu'elle passera au script qu'elle reçoit comme deuxième paramètre.
Ajouter du contenu au fichier "marqueur_mobile.sqf"
Si vous lancez la mission maintenant, rien ne se passe avec le deuxième véhicule et pour cause... le fichier ne contient aucune commande.
Pour commencer nous allons ajouter du code qui nous permet de tester ce que reçoit le script.
Tapez ou copier la ligne de code suivante dans le fichier:
Sauvez les modifications et relancez la mission, vous devriez voir un message s'afficher avec le contenu suivant:
On voit donc que la variable spéciale "_this", contient un tableau avec les deux éléments prévus: le véhicule et le nom du marqueur.
Le charabia qui représente le véhicule n'a aucune espèce d'importance, c'est la manière dont ArmA référence les objets auquel on n'a pas donné de nom dans l'éditeur. Si vous aviez donné le nom "vec" dans l'éditeur au véhicule, vous auriez vu "vec" ici.
Faites le test...
Ecrire le script qui déplace le marqueur
Il est maintenant temps d'écrire le vrai code à exécuter:
Code : Tout sélectionner
private ["_veh","_marqueur"];
_veh = _this select 0;
_marqueur = _this select 1;
while { alive _veh } do {
_marqueur setMarkerPos (position _veh);
sleep 2;
};
Une fois de plus, je ne reviendrai pas sur les notions déjà vues et je vais passer directement aux nouvelles notions.
Avec une coloration de syntaxe on obtient:
private ["_veh","_marqueur"];
Un script lorsqu'il est exécuté possède deux types de variables, des variables locales et des variables globales.
Je vous invite à relire le
tutoriel sur les variables si ce n'est pas déjà fait.
Les variables locales sont soit déclarées dans le script, soit héritée du script qui l'appelle (on peut appeler un script, dans un script, dans un script, etc. à l'infini). Une variable qui ne doit exister que dans le script en cours doit être déclarée "
privée".
C'est le but de la commande
private on lui passe un tableau contenant tous les NOMS des variables que l'on souhaite garder privées.
Dans notre cas, notre script va utiliser deux variables: _veh et _marqueur.
On passe donc les deux noms (sous forme de chaînes de caractères) à la commande
private avant tout autre chose.
A noter, ce n'est pas obligatoire d'utiliser "private", mais dans les scripts plus complexes, vous risquez des effets de bord très bizarre si vous ne le faites pas... donc prenez de bonnes habitudes.
_veh = _this select 0;
Au début de la grande majorité des scripts vous verrez une ou plusieurs lignes de ce type.
Elles permettent d'assigner les paramètres reçus par le script (et contenus dans "_this") à des variables locales au script, pour pouvoir facilement identifier ce qu'on manipule.
La commande
select, permet de
sélectionner une valeur dans un tableau de valeurs. Les tableaux de valeurs dans ArmA sont référencés par un index numérique commençant pas "0". La première case du tableau a donc l'index 0, la deuxième 1, la troisième 2, etc.
Nous avons appelé le script avec la ligne de code suivante:
Code : Tout sélectionner
[this, "marqueur_veh2"] execVM "[b]scripts\[/b]marqueur_mobile.sqf";
Nous avons donc passé un tableau avec deux valeurs, la première, le véhicule est à l'index 0.
Donc, la ligne de code suivante:
Récupère la première valeur du tableau et la place dans la variable "_veh". Cette variable, à partir de maintenant, représente notre véhicule.
Le principe sera le même pour:
Qui va assigner la deuxième valeur du tableau à la variable "_marqueur".
while { alive _veh } do { ... };
La seule différence ici par rapport à l'exemple précédent, c'est qu'on utilise maintenant la variable locale "_veh" au lieu de la variable spéciale "this" pour représenter le véhicule.
_marqueur setMarkerPos (position _veh);
Même chose que pour le point ci-dessus, on utilise les variables locales au lieu des variables spéciales.
L'avantage ici, c'est que "_marqueur" peut contenir le nom de n'importe quel marqueur passé comme paramètre pas uniquement un seul marqueur. Ce qui rend le code réutilisable.
La règle est donc que si une valeur est amenée à changer suivant l'utilisation du script, vous devez en faire une variable qui est passée comme paramètre au script.
Si on avait simplement utilisé "marqueur_veh" à la place d'une variable, TOUS les véhicules auraient déplacé le même marqueur!!!! Ce marqueur n'aurait fait que sauter d'un bout à l'autre de la carte.
Et voilà... on y est, on a un marqueur mobile et le script qui le déplace.
Le marqueur bouge, victoire, et après?
Lorsque le véhicule est détruit, vous pouvez laisser le marqueur en place ou vous pouvez choisir de l'effacer. Si c'est le cas, à la fin de votre fichier, ajoutez la ligne de code suivante:
La commande
deleteMarker efface tout simplement le marqueur que vous lui passez.
Le marqueur disparaîtra lorsqu'on quitte la boucle
while. Et on ne quitte cette boucle que lorsque le véhicule est détruit.
C'est un bel exemple de l'utilité d'un script, imaginez, si vous avez placé 50 véhicules avec marqueurs... vous devriez changer l'initialisation de ces 50 véhicules sans faire de faute... ici, un seul fichier à modifier!
Conclusion
Le scripting est l'un des éléments les plus intéressants du moteur d'ArmA pour ce qui me concerne.
Ce tutoriel devrait vous ouvrir la porte pour l'écriture de vos premiers scripts.
Si vous avez des questions sur ce tutoriel, utilisez
le fil dédié!
Retour à la table des matières