Menu
Coddy logo textTech

Componente de Personagem de Jogo

Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy. Lição 69 de 70.

challenge icon

Desafio

Fácil

Vamos criar um sistema de personagens de jogo usando o padrão de arquitetura baseado em componentes! Em vez de criar hierarquias rígidas de herança, você vai compor personagens anexando componentes independentes que lidam com comportamentos específicos — uma abordagem flexível amplamente usada no desenvolvimento de jogos.

Você vai organizar seu código em cinco arquivos:

  • IComponent.cs: Defina uma interface IComponent no namespace Game.Components. Todo componente deve ter um método Update() que imprime o que o componente está fazendo.
  • HealthComponent.cs: Crie uma classe HealthComponent que implemente IComponent. Ela deve acompanhar os pontos de vida atuais e máximos, com métodos TakeDamage(int amount) e Heal(int amount). A vida nunca deve ficar abaixo de 0 nem acima do máximo. Inclua um event Action<int> HealthChanged que seja acionado sempre que a vida mudar, passando o novo valor de vida. O método Update() deve imprimir o status atual da vida.
  • InventoryComponent.cs: Crie uma classe InventoryComponent que implemente IComponent. Ela gerencia uma lista de nomes de itens com os métodos AddItem(string item) e RemoveItem(string item) (retorna bool indicando o sucesso). O método Update() deve imprimir o conteúdo do inventário.
  • Character.cs: Crie uma classe Character no namespace Game que mantenha uma coleção de componentes. Seu personagem precisa de uma propriedade Name e destes métodos:
    • AddComponent(IComponent component) - anexa um componente ao personagem
    • GetComponent<T>() where T : IComponent - retorna o primeiro componente do tipo T ou null se não for encontrado
    • UpdateAll() - chama Update() em cada componente anexado
  • Program.cs: Reúna tudo criando um personagem, anexando componentes e processando comandos.

Você receberá as seguintes entradas:

  • Nome do personagem
  • Vida máxima inicial do HealthComponent
  • Número de comandos a serem processados
  • Para cada comando: a ação seguida dos dados relevantes

Formatos dos comandos:

damage
{amount}

heal
{amount}

add_item
{itemName}

remove_item
{itemName}

update

Formatos da saída:

  • Quando a vida mudar (por meio do evento): Health changed: {newHealth}
  • Ao adicionar um item: Added: {itemName}
  • Ao remover um item: Removed: {itemName} ou Item not found: {itemName}
  • Update() de HealthComponent: Health: {current}/{max}
  • Update() de InventoryComponent: Inventory: {item1}, {item2}, ... ou Inventory: empty

Por exemplo, se as entradas forem:

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

A saída deverá ser:

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

Observe como o personagem não herda de nada especial — ele simplesmente mantém componentes que fornecem comportamentos. O método GetComponent<T>() usa genéricos para uma recuperação segura quanto ao tipo, e os eventos notificam quando a vida muda. Essa abordagem de composição permite combinar componentes livremente!

Experimente você mesmo

using System;
using Game;
using Game.Components;

class Program
{
    public static void Main(string[] args)
    {
        // Lê o nome do personagem
        string characterName = Console.ReadLine();
        
        // Lê a vida máxima inicial
        int maxHealth = Convert.ToInt32(Console.ReadLine());
        
        // Lê o número de comandos
        int numCommands = Convert.ToInt32(Console.ReadLine());
        
        // TODO: Criar um Character com o nome fornecido
        
        // TODO: Criar HealthComponent com maxHealth e InventoryComponent
        
        // TODO: Inscrever-se no evento HealthChanged para imprimir: Health changed: {newHealth}
        
        // TODO: Adicionar ambos os componentes ao personagem
        
        // TODO: Processar cada comando
        for (int i = 0; i < numCommands; i++)
        {
            string command = Console.ReadLine();
            
            // TODO: Lidar com cada tipo de comando:
            // - "damage": ler a quantidade, chamar TakeDamage no componente de saúde
            // - "heal": ler a quantidade, chamar Heal no componente de saúde
            // - "add_item": ler o nome do item, chamar AddItem no componente de inventário
            // - "remove_item": ler o nome do item, chamar RemoveItem no componente de inventário
            // - "update": chamar UpdateAll no personagem
        }
    }
}

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de C# online