Menu
Coddy logo textTech

Game Character Component

Part of the Object Oriented Programming section of Coddy's C# journey — lesson 69 of 70.

challenge icon

Challenge

Easy

Let's build a game character system using the component-based architecture pattern! Instead of creating rigid inheritance hierarchies, you'll compose characters by attaching independent components that handle specific behaviors - a flexible approach widely used in game development.

You'll organize your code across five files:

  • IComponent.cs: Define an IComponent interface in the Game.Components namespace. Every component must have an Update() method that prints what the component is doing.
  • HealthComponent.cs: Create a HealthComponent class that implements IComponent. It should track current and maximum health points, with methods to TakeDamage(int amount) and Heal(int amount). The health should never go below 0 or above the maximum. Include an event Action<int> HealthChanged that fires whenever health changes, passing the new health value. The Update() method should print the current health status.
  • InventoryComponent.cs: Create an InventoryComponent class that implements IComponent. It manages a list of item names with methods AddItem(string item) and RemoveItem(string item) (returns bool indicating success). The Update() method should print the inventory contents.
  • Character.cs: Create a Character class in the Game namespace that holds a collection of components. Your character needs a Name property and these methods:
    • AddComponent(IComponent component) - attaches a component to the character
    • GetComponent<T>() where T : IComponent - returns the first component of type T, or null if not found
    • UpdateAll() - calls Update() on each attached component
  • Program.cs: Bring everything together by creating a character, attaching components, and processing commands.

You will receive the following inputs:

  • Character name
  • Initial max health for the HealthComponent
  • Number of commands to process
  • For each command: the action followed by relevant data

Command formats:

damage
{amount}

heal
{amount}

add_item
{itemName}

remove_item
{itemName}

update

Output formats:

  • When health changes (via event): Health changed: {newHealth}
  • When adding an item: Added: {itemName}
  • When removing an item: Removed: {itemName} or Item not found: {itemName}
  • HealthComponent's Update(): Health: {current}/{max}
  • InventoryComponent's Update(): Inventory: {item1}, {item2}, ... or Inventory: empty

For example, if the inputs are:

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

The output should be:

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

Notice how the character doesn't inherit from anything special - it simply holds components that provide behavior. The GetComponent<T>() method uses generics for type-safe retrieval, and events notify when health changes. This composition approach lets you mix and match components freely!

Try it yourself

using System;
using Game;
using Game.Components;

class Program
{
    public static void Main(string[] args)
    {
        // Read character name
        string characterName = Console.ReadLine();
        
        // Read initial max health
        int maxHealth = Convert.ToInt32(Console.ReadLine());
        
        // Read number of commands
        int numCommands = Convert.ToInt32(Console.ReadLine());
        
        // TODO: Create a Character with the given name
        
        // TODO: Create HealthComponent with maxHealth and InventoryComponent
        
        // TODO: Subscribe to HealthChanged event to print: Health changed: {newHealth}
        
        // TODO: Add both components to the character
        
        // TODO: Process each command
        for (int i = 0; i < numCommands; i++)
        {
            string command = Console.ReadLine();
            
            // TODO: Handle each command type:
            // - "damage": read amount, call TakeDamage on health component
            // - "heal": read amount, call Heal on health component
            // - "add_item": read item name, call AddItem on inventory component
            // - "remove_item": read item name, call RemoveItem on inventory component
            // - "update": call UpdateAll on character
        }
    }
}

All lessons in Object Oriented Programming