Souvent, durant le développement d'un jeu, certaines procédures et certains calculs vous seront utiles plusieurs fois, à différents endroits de votre code. Dans cette situation, pour éviter de recopier du code déjà fonctionnel, à plusieurs endroits différents, vous créerez des fonctions réutilisables et configurables.
Cela a de nombreux avantages, comme un gain de temps au développement, à la maintenance de votre code, et une meilleure lisibilité et donc compréhension de celui-ci.
C'est un des moyens de mettre en œuvre la philosophie DRY (Don't Repeat Yourself - Ne vous répétez pas), qui est un des principes de base à respecter en programmation.
Les langages de programmation vous fournissent déjà un certain nombre de fonctions, qui font partie intégrante du langage. Elles permettent par exemple de manipuler les variables (tri de tableau, recherche dans une chaîne de caractères...), d'effectuer certaines opérations mathématiques (trigonométrie, logarithme, arrondir un nombre...), ou d'accéder à des fonctionnalités avancées du navigateur. Généralement, le site officiel d'un langage de programmation vous fournira une documentation détaillée du langage, et vous servira de référence pour toute information dont vous pourriez avoir besoin pour l'utilisation des fonctions natives du langage (nom de la fonction, paramètres à lui fournir, valeur qu'elle fournit en retour, avec des exemples pratiques). Dans le cas du JavaScript, le Mozilla Developper Network est la source à privilégier dans vos résultats de recherches.
Déclarer une fonction
Il existe différentes façons de déclarer une fonction, voici la syntaxe la plus simple:
function nomDeLaFonction(parametre1, parametre2) {
// Corps de la fonction
}
En détail: on commence par le mot-clé function
suivi du nom de la fonction, ensuite de parenthèses entourant le ou les paramètres nécessaire(s) à votre fonction et enfin des accolades autour du corps de votre fonction.
Dans de nombreux cas, le corps de votre fonction contiendra le mot-clé return
suivi du résultat de la fonction à retourner.
Les paramètres d'une fonction sont des données qui ne sont valables qu'à l'intérieur de cette fonction, au même titre qu'une donnée définie à l'aide du mot-clé
let
vu au chapitre précédent. Vous en définissez les noms selon ce qu'elles contiennent, et vous y avez ensuite accès de la même façon qu'une donnée classique. Elles sont ensuite automatiquement détruites lorsque la fonction a terminé d'effectuer les procédures qu'elle contient.
Un exemple concret
Disons que nous devions calculer la distance entre deux éléments de votre jeu en 2 dimensions – ça arrive tout le temps ! –. Nous pourrions définir une fonction nommée distance
et prenant en paramètre les coordonnées x
et y
des deux objets.
La distance entre les coordonnées x
de vos 2 éléments donne le côté horizontal d'un triangle rectangle. La distance entre les coordonnées y
donne le côté vertical du triangle. Et du coup en appliquant le théorème de Pythagore pour calculer l'hypoténuse du triangle, on obtient la distance entre les 2 éléments.
function distance(x1, x2, y1, y2) {
let deltaX = x2 - x1 // Delta X séparant les deux éléments
let deltaY = y2 - y1 // Delta Y séparant les deux éléments
// Théorème de pythagore: C² = A² + B²
let hypot = deltaX^2 + deltaY^2
return hypot^0.5 // On retourne la racine carrée de C²
}
Des paramètres optionnels
Il peut arriver qu'une fonction accepte un nombre variable de paramètres, on dit alors que les paramètres pouvant être omis sont optionnels.
Pour déclarer un paramètre optionnel, il suffit de lui définir une valeur par défaut à l'aide du signe égal, suivi de sa valeur dans le cas où le paramètre ne serait pas fourni.
Dans la continuité de la fonction précédente, nous pourrions intégrer le calcul de distance entre deux éléments dans un jeu en 3 dimensions, la seule différence par rapport au calcul précédent et qu'il faille ajouter le delta entre les positions z
des deux éléments:
function distance(x1, x2, y1, y2, z1 = 0, z2 = 0) {
let deltaX = x2 - x1 // Delta X séparant les deux éléments
let deltaY = y2 - y1 // Delta Y séparant les deux éléments
let deltaZ = z2 - z1 // Delta Z séparant les deux éléments
let hypot = deltaX^2 + deltaY^2 + deltaZ^2
return hypot^0.5
}
Dans le cas où l'on évoluerait dans un monde en 2 dimensions, nous donnerions à la fonction seulement les 4 premiers paramètres, les deux derniers z1
et z2
vaudront alors 0
par défaut, et le deltaZ
serait de 0
, ce qui n'empêche en rien le calcul d'être effectué.
Dans le cas où nous développerions un jeu en 3 dimensions, nous en donnerions 6 et la distance serait calculée sur l'ensemble des paramètres fournis.
En pratique, JavaScript ne vérifiera pas le nombre de paramètres que vous fournissez lorsque vous utiliserez la fonction. Un paramètre non fourni, et n'ayant pas de valeur par défaut prendra la valeur
undefined
, c'est-à-dire non définie. Le corps de la fonction serait tout de même exécuté sans erreur mais le résultat du calcul vaudraNaN
signifiant "Not a Number", indiquant que le résultat n'est pas un nombre.
Utilisation d'une fonction
Lorsque l'on utilise une fonction, on dit qu'on l'appelle, en lui fournissant les paramètres nécessaires à son bon fonctionnement.
Définissons par exemple deux éléments sous forme d'objets avec des coordonnées x
et y
et calculons la distance entre ces deux objets à l'aide de la fonction précédemment créée:
let personnage = {
x: 5,
y: 8
}
let ennemi = {
x -1,
y: 15
}
// Appel de la fonction distance avec les coordonnées de gnome et troll
let distanceEntrePersonnageEtEnnemi = distance(personnage.x, ennemi.x, personnage.y, ennemi.y)
Dans cet exemple, la donnée distanceEntrePersonnageEtEnnemi
aura la valeur de l'expression retournée par la fonction distance
, soit 9.22
.
La fonction est ré-utilisable à l'infini, il vous suffit de vous en resservir à chaque fois que vous devez calculer la distance entre deux éléments de votre jeu.
Les fonctions du langage
En consultant la documentation javascript, on peut constater que le langage fournit la fonction Math.hypot
, qui permet de faire le même calcul d'hypoténuse à partir de 3 longueurs, que nous avions fait dans notre fonction. Du coup, pour simplifier notre fonction, nous calculons les deltas, mais ensuite, nous utilisons la fonction Math.hypoth
que Javascript nous fournit, en lui passant ces 3 valeurs (deltaX
, deltaY
et deltaZ
) en paramètre, et on récupère le résultat (l'hypoténuse), qui sera la distance.
Une fonction du langage s'utilise de la même manière qu'une fonction que vous avez déclarée vous-même.
Nous pouvons donc simplifier notre fonction distance
en utilisant Math.hypot
:
function distance(x1, x2, y1, y2, z1 = 0, z2 = 0) {
let deltaX = x2 - x1
let deltaY = y2 - y1
let deltaZ = z2 - z1
// notre fonction retourne
// le résultat que Math.hypot lui aura retourné
return Math.hypot(deltaX, deltaY, deltaZ)
}
Les calculs des deltas peuvent même se faire directement dans l'appel de la fonction, qui utilisera leurs résultats comme paramètres. Cela permet de considérablement raccourcir notre fonction, mais on perd en lisibilité. Libre à vous de décider la version que vous préférez.
function distance(x1, x2, y1, y2, z1 = 0, z2 = 0) {
return Math.hypot(x2 - x1, y2 - y1, z2 - z1)
}
Exercices
Créer une fonction
Définir une fonction avec pour nom moitieDe
retournant la moitié du paramètre passé en paramètre.
moitieDe(12)
doit retourner6
moitieDe(48)
doit retourner24
// Practice-code // Complétez ici return [moitieDe(12), moitieDe(48)] // Hidden line // Doit valoir : [6, 24]
Paramètres optionnels
Modifier la fonction moitieDe
pour qu'elle accepte, 1, 2 ou 3 paramètres. La fonction doit retourner la moitié de la somme des paramètres.
moitieDe(12)
doit retourner6
moitieDe(12, 36)
doit retourner la moitié de12 + 36
, soit24
moitieDe(12, 36, 52)
doit retourner la moitié de12 + 36 + 52
, soit50
// Practice-code // Complétez ici return [moitieDe(12), moitieDe(12, 36), moitieDe(12, 36, 52)] // Hidden line // Doit valoir : [6, 24, 50]