3) Enrichir le jeu
Ajouter le mage et le plateau

Objectifs de la séance
- Créer une deuxième classe fille,
Mage, avec ses propres mécaniques (mana, sorts offensifs). - Modifier une classe existante (
Personnage) pour y ajouter des propriétés sans casser le code existant. - Utiliser les valeurs par défaut de paramètres pour rendre des arguments facultatifs.
- Ajouter une méthode de déplacement avec la structure
switch. - Afficher un plateau de jeu sous forme de grille HTML avec des boucles
forimbriquées. - Utiliser
instanceofpour adapter le comportement selon le type d'un objet. - Parcourir un tableau d'objets avec
foreach.
Notions théoriques
Faire évoluer une classe existante sans tout casser
Jusqu'ici, la classe Personnage ne connaît que trois informations : nom, vie et DPS.
Pour ce jeu, on a besoin que les personnages occupent une position sur un plateau.
On va donc ajouter deux propriétés $x et $y à la classe Personnage.
Le défi quand on modifie une classe existante est de ne pas casser le code qui l'utilise déjà.
Si l'on ajoute $x et $y comme paramètres obligatoires du constructeur, toutes les lignes
existantes du type new Guerrier("Lara", 100, 10, 5) cesseront de fonctionner.
La solution : les valeurs par défaut de paramètres. Un paramètre peut avoir une valeur par défaut, ce qui le rend facultatif à l'appel. Si on ne le précise pas, la valeur par défaut est utilisée.
public function __construct($nom, $vie, $dps, $x = 0, $y = 0) {
// ...
}
Avec cette signature, les deux appels suivants sont valides :
new Guerrier("Lara", 100, 10, 5); // x=0, y=0 par défaut
new Guerrier("Lara", 100, 10, 5, 2, 3); // x=2, y=3 explicitement
Les paramètres avec une valeur par défaut doivent toujours être placés à la fin de la liste.
PHP interdirait d'écrire function __construct($x = 0, $nom, $vie) car un paramètre
obligatoire ne peut pas suivre un paramètre facultatif.
La structure switch
Quand on doit comparer une même variable à plusieurs valeurs possibles, la structure switch
est plus lisible qu'une série de if / else if.
$direction = "haut";
switch ($direction) {
case "haut":
$this->y = $this->y - 1;
break;
case "bas":
$this->y = $this->y + 1;
break;
case "gauche":
$this->x = $this->x - 1;
break;
case "droite":
$this->x = $this->x + 1;
break;
}
Chaque case se termine par break. Sans ce mot-clé, PHP continuerait à exécuter
les case suivants même si la condition ne correspond pas. Ce comportement involontaire
est l'une des erreurs les plus courantes avec switch.
Les boucles for imbriquées pour parcourir une grille
Un plateau de jeu est une grille à deux dimensions : des lignes et des colonnes.
Pour parcourir toutes les cases, on utilise deux boucles for imbriquées :
la boucle externe parcourt les lignes, la boucle interne parcourt les colonnes.
$taille = 5;
for ($ligne = 0; $ligne < $taille; $ligne++) {
for ($colonne = 0; $colonne < $taille; $colonne++) {
// On est sur la case ($colonne, $ligne)
}
}
La convention adoptée dans ce projet : $x représente la colonne (axe horizontal),
et $y représente la ligne (axe vertical). La case en haut à gauche a pour coordonnées
(0, 0). Aller vers la droite augmente $x, aller vers le bas augmente $y.
L'opérateur instanceof
instanceof permet de vérifier de quelle classe est un objet. C'est utile quand on
manipule une collection d'objets de types différents (des guerriers et des mages mélangés)
et qu'on veut adapter le comportement selon le type.
if ($personnage instanceof Guerrier) {
// ce personnage est un guerrier
}
if ($personnage instanceof Mage) {
// ce personnage est un mage
}
instanceof fonctionne aussi avec l'héritage : si Guerrier hérite de Personnage,
alors un guerrier est à la fois une instance de Guerrier et une instance de Personnage.
Parcourir un tableau d'objets avec foreach
Quand plusieurs personnages sont stockés dans un tableau, foreach permet de les parcourir
un par un sans avoir à gérer un compteur manuellement.
$personnages = [$p1, $p2, $p3];
foreach ($personnages as $p) {
print "<p>" . $p . "</p>";
}
On peut aussi récupérer l'indice de chaque élément avec la syntaxe as $index => $p :
foreach ($personnages as $index => $p) {
print "<p>Personnage numéro " . $index . " : " . $p->getNom() . "</p>";
}