Game Character Component
Part of the Object Oriented Programming section of Coddy's C# journey — lesson 69 of 70.
Challenge
EasyLet'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 anIComponentinterface in theGame.Componentsnamespace. Every component must have anUpdate()method that prints what the component is doing.HealthComponent.cs: Create aHealthComponentclass that implementsIComponent. It should track current and maximum health points, with methods toTakeDamage(int amount)andHeal(int amount). The health should never go below 0 or above the maximum. Include anevent Action<int> HealthChangedthat fires whenever health changes, passing the new health value. TheUpdate()method should print the current health status.InventoryComponent.cs: Create anInventoryComponentclass that implementsIComponent. It manages a list of item names with methodsAddItem(string item)andRemoveItem(string item)(returnsboolindicating success). TheUpdate()method should print the inventory contents.Character.cs: Create aCharacterclass in theGamenamespace that holds a collection of components. Your character needs aNameproperty and these methods:AddComponent(IComponent component)- attaches a component to the characterGetComponent<T>()where T : IComponent - returns the first component of type T, or null if not foundUpdateAll()- callsUpdate()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}
updateOutput formats:
- When health changes (via event):
Health changed: {newHealth} - When adding an item:
Added: {itemName} - When removing an item:
Removed: {itemName}orItem not found: {itemName} - HealthComponent's
Update():Health: {current}/{max} - InventoryComponent's
Update():Inventory: {item1}, {item2}, ...orInventory: 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
updateThe output should be:
Added: Sword
Added: Shield
Health changed: 70
Health changed: 80
Item not found: Potion
Removed: Sword
Health: 80/100
Inventory: ShieldNotice 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
1Fundamentals of OOP
External FilesNamespaces & DirectivesIntro to Classes & ObjectsThe 'this' KeywordMethods and ParametersFields vs PropertiesConstructorsObject InitializersRecap - Simple Calculator4Inheritance
Basic Inheritance (:) SyntaxThe 'base' KeywordVirtual & Override KeywordsSealed ClassesThe 'object' Base ClassRecap - Employee Hierarchy7Advanced Features
Operator OverloadingIndexers (this[])ToString() OverrideExtension MethodsRecap - Custom List2Properties & Static Members
Auto-Implemented PropertiesRead/Write-Only PropertiesStatic Fields & MethodsStatic ClassesExpression-Bodied Members5Polymorphism & Interfaces
Compile vs Runtime PolyInterface vs Abstract ClassMultiple InterfacesExplicit InterfacesUpcasting & DowncastingRecap - Shape Calculator