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 où différentes classes de personnages s'affrontent en utilisant des capacités uniques. Vous allez créer une hiérarchie de personnages avec un système d'expérience et de montée de niveau, démontrant comment l'héritage, les interfaces, les traits et l'encapsulation fonctionnent ensemble dans le contexte d'un jeu.
Vous organiserez votre code sur six fichiers :
Ability.php— Définissez 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éez un traitCombatLoggerqui fournit une méthodelogAction(string $action): string. Cette méthode doit retourner la chaîne d'action préfixée par"[COMBAT] ". Les personnages utiliseront ce trait pour formater leurs messages de combat de manière cohérente.Character.php— Incluez les fichiers Ability et CombatLogger. Créez une classe abstraiteCharacterqui utilise le traitCombatLogger. Utilisez la promotion de constructeur pourname(string, public readonly). Incluez des propriétés privées pourhealth(int, commençant à 100),level(int, commençant à 1), etexperience(int, commençant à 0). Implémentez :getHealth(): intetgetLevel(): int— getters pour les propriétés privéestakeDamage(int $amount): void— réduit la santé mais jamais en dessous de 0heal(int $amount): void— augmente la santé mais jamais au-dessus de 100gainExperience(int $xp): string— ajoute de l'XP ; si l'expérience atteint 100 ou plus, monte de niveau (réinitialise l'XP à 0, augmente le niveau, soigne de 20 HP), retourne"[name] leveled up to [level]!"; sinon retourne"[name] gained [xp] XP"isAlive(): bool— retourne 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, utiliselogAction()pour retourner"[COMBAT] [name] attacks [target name] for 10 damage"
Warrior.php— Incluez le fichier Character. Créez une classeWarriorétendantCharacter. ImplémentezgetSpecialAbility()pour retourner une classe anonyme implémentantAbility:getName()retourne"Shield Bash"use()inflige 25 points de dégâts et retourne"[COMBAT] Shield Bash hits [target name] for 25 damage!"(utilisez lelogAction()du trait)
Mage.php— Incluez le fichier Character. Créez une classeMageétendantCharacter. ImplémentezgetSpecialAbility()pour retourner une classe anonyme implémentantAbility:getName()retourne"Fireball"use()inflige 35 points de dégâts et retourne"[COMBAT] Fireball engulfs [target name] for 35 damage!"
main.php— Incluez les fichiers Warrior et Mage. Vous recevrez 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éez tous les personnages et stockez-les dans un tableau (index 0, 1, etc.). Traitez chaque action :
"attack"— Le personnage à l'index de l'attaquant attaque la cible ; affichez le résultat"special"— Le personnage utilise sa capacité spéciale sur la cible ; affichez le résultat"xp"— Le personnage gagne de l'expérience ; affichez le résultat"heal"— Le personnage se soigne du montant donné ; affichez"[name] healed to [health] HP""status"— Affichez"[name] - Level [level], HP: [health], Alive: [Yes/No]"
Affichez chaque résultat sur une nouvelle ligne.
Ce système démontre comment les classes abstraites définissent un comportement de personnage partagé, les interfaces garantissent que les capacités suivent un contrat cohérent, les traits fournissent une fonctionnalité de journalisation réutilisable, et les classes anonymes créent des implémentations de capacités uniques sans encombrer votre base de code avec des classes à usage unique.
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 de personnages
$characters = [];
// TODO: Parcourir $charactersData et créer des objets Warrior ou Mage
// en fonction du 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 ; imprimer le résultat
// - "special": Le personnage utilise getSpecialAbility()->use() sur la cible ; imprimer le résultat
// - "xp": Le personnage gagne de l'expérience ; imprimer le résultat
// - "heal": Le personnage se soigne ; imprimer "[name] healed to [health] HP"
// - "status": Imprimer "[name] - Level [level], HP: [health], Alive: [Yes/No]"
?>Toutes les leçons de Programmation Orientée Objet
1Les bases de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé $thisMéthodesPropriétésConstructeur (__construct)Destructeur (__destruct)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLe mot-clé parent::Redéfinition de méthodeLe mot-clé finalClasses abstraitesRécapitulatif - Hiérarchie des employés7Encapsulation
Public, Protégé, PrivéModificateurs d'accès en détailGetters et SettersMasquage d'informationPromotion de constructeur (8.0)Récapitulatif - Système de gestion d'étudiants10Concepts avancés de la POO
Composition vs HéritageInjection de dépendancesClasses anonymesÉnumérations (PHP 8.1)Fibers (PHP 8.1)Clonage d'objets : analyse approfondieGénérateurs et Itérateurs13Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository2Espaces de noms et Autoloading
Introduction aux espaces de nomsLe mot-clé useStandard d'Autoloading PSR-4L'Autoloader ComposerRécapitulatif - Projet organisé5Interfaces et Contrats
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesInterface vs Classe AbstraiteType Hinting avec les InterfacesRécapitulatif - Calculateur de Formes8Méthodes magiques
Introduction aux méthodes magiques__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Clonage d'objets__serialize & __unserializeRécapitulatif - Collection personnalisée3Propriétés de classe
Propriétés d'instance vs Propriétés statiquesConstantes dans les classesMéthodes et propriétés statiquesPropriétés privées et protégéesPropriétés readonly (PHP 8.1)Récapitulatif - Gestionnaire de compte bancaire6Polymorphisme
Retour sur la redéfinition de méthodePolymorphisme via les interfacesType Hinting et Types d'unionLiaison statique tardiveRécapitulatif - Processeur de paiement9Traits
Introduction aux TraitsUtilisation de plusieurs TraitsRésolution des conflits de TraitsMéthodes abstraites dans les TraitsTraits vs Héritage12Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie15Défis finaux
Plateforme d'E-LearningSystème bancaireDéveloppement de personnages de jeuService de location de véhicules