Démarrage : cloner ce repository. {: .alert-info } Puis lancer la commande
composer install
Tu remarqueras que les fichiers composer.json et composer.lock sont déjà présents, et que l'autoload est configuré dans composer.json. Ainsi, dans index.php, les require
multiples des classes ont été remplacés par un unique require
de vendor/autoload.php. Des namespaces ont également été ajoutés sur les classes puisqu'ils servent pour l'autoload.
Un nouvelle épreuve attend notre champion, tuer les oiseaux monstrueux du lac Stymphale. Héraclès (et son équipement) ainsi que trois oiseaux sont déjà instanciés dans index.php.
Pour le moment, les monstres et les héros sont tous deux des instances de la classe Fighter
. Cependant, s'ils ont des propriétés communes propres aux combattants (name, life, dexterity, strength...) certaines caractéristiques diffèrent. Par exemple, seuls les Hero
vont pouvoir porter de l'équipement (Shield, Weapon...).
Il ne devrait donc pas être possible d'attribuer une épée à un sanglier, or c'est pour le moment possible. Pour régler ce problème de conception, il faut passer par l'héritage.
-
Crée deux classes
Hero
etMonster
, chacune héritant deFighter
. Les propriétés communes aux deux vont rester dans Fighter, celles propres auxHero
(Weapon
etShield
) vont passer avec leur getters et setters dansHero
. La classeMonster
ne fait pour l'instant qu'étendreFighter
sans autre modification. -
De plus, les méthodes
getDamage()
etgetDefense()
ont un comportement différent entre un monstre et héros. Dans le premier cas, seules la force et la dextérité sont prises en compte, dans le cas du héros, les valeurs retournées prennent aussi en compte les caractéristiques des armes et armures. Les méthodesgetDamage()
etgetDefense()
doivent donc exister dansFighter
pour refléter le cas le plus simple, et être réécrites dansHero
pour prendre en compte les équipements (ce qui correspond normalement au code actuel deFighter
à la fin de l'atelier précédent). -
Dans index.php, modifier les instanciations pour prendre en compte ses nouvelles classes,
Hero
pour Héraclès etMonster
pour les 3 birds.
Un autre changement de conception apparaît avec cette nouvelle épreuve. Ici, Héraclès ne se bat plus contre un unique monstre, mais contre une multitude. Pour l'instant, un Fighter n'a pas de méthode qui lui permette de connaître tous les autres Fighter du combat. Il serait possible de créer une propriété $adversaries
dans Fighter
, mais chaque Fighter devrait contenir tous les autres, ce qui serait assez redondant et ne permettrait pas d'avoir facilement une vue d'ensemble.
Une meilleure solution est de créer une nouvelle classe Arena
qui contiendrait tous les Fighter
ainsi que des méthodes pour les manipuler (les faire se combattre, les déplacer dans l'arène, etc.). De plus, cette arène peut servir de carte sur laquelle placer les Fighter
et ajouter ainsi du positionnement au gameplay de notre jeu.
-
Créé une class
Arena
contenant les propriétés$monsters
(un tableau d'objetsMonster
) et$hero
(un objetHero
). Par simplification, on partira du principe que nous avons forcément un unique héro dans une arène et un ou plusieurs monstres.
Ajouter les getters et setters comme d'habitude. Crée également un__construct()
qui prendra en paramètre un héro et un tableau de monstres. Ajoute également une propriété$size
(integer avec la valeur 10 par défaut) qui indiquera la taille de l'arène. -
On veut positionner des combattants dans l'arène.
Ajoute les propriétés$x
et$y
(+ getters / setters) dansFighter
ce qui te permettra de donner une position aux combattants. -
Dans index.php, crée un objet de type
Arena
en lui passant$heracles
et les trois birds que tu auras mis dans un tableau. Donne également des positions (x et y) à ces quatre Fighters.
Actualise.
Tu dois les voir sur une carte représentant ton arène et tes combattants dessus ! Modifies les coordonnées de chacun, ils doivent bouger en conséquence !
Maintenant que les combattants ont tous une position, essayons d'exploiter cette nouvelle information.
Tout d'abord, il serait intéressant de connaître la distance entre le héros et chacun des monstres.
Rappel : Pour calculer la distance entre deux points A et B sur une carte, cela revient à appliquer la formule suivante (qui n'est ni plus ni moins que le théorème de pythagore 😛). {: .alert-info }
💡 Hint: en PHP, la racine carrée se calcule grâce à la fonction
sqrt()
et la puissance via l'opérateur**
.
Crée une méthode getDistance()
dans Arena prenant deux objets Fighter
en paramètre et qui retournera la distance entre ces deux combattants. Une fois cela réalisé, réactualise. La distance devrait s'afficher sur la carte au survol d'un oiseau avec la souris.
-
Maintenant que tu peux calculer un éloignement, ajoute la notion de « portée » aux attaques. De base, un combattant sans arme ne devrait pas pouvoir frapper plus loin qu'un adversaire sur une case adjacente. Ajoute à
Fighter
la propriété$range
(float à 1 par défaut) et la méthodegetRange()
. -
Dans
Arena
, crée une méthodetouchable()
prenant en premier paramètre l'attaquant et en second l'attaqué. Cette méthode doit renvoyertrue
si l'attaqué est à portée de l'attaquant, c'est-à-dire si la distance entre les deux combattants est bien inférieure ou égale à la portée (range) de l'attaquant. Une fois cela fait, actualise. Tu devrais voir apparaître en couleur les oiseaux à portée d'Héraclès, et en grisé ceux qui ne le sont pas. N'hésite pas à modifier les coordonnées du héro pour faire varier les distances. -
Ajoute ensuite une propriété
range
(float à 0.5 par défaut) sur les armes et le getter correspondant. -
Dans
Hero
uniquement, ajoute ungetRange()
qui additionnera la portée de base du combattant à celle de l'arme qu'il porte (pour unHero
, c'est donc cette méthodegetRange()
modifiée qui s'exécutera et non plus celle deFighter
, fais attention à la visibilité de la propriétérange
). Ainsi Heracles avec une épée devrait avoir une portée de 1.5 (ce qui doit lui permettre d'attaquer maintenant en diagonale). Le range s'affiche également dans l'inventaire du héros. Bouge le personnage pour vérifier que cela fonctionne. -
Dans index.php, crée une nouvelle arme
$bow
, instance de Weapon, qui possède un range de 5, des dégâts à 8, et l'image bow.svg (ajouter un__construct
+ des getters / setters serait sans doute une bonne idée à ce stade). Attribue cette arme à Héraclès en remplacement de son actuelle épée. Actualise et vérifie dans l'inventaire que l'arme apparaît bien.
Sur la carte, tu devrais constater que les oiseaux sont "atteignables" de plus loin puisque cette arme a un range bien plus important.
Épisode suivant
Les juments de Diomède
{: .text-center :}