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 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 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éez un trait CombatLogger qui fournit une méthode logAction(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 abstraite Character qui utilise le trait CombatLogger. Utilisez la promotion de constructeur pour name (string, public readonly). Incluez des propriétés privées pour health (int, commençant à 100), level (int, commençant à 1), et experience (int, commençant à 0). Implémentez :
    • getHealth(): int et getLevel(): int — getters pour les propriétés privées
    • takeDamage(int $amount): void — réduit la santé mais jamais en dessous de 0
    • heal(int $amount): void — augmente la santé mais jamais au-dessus de 100
    • gainExperience(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 à 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, utilise logAction() pour retourner "[COMBAT] [name] attacks [target name] for 10 damage"
  • Warrior.php — Incluez le fichier Character. Créez une classe Warrior étendant Character. Implémentez getSpecialAbility() pour retourner une classe anonyme implémentant Ability :
    • getName() retourne "Shield Bash"
    • use() inflige 25 points de dégâts et retourne "[COMBAT] Shield Bash hits [target name] for 25 damage!" (utilisez le logAction() du trait)
  • Mage.php — Incluez le fichier Character. Créez une classe Mage étendant Character. Implémentez getSpecialAbility() pour retourner une classe anonyme implémentant Ability :
    • 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