Menu
Coddy logo textTech

Desarrollo de personajes de videojuegos

Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy. Lección 90 de 91.

challenge icon

Desafío

Fácil

Construyamos un sistema de Desarrollo de personajes de juego en el que diferentes clases de personajes combatan usando habilidades únicas. Crearás una jerarquía de personajes con un sistema de experiencia y niveles, demostrando cómo funcionan conjuntamente la herencia, las interfaces, los traits y la encapsulación en el contexto de un juego.

Organizarás tu código en seis archivos:

  • Ability.php: Define una interfaz Ability con dos métodos: getName(): string y use(Character $target): string. Este contrato garantiza que todas las habilidades puedan usarse de manera coherente, independientemente de sus efectos específicos.
  • CombatLogger.php: Crea un trait CombatLogger que proporcione un método logAction(string $action): string. Este método debe devolver la cadena de acción con el prefijo "[COMBAT] ". Los personajes usarán este trait para dar formato coherente a sus mensajes de combate.
  • Character.php: Incluye los archivos Ability y CombatLogger. Crea una clase abstracta Character que use el trait CombatLogger. Usa la promoción del constructor para name (string, public readonly). Incluye propiedades privadas para health (int, comienza en 100), level (int, comienza en 1) y experience (int, comienza en 0). Implementa:
    • getHealth(): int y getLevel(): int: getters para las propiedades privadas
    • takeDamage(int $amount): void: reduce la salud, pero nunca por debajo de 0
    • heal(int $amount): void: aumenta la salud, pero nunca por encima de 100
    • gainExperience(int $xp): string: añade XP; si la experiencia llega a 100 o más, sube de nivel (restablece la XP a 0, aumenta el nivel y restaura 20 HP), y devuelve "[name] leveled up to [level]!"; de lo contrario, devuelve "[name] gained [xp] XP"
    • isAlive(): bool: devuelve true si la salud es mayor que 0
    • abstract getSpecialAbility(): Ability: cada tipo de personaje proporciona su habilidad única
    • attack(Character $target): string: inflige 10 de daño al objetivo y usa logAction() para devolver "[COMBAT] [name] attacks [target name] for 10 damage"
  • Warrior.php: Incluye el archivo Character. Crea una clase Warrior que extienda Character. Implementa getSpecialAbility() para devolver una clase anónima que implemente Ability:
    • getName() devuelve "Shield Bash"
    • use() inflige 25 de daño y devuelve "[COMBAT] Shield Bash hits [target name] for 25 damage!" (usa el logAction() del trait)
  • Mage.php: Incluye el archivo Character. Crea una clase Mage que extienda Character. Implementa getSpecialAbility() para devolver una clase anónima que implemente Ability:
    • getName() devuelve "Fireball"
    • use() inflige 35 de daño y devuelve "[COMBAT] Fireball engulfs [target name] for 35 damage!"
  • main.php: Incluye los archivos Warrior y Mage. Recibirás dos entradas: datos de personajes (JSON) y una secuencia de acciones de combate (JSON).

    Formato JSON de los personajes:

    [{"type": "warrior", "name": "Thorin"}, {"type": "mage", "name": "Gandalf"}]

    Formato JSON de las acciones:

    [{"action": "attack", "attacker": 0, "target": 1}, {"action": "special", "attacker": 1, "target": 0}, {"action": "xp", "character": 0, "amount": 100}, {"action": "status", "character": 0}]

    Crea todos los personajes y guárdalos en un array (índices 0, 1, etc.). Procesa cada acción:

    • "attack": el personaje en el índice attacker ataca al objetivo; imprime el resultado
    • "special": el personaje usa su habilidad especial contra el objetivo; imprime el resultado
    • "xp": el personaje gana experiencia; imprime el resultado
    • "heal": el personaje se cura la cantidad indicada; imprime "[name] healed to [health] HP"
    • "status": imprime "[name] - Level [level], HP: [health], Alive: [Yes/No]"

    Imprime cada resultado en una línea nueva.

Este sistema demuestra cómo las clases abstractas definen el comportamiento compartido de los personajes, las interfaces garantizan que las habilidades sigan un contrato coherente, los traits proporcionan una funcionalidad de registro reutilizable y las clases anónimas crean implementaciones de habilidades únicas sin llenar tu base de código de clases de un solo uso.

Pruébalo tú mismo

<?php
require_once 'Warrior.php';
require_once 'Mage.php';

// Leer la entrada
$charactersJson = trim(fgets(STDIN));
$actionsJson = trim(fgets(STDIN));

// Analizar las entradas JSON
$charactersData = (array)json_decode($charactersJson, true);
$actionsData = (array)json_decode($actionsJson, true);

// TODO: Crea un array para almacenar objetos de personajes
$characters = [];

// TODO: Recorre $charactersData y crea objetos Warrior o Mage
// basándote en el campo "type", almacénalos en el array $characters

// TODO: Procesa cada acción en $actionsData
// Maneja estos tipos de acción:
// - "attack": El personaje en el índice del atacante ataca al objetivo; imprime el resultado
// - "special": El personaje usa getSpecialAbility()->use() en el objetivo; imprime el resultado
// - "xp": El personaje gana experiencia; imprime el resultado
// - "heal": El personaje se cura; imprime "[name] healed to [health] HP"
// - "status": Imprime "[name] - Level [level], HP: [health], Alive: [Yes/No]"

?>

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de PHP online