Développement de personnages de jeu
Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy. Leçon 90 sur 91.
Défi
FacileConstruisons un système de développement de personnages de jeu dans lequel différentes classes de personnages s'affrontent en utilisant des capacités uniques. Tu vas créer une hiérarchie de personnages avec un système d'expérience et de niveaux, montrant comment l'héritage, les interfaces, les traits et l'encapsulation fonctionnent ensemble dans le contexte d'un jeu.
Tu organiseras ton code sur six fichiers :
Ability.php: définis une interfaceAbilityavec deux méthodes :getName(): stringetuse(Character $target): string. Ce contrat garantit que toutes les capacités peuvent être utilisées de manière cohérente, quels que soient leurs effets spécifiques.CombatLogger.php: crée un traitCombatLoggerqui fournit une méthodelogAction(string $action): string. Cette méthode doit renvoyer la chaîne de l'action précédée de"[COMBAT] ". Les personnages utiliseront ce trait pour formater leurs messages de combat de manière cohérente.Character.php: inclus les fichiers Ability et CombatLogger. Crée une classe abstraiteCharacterqui utilise le traitCombatLogger. Utilise la promotion du constructeur pourname(string, public readonly). Inclus des propriétés privées pourhealth(int, initialisée à 100),level(int, initialisé à 1) etexperience(int, initialisée à 0). Implémente :getHealth(): intetgetLevel(): int: accesseurs pour les propriétés privéestakeDamage(int $amount): void: réduit la santé, sans jamais descendre en dessous de 0heal(int $amount): void: augmente la santé, sans jamais dépasser 100gainExperience(int $xp): string: ajoute de l'XP ; si l'expérience atteint 100 ou plus, passe au niveau supérieur (réinitialise l'XP à 0, augmente le niveau et soigne de 20 PV), puis renvoie"[name] leveled up to [level]!"; sinon, renvoie"[name] gained [xp] XP"isAlive(): bool: renvoie true si la santé est supérieure à 0abstract getSpecialAbility(): Ability: chaque type de personnage fournit sa capacité uniqueattack(Character $target): string: inflige 10 points de dégâts à la cible et utiliselogAction()pour renvoyer"[COMBAT] [name] attacks [target name] for 10 damage"
Warrior.php: inclus le fichier Character. Crée une classeWarriorqui étendCharacter. ImplémentegetSpecialAbility()afin de renvoyer une classe anonyme implémentantAbility:getName()renvoie"Shield Bash"use()inflige 25 points de dégâts et renvoie"[COMBAT] Shield Bash hits [target name] for 25 damage!"(utilise lelogAction()du trait)
Mage.php: inclus le fichier Character. Crée une classeMagequi étendCharacter. ImplémentegetSpecialAbility()afin de renvoyer une classe anonyme implémentantAbility:getName()renvoie"Fireball"use()inflige 35 points de dégâts et renvoie"[COMBAT] Fireball engulfs [target name] for 35 damage!"
main.php: inclus les fichiers Warrior et Mage. Tu recevras deux entrées : les données des personnages (JSON) et une séquence d'actions de combat (JSON).Format JSON des personnages :
[{"type": "warrior", "name": "Thorin"}, {"type": "mage", "name": "Gandalf"}]Format JSON des actions :
[{"action": "attack", "attacker": 0, "target": 1}, {"action": "special", "attacker": 1, "target": 0}, {"action": "xp", "character": 0, "amount": 100}, {"action": "status", "character": 0}]Crée tous les personnages et stocke-les dans un tableau (index 0, 1, etc.). Traite chaque action :
"attack": le personnage à l'index attacker attaque la cible ; affiche le résultat"special": le personnage utilise sa capacité spéciale sur la cible ; affiche le résultat"xp": le personnage gagne de l'expérience ; affiche le résultat"heal": le personnage se soigne du montant indiqué ; affiche"[name] healed to [health] HP""status": affiche"[name] - Level [level], HP: [health], Alive: [Yes/No]"
Affiche chaque résultat sur une nouvelle ligne.
Ce système montre comment les classes abstraites définissent le comportement partagé des personnages, comment les interfaces garantissent que les capacités respectent un contrat cohérent, comment les traits fournissent une fonctionnalité de journalisation réutilisable et comment les classes anonymes permettent de créer des implémentations de capacités uniques sans encombrer ta base de code avec des classes utilisées une seule fois.
Essayez vous-même
<?php
require_once 'Warrior.php';
require_once 'Mage.php';
// Lire l'entrée
$charactersJson = trim(fgets(STDIN));
$actionsJson = trim(fgets(STDIN));
// Analyser les entrées JSON
$charactersData = (array)json_decode($charactersJson, true);
$actionsData = (array)json_decode($actionsJson, true);
// TODO: Créer un tableau pour stocker les objets personnages
$characters = [];
// TODO: Parcourir $charactersData et créer des objets Warrior ou Mage
// basé sur le champ "type", les stocker dans le tableau $characters
// TODO: Traiter chaque action dans $actionsData
// Gérer ces types d'actions :
// - "attack": Le personnage à l'index de l'attaquant attaque la cible ; afficher le résultat
// - "special": Le personnage utilise getSpecialAbility()->use() sur la cible ; afficher le résultat
// - "xp": Le personnage gagne de l'expérience ; afficher le résultat
// - "heal": Le personnage se soigne ; afficher "[name] healed to [health] HP"
// - "status": Afficher "[name] - Level [level], HP: [health], Alive: [Yes/No]"
?>Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses et objetsLe mot-clé $thisMéthodesPropriétésConstructeur (__construct)Destructeur (__destruct)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLe mot-clé parent::Redéfinition des méthodesLe mot-clé finalClasses abstraitesRécapitulatif – Hiérarchie des employés7Encapsulation
Public, Protected, PrivateModificateurs d’accès en profondeurAccesseurs et mutateursDissimulation de l’informationPromotion des constructeurs (8.0)Récapitulatif – Système de fiches étudiant10Concepts avancés de la POO
Composition ou héritageInjection de dépendancesClasses anonymesÉnumérations (PHP 8.1)Fibres (PHP 8.1)Approfondissement du clonage d’objetsGénérateurs et itérateurs13Patrons de conception – Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode modèlePatron ÉtatPatron CompositePatron Dépôt2Espaces de noms et chargement automatique
Introduction aux espaces de nomsLe mot-clé useNorme de chargement automatique PSR-4Autoloader de ComposerRécapitulatif - Projet organisé5Interfaces et contrats
Introduction aux interfacesImplémentation des interfacesImplémentation de plusieurs interfacesInterface ou classe abstraiteIndication de type avec les interfacesRécapitulatif - Calculateur de formes8Méthodes magiques
Introduction aux méthodes magiques__toString et __debugInfo__get, __set, __isset, __unset__call et __callStatic__clone et clonage d’objets__serialize et __unserializeRécapitulatif - Collection personnalisée3Propriétés de classe
Propriétés d’instance vs statiquesConstantes dans les classesMéthodes et propriétés statiquesPropriétés privées et protégéesPropriétés en lecture seule (PHP 8.1)Récapitulatif - Gestionnaire de comptes bancaires6Polymorphisme
Révision de la redéfinition des méthodesPolymorphisme via les interfacesAnnotations de type et types unionLiaison statique tardiveRécapitulatif - Processeur de paiements9Traits
Introduction aux traitsUtilisation de plusieurs traitsRésolution des conflits entre traitsMéthodes abstraites dans les traitsTraits par rapport à l’héritage12Patrons de conception – Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FactoryPatron ObserverPatron Strategy15Défis finaux
Plateforme d’apprentissage en ligneSystème bancaireDéveloppement de personnages de jeuService de location de véhiculesEntraînez-vous par vous-même : Compilateur PHP en ligne