Menu
Coddy logo textTech

Componente de personaje de juego

Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy — lección 69 de 70.

challenge icon

Desafío

Fácil

¡Vamos a construir un sistema de personajes de juego utilizando el patrón de arquitectura basado en componentes! En lugar de crear jerarquías de herencia rígidas, compondrás personajes adjuntando componentes independientes que manejan comportamientos específicos, un enfoque flexible ampliamente utilizado en el desarrollo de videojuegos.

Organizarás tu código en cinco archivos:

  • IComponent.cs: Define una interfaz IComponent en el espacio de nombres Game.Components. Cada componente debe tener un método Update() que imprima lo que el componente está haciendo.
  • HealthComponent.cs: Crea una clase HealthComponent que implemente IComponent. Debe rastrear los puntos de salud actuales y máximos, con métodos para TakeDamage(int amount) y Heal(int amount). La salud nunca debe bajar de 0 ni superar el máximo. Incluye un event Action<int> HealthChanged que se dispare cada vez que la salud cambie, pasando el nuevo valor de salud. El método Update() debe imprimir el estado de salud actual.
  • InventoryComponent.cs: Crea una clase InventoryComponent que implemente IComponent. Gestiona una lista de nombres de objetos con los métodos AddItem(string item) y RemoveItem(string item) (devuelve un bool indicando el éxito). El método Update() debe imprimir el contenido del inventario.
  • Character.cs: Crea una clase Character en el espacio de nombres Game que contenga una colección de componentes. Tu personaje necesita una propiedad Name y estos métodos:
    • AddComponent(IComponent component) - adjunta un componente al personaje
    • GetComponent<T>() donde T : IComponent - devuelve el primer componente de tipo T, o null si no se encuentra
    • UpdateAll() - llama a Update() en cada componente adjunto
  • Program.cs: Une todo creando un personaje, adjuntando componentes y procesando comandos.

Recibirás las siguientes entradas:

  • Nombre del personaje
  • Salud máxima inicial para el HealthComponent
  • Número de comandos a procesar
  • Para cada comando: la acción seguida de los datos relevantes

Formatos de comando:

damage
{amount}

heal
{amount}

add_item
{itemName}

remove_item
{itemName}

update

Formatos de salida:

  • Cuando la salud cambia (vía evento): Health changed: {newHealth}
  • Al añadir un objeto: Added: {itemName}
  • Al eliminar un objeto: Removed: {itemName} o Item not found: {itemName}
  • Update() de HealthComponent: Health: {current}/{max}
  • Update() de InventoryComponent: Inventory: {item1}, {item2}, ... o Inventory: empty

Por ejemplo, si las entradas son:

Hero
100
7
add_item
Sword
add_item
Shield
damage
30
heal
10
remove_item
Potion
remove_item
Sword
update

La salida debería ser:

Added: Sword
Added: Shield
Health changed: 70
Health changed: 80
Item not found: Potion
Removed: Sword
Health: 80/100
Inventory: Shield

Observa cómo el personaje no hereda de nada especial; simplemente contiene componentes que proporcionan comportamiento. El método GetComponent<T>() utiliza genéricos para una recuperación segura de tipos, y los eventos notifican cuando la salud cambia. ¡Este enfoque de composición te permite mezclar y combinar componentes libremente!

Pruébalo tú mismo

using System;
using Game;
using Game.Components;

class Program
{
    public static void Main(string[] args)
    {
        // Leer el nombre del personaje
        string characterName = Console.ReadLine();
        
        // Leer la salud máxima inicial
        int maxHealth = Convert.ToInt32(Console.ReadLine());
        
        // Leer el número de comandos
        int numCommands = Convert.ToInt32(Console.ReadLine());
        
        // TODO: Crear un Character con el nombre dado
        
        // TODO: Crear HealthComponent con maxHealth e InventoryComponent
        
        // TODO: Suscribirse al evento HealthChanged para imprimir: Health changed: {newHealth}
        
        // TODO: Agregar ambos componentes al personaje
        
        // TODO: Procesar cada comando
        for (int i = 0; i < numCommands; i++)
        {
            string command = Console.ReadLine();
            
            // TODO: Manejar cada tipo de comando:
            // - "damage": leer la cantidad, llamar a TakeDamage en el componente de salud
            // - "heal": leer la cantidad, llamar a Heal en el componente de salud
            // - "add_item": leer el nombre del objeto, llamar a AddItem en el componente de inventario
            // - "remove_item": leer el nombre del objeto, llamar a RemoveItem en el componente de inventario
            // - "update": llamar a UpdateAll en el personaje
        }
    }
}

Todas las lecciones de Programación Orientada a Objetos