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 construir um sistema de personagens de jogo usando o padrão de arquitetura baseada em componentes! Em vez de criar hierarquias de herança rígidas, você comporá personagens anexando componentes independentes que lidam com comportamentos específicos - uma abordagem flexível amplamente utilizada no desenvolvimento de jogos.

Você 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 implementa IComponent. Ela deve rastrear os pontos de vida atuais e máximos, com métodos para TakeDamage(int amount) e Heal(int amount). A vida nunca deve ficar abaixo de 0 ou acima do máximo. Inclua um event Action<int> HealthChanged que é disparado sempre que a vida muda, passando o novo valor de vida. O método Update() deve imprimir o status atual da vida.
  • InventoryComponent.cs: Crie uma classe InventoryComponent que implementa IComponent. Ela gerencia uma lista de nomes de itens com os métodos AddItem(string item) e RemoveItem(string item) (retorna um bool indicando sucesso). O método Update() deve imprimir o conteúdo do inventário.
  • Character.cs: Crie uma classe Character no namespace Game que contém 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>() onde 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 para o HealthComponent
  • Número de comandos a serem processados
  • Para cada comando: a ação seguida pelos dados relevantes

Formatos de comando:

damage
{amount}

heal
{amount}

add_item
{itemName}

remove_item
{itemName}

update

Formatos de saída:

  • Quando a vida muda (via evento): Health changed: {newHealth}
  • Ao adicionar um item: Added: {itemName}
  • Ao remover um item: Removed: {itemName} ou Item not found: {itemName}
  • Update() do HealthComponent: Health: {current}/{max}
  • Update() do 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 deve 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 contém componentes que fornecem comportamento. O método GetComponent<T>() usa genéricos para recuperação segura de tipos, e os eventos notificam quando a vida muda. Essa abordagem de composição permite que você misture e combine 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