1 - Introduction

LUA est un langage de scripting principalement conçu pour être intégré dans des applications hôtes. Il est parfait pour
apprendre les bases de la programmation puisqu’il contient tous les éléments que l’on retrouve dans tous les autres langages.
L’application hôte qui permettra d’exécuter du code LUA en situation réelle est
Demoniak3D.
Mais nous utiliserons aussi l’interpréteur lua.exe pour une utilisation immédiate et simple en ligne de commande.
Liens:
- LUA home page: le site officiel de LUA.
- LUA.exe: l'interpréteur LUA en ligne de commande.
- XpConfigurator: l'utilitaire qui permet d'ajouter l'ouverture d'un shell DOS au clic droit de la souris dans l'Explorer. Pratique pour tester ses codes LUA avec l'interpréteur en ligne de commande.
Mais avant de commencer, nous allons faire le classique "Hello World", histoire de verifier que l'interpréteur en ligne de commande est
opérationnel. Pour cela, copiez le code suivant dans un fichier que vous appelerez
hello.lua:
print("Hello World From LUA!");
Code 1 - Hello World!Mettez ce fichier dans le même répertoire que lua.exe et ouvrez un shell dans le répertoire de l'interpréteur. Maintenant vous pouvez
exécuter ce premier script avec la commande suivante:
lua hello.lua
Si tout s'est bien passé, le résultat doit être comparable à la figure 1:

Fig. 1 - Votre premier script LUA!Pour écrire du code LUA, il vous faut un éditeur de texte (j'ai pas dit un logiciel de traitement de texte!). Voici une petite sélection de quelques éditeurs
gratuits et commerciaux:
- Notepad++: simple, performant, régulièrement mis à jour et gratuit.
Coloration syntaxique pour la plupart des languages (LUA, XML, C/C++ HTML, VBS, Java, ...). C'est ce que j'utilise en ce moment.
- Crimson Editor: simple, performant et gratuit.
Les mises à jour sont peu fréquentes. Coloration syntaxique des languages.
- Ultra-Edit: un éditeur de texte ultra performant. Payant (environ 40.00$).
2 - Variables

La variable est un des concepts les plus fondamentaux de la programmation. Une définition assez générale de la variable peut être:
emplacement mémoire permettant de stocker une donnée.
Comme dans beaucoup de langages de scripting (PHP, VBScript, ...),
les variables en LUA ne sont pas typées (typeless). Cela signifie qu'une variable
peut contenir aussi bien une valeur numérique, qu'une chaîne de caractères, ou même une variable (simple ou complexe).
De plus,
aucune déclaration n'est à faire avant d'utiliser une variable. On peut l'utiliser directement. C'est
simple mais cela peut parfois poser des problèmes lors du codage de scripts volumineux. J'aurais bien apprécié la
possibilité d'activer une option du langage pour forcer la déclaration des variables avant leur utilisation.
Voilà un exemple tout simple:
a = 10;
b = 3;
sum = a + b;
print("Sum = " .. sum );
Code 2 - AdditionneurExécutez-le, le résultat doit être:

Fig. 2 - L'additionneur en action.Un autre point à aborder est celui de la portée ou visibilité des variables. Par défaut
les variables en LUA
sont globales. Cela signifie qu'une variable peut être utilisée dans différents scripts, lorsque ces différents
scripts font partie du même contexte d'exécution, comme c'est le cas dans les démos Demoniak3D (script d'initialisation,
script d'update, ...). Les variables globales sont donc très pratiques dans tous les cas où l'on a besoin de communiquer
des données entre différents scripts, ou lorsque l'on a besoin de données persistantes.
Nous aurons l'accasion de voir un exemple de compteur de frames dans un des tutoriels consacrés à l'utilisation de LUA dans Demoniak3D.
Si vous avez besoin de limiter la porté d'une variable, il suffit d'ajouter le mot clé (mot réservé du langage)
local
devant la variable:
a = 10;
local b = 3;
sum = a + b;
print("Sum = " .. sum );
Code 3 - Création d'une variable localeLes variables que nous venons de voir sont des variables simples, dans le sens où elles contiennent des valeurs simples
(nombre et/ou chaîne de caractères). Dans de nombreux cas, dépendants bien sûr des algorithmes employés ou du niveau d'abstration
en cours, nous avons besoin de définir des variables un peu plus sophistiquées. Un exemple simple est la manipulation de vecteurs 3D.
Il est dans ce cas plus simple de manipuler une seule variable contenant les 3 composantes du vecteur, que de manipuler 3 variables
représentant chacune une composante. La création d'une variable qui nous permettrait d'agir sur des vecteurs 3D peut se faire
de la manière suivante:
vecA = {x=2.0, y=-1.0, z=0.0};
vecB = {x=-4.0, y=0.0, z=-2.0};
vecSum = vecB;
vecSum.x = vecA.x + vecB.x;
vecSum.y = vecA.y + vecB.y;
vecSum.z = vecA.z + vecB.z;
Code 4 - Création de variables complexesUne autre catégorie de variables couramment utilisée est le tableau. Un tableau peut se définir comme un ensemble de variables qui peuvent
être accédées par un indice. Un tableau se note avec le symbole []. Chaque valeur contenue dans une case du tableau se nomme
élément.
Le code suivant nous donne un exemple:
-- Array creation.
myArray = {};
-- Array initialization.
myArray[0] = 10.0;
myArray[1] = 20.0;
myArray[3] = "Hello";
vecA = {x=-4.0, y=0.0, z=-2.0};
myArray[4] = vecA;
Code 5 - Création et initialisation d'un tableau 3 - Fonctions

LUA, comme tout bon langage qui se respecte, nous donne la possibilité de créer des fonctions. Une fonction peut être
vue comme une séquence d’instructions masquée derrière un nom unique et permettant de réaliser une action ou d’agir sur
des données. Une fonction permet simplement de factoriser le code afin d'éviter de coder plusieurs fois une même suite
d'instructions.
Il existe dans LUA 2 catégories de fonctions:
- Fonctions existantes: librairies standards de LUA - cas de la fonction print().
- Fonctions utilisateurs: créées par le développeur
Le cas intéressant est celui des fonctions utilisateurs.
Reprenons notre addition de tout à l'heure mais, maintenant, créons une fonction pour additionner 2 nombres. Cette fonction
additionnera les 2 nombres et affichera la somme:
function add( a, b)
local sum = a + b;
print( "Sum = " .. sum );
end
add(12, 45);
add(548.02, 14587.2298);
add(-1, 1);
Code 6 - Création d'une fonctionUne fonction peut aussi retourner une valeur. Modifions légèrement notre additionneur pour qu'il nous retourne la somme des 2 nombres
passés en paramètre:
function add( a, b)
local sum = a + b;
return(sum);
end
local sum = add(12, 45);
sum = add(548.02, 14587.2298);
sum = add(-1, 1);
Code 7 - Création d'une fonction additionLa variable retournée peut être simple ou complexe comme le montre l'exemple suivant:
function createVec(_x, _y, _z)
local out = {x = _x, y = _y, z = _z};
return(out);
end
function addVec( u, v )
local out = {x=0.0, y=0.0, z=0.0};
out.x = u.x + v.x;
out.y = u.y + v.y;
out.z = u.z + v.z;
return(out);
end
function printVec( v )
print( "vector: <" .. v.x .. ", " .. v.y .. ",
" .. v.z .. ">" );
end
local vecA = createVec(0.22, 0.45, -0.66);
local vecB = createVec(-012, 0.55, 0.59);
local vecSum = addVec(vecA, vecB);
printVec( vecSum );
Code 8 - Création d'une fonction complexeL'exécution du code 8 donne le résultat suivant:

Fig. 3 - L'addition de vecteurs. 4 - Séquencement des données - Structures de contrôle

Le séquencement des données est le terme technique qui engloble toute la logique permettant de contrôler le
flux de données. Cela comprend principalement:
- les structures de tests conditionnels
- les structures itératives
4.1 - Tests conditionnels
Les tests conditionnels se font avec la construction
if - then - else. Un exemple simple qui se prête
à merveille aux tests conditionnels est la résolution de l'équation du second degré ax^2 + bx + c = 0.
Le code suivant applique l'algorithme classique (calcul du déterminant et test de celui-ci) pour la résolution
de l'équation:
--
-- Resolution de l'equation du second degre: ax^2 + bx + c =0
--
text = "";
a = 2.0;
b = 1.0;
c = -2.0;
print( "\nEquation " .. a .. "x^2 + " .. b .. "x +
" .. c .. " = 0\n" );
-- 1) Calcul du determinant
--
delta = b*b - (4 * a * c );
-- 2) Solutions en fonction de la valeur du determinant.
--
if( delta<0 ) then
text = "Il n'y a aucune solution reelle."
elseif( delta == 0 ) then
x = -b / (2 * a);
text = "Il y a une solution reelle: x=" .. x;
else
x1 = (-b + math.sqrt(delta)) / (2*a);
x2 = (-b - math.sqrt(delta)) / (2*a);
text = "Il y a deux solutions reelles: x1=" .. x1 .. "
et x2=" .. x2;
end
print( text );
Code 9 - Résolution de l'équation du second degréJe vous laisse le soin de tester vous-même ce code...
4.2 - Structures itératives
Les structures itératives nous permettent de répéter une séquence d’opérations un certain nombre de fois.
Les itérations se font avec
while / do-while / repeat-until / for.
L'exemple suivant montre comment calculer la somme des 100 premiers entiers à l'aide des itérateurs:
sum = 0;
loop_counter = 0;
limit_sup = 100;
while( loop_counter<limit_sup ) do
sum = sum + loop_counter;
loop_counter = loop_counter + 1;
print( "Somme intermédiaire = " .. sum );
end
print( "
La somme des " .. limit_sup .. " premiers entiers est: " .. sum );
Code 10 - Somme des 100 premiers entiers
L'exemple suivant montre comment utiliser une boucle for:
for j=0,10 do
for i=0,10 do
print( "j=" .. j .. " i=" .. i );
end
end
Code 11 - Boucle forIl est possible de sortir prématurément d’une itération avec le mot clé
break.
Pour cloturer cette initiation à LUA, je vous propose un exemple complet qui utilise tout ce que l'on a vu
jusqu'à présent: l'implémentation LUA du célèbre algorithme du
tri à bulles (le bubbleSort). Le script est divisé
en 3 grandes parties:
- Partie 1: création d'un tableau contenant MAX_SIZE éléments. La valeur de chacun des éléments est générée aléatoirement
grâce à la fonction random() de la librairie standard math.
- Partie 2: tri en ordre décroissant des éléments du tableau à l'aide de l'algortihme bubble sort.
- Partie 3: affichage des éléments triés.
-- 1) creation et initilisation d'un tableau
--
myArray = {};
MAX_SIZE = 10;
i = 0;
while( i<MAX_SIZE ) do
myArray[i] = math.random(200);
print( "myArray[" .. i .. "]=" .. myArray[i] );
i = i + 1;
end
-- 2) tri du tableau avec l'algorithme du tri a
-- bulles (bubblesSort)
--
num_swaps = 0;
i = 0;
while( i<MAX_SIZE ) do
j = i+1;
while( j<MAX_SIZE ) do
if( myArray[j] > myArray[i] ) then
tmp = myArray[j];
myArray[j] = myArray[i];
myArray[i] = tmp;
num_swaps = num_swaps + 1;
end
j = j + 1;
end
i = i + 1;
end
-- 3) affichage du tableau trie
--
print( "
Et voila le tableau trie:
" );
i = 0;
while( i<MAX_SIZE ) do
print( "myArray[" .. i .. "]=" .. myArray[i] );
i = i + 1;
end
print( "\nIl y a eu " .. num_swaps .. " swaps pour
trier ce tableau" );
Code 12 - Tri à bullesL'exécution du code 12 donne le résultat suivant:

Fig. 4 - Tri à bulles. 5 - Conventions de codage

Les conventions de codage sont très importantes pour ne pas dire primordiales pour obtenir du code clair, fonctionnel, facile à lire
et surtout FACILE A DEBOGUER! Chacun est libre d'adopter les conventions de codage qui lui plaisent, le principal étant d'arriver aux
objectifs cités précédemment. Pour ma part voici celles que j'utilise:
- Préfixer le nom des variables globales par g_. Exemple: g_frame_counter = 0;
- Toujours ajouter d'un point-virgule à la fin de chaque instruction. En effet, LUA est très souple et n'oblige pas à préciser de manière explicite
la fin d'une instruction. Mais il est conseillé de le faire afin de simplifier la vie du parser / compiler LUA.
- Bien identer son code et respecter les hiérarchies d'identation. Voir l'algo du tri à bulles pour une exemple.
- Nommer de manière explicite les noms variables et de fonctions. Ceci est fondamental pour la lecture et la compréhension d'un code LUA complexe. Il est plus
facile de comprendre à quoi sert la variable g_position_sphere_red_x que x1...
- Préfixer une variable de type tableau par arr. Exemple arr_sphere_clones ou g_arr_sphere_clones si la variable est globale.
- Préfixer une variable avec i, f ou str pour indiquer si elle contient une valeur numérique entière (i), réelle (f) ou une chaîne de
caractères (str). Exemple: g_i_status, str_name, g_f_position_x.
- Mettre des commentaires (--). Les commentaires ont un triple rôle: ils vous permettent de faire le point sur ce que vous être en
train de coder, ils vous permettent de savoir ce que vous avez codé et enfin ils permettent aux autres de savoir ce que vous avez tenté
de coder...
6 - Downloads

 | Téléchargez les codes sources d'accompagnement + Interpréteur LUA Mise à jour: 5 Octobre 2005 |