Menu
Coddy logo textTech

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.

challenge icon

Défi

Facile

Construisons 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 interface Ability avec deux méthodes : getName(): string et use(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 trait CombatLogger qui fournit une méthode logAction(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 abstraite Character qui utilise le trait CombatLogger. Utilise la promotion du constructeur pour name (string, public readonly). Inclus des propriétés privées pour health (int, initialisée à 100), level (int, initialisé à 1) et experience (int, initialisée à 0). Implémente :
    • getHealth(): int et getLevel(): int : accesseurs pour les propriétés privées
    • takeDamage(int $amount): void : réduit la santé, sans jamais descendre en dessous de 0
    • heal(int $amount): void : augmente la santé, sans jamais dépasser 100
    • gainExperience(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 à 0
    • abstract getSpecialAbility(): Ability : chaque type de personnage fournit sa capacité unique
    • attack(Character $target): string : inflige 10 points de dégâts à la cible et utilise logAction() pour renvoyer "[COMBAT] [name] attacks [target name] for 10 damage"
  • Warrior.php : inclus le fichier Character. Crée une classe Warrior qui étend Character. Implémente getSpecialAbility() afin de renvoyer une classe anonyme implémentant Ability :
    • getName() renvoie "Shield Bash"
    • use() inflige 25 points de dégâts et renvoie "[COMBAT] Shield Bash hits [target name] for 25 damage!" (utilise le logAction() du trait)
  • Mage.php : inclus le fichier Character. Crée une classe Mage qui étend Character. Implémente getSpecialAbility() afin de renvoyer une classe anonyme implémentant Ability :
    • 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

Entraînez-vous par vous-même : Compilateur PHP en ligne