游戏角色组件
本课属于 Coddy C# 学习旅程的“面向对象编程”单元。第 69 课,共 70 课。
挑战
简单让我们使用基于组件的架构模式来构建一个游戏角色系统!你不再创建僵化的继承层次结构,而是通过附加独立组件来组合角色,每个组件负责处理特定行为。这种灵活的方法在游戏开发中得到了广泛应用。
你需要将代码组织在 5 个文件中:
IComponent.cs:在Game.Components命名空间中定义IComponent接口。每个组件都必须有一个Update()方法,用于输出该组件正在执行的操作。HealthComponent.cs:创建一个实现IComponent的HealthComponent类。它应跟踪当前生命值和最大生命值,并提供TakeDamage(int amount)和Heal(int amount)方法。生命值不能低于 0,也不能超过最大值。添加一个event Action<int> HealthChanged事件,每当生命值发生变化时触发,并传递新的生命值。Update()方法应输出当前生命值状态。InventoryComponent.cs:创建一个实现IComponent的InventoryComponent类。它管理一个物品名称列表,并提供AddItem(string item)和RemoveItem(string item)方法。RemoveItem(string item)返回一个用于表示操作是否成功的bool值。Update()方法应输出物品栏内容。Character.cs:在Game命名空间中创建一个Character类,用于保存组件集合。你的角色需要有一个Name属性,以及以下方法:AddComponent(IComponent component):将组件附加到角色上GetComponent<T>(),其中 T : IComponent:返回第一个类型为 T 的组件;如果找不到,则返回 nullUpdateAll():对每个已附加的组件调用Update()
Program.cs:通过创建角色、附加组件并处理命令,将所有内容组合起来。
你将收到以下输入:
- 角色名称
- HealthComponent 的初始最大生命值
- 要处理的命令数量
- 对于每条命令:操作及其相关数据
命令格式:
damage
{amount}
heal
{amount}
add_item
{itemName}
remove_item
{itemName}
update输出格式:
- 生命值发生变化时(通过事件):
Health changed: {newHealth} - 添加物品时:
Added: {itemName} - 移除物品时:
Removed: {itemName}或Item not found: {itemName} - HealthComponent 的
Update():Health: {current}/{max} - InventoryComponent 的
Update():Inventory: {item1}, {item2}, ...或Inventory: empty
例如,输入如下:
Hero
100
7
add_item
Sword
add_item
Shield
damage
30
heal
10
remove_item
Potion
remove_item
Sword
update输出应为:
Added: Sword
Added: Shield
Health changed: 70
Health changed: 80
Item not found: Potion
Removed: Sword
Health: 80/100
Inventory: Shield注意,角色并不继承任何特殊类,而只是保存提供各种行为的组件。GetComponent<T>() 方法使用泛型来实现类型安全的检索,而事件会在生命值发生变化时发出通知。这种组合方式让你可以自由搭配各种组件!
亲手试试
using System;
using Game;
using Game.Components;
class Program
{
public static void Main(string[] args)
{
// 读取角色名称
string characterName = Console.ReadLine();
// 读取初始最大生命值
int maxHealth = Convert.ToInt32(Console.ReadLine());
// 读取命令数量
int numCommands = Convert.ToInt32(Console.ReadLine());
// TODO: 用给定名称创建一个 Character
// TODO: 用 maxHealth 创建 HealthComponent,并创建 InventoryComponent
// TODO: 订阅 HealthChanged 事件,并输出:Health changed: {newHealth}
// TODO: 将这两个组件添加到角色中
// TODO: 处理每条命令
for (int i = 0; i < numCommands; i++)
{
string command = Console.ReadLine();
// TODO: 处理每种命令类型:
// - "damage":读取数值,在生命值组件上调用 TakeDamage
// - "heal":读取数值,在生命值组件上调用 Heal
// - "add_item":读取物品名称,在物品栏组件上调用 AddItem
// - "remove_item":读取物品名称,调用背包组件的 RemoveItem 方法
// - "update":调用角色的 UpdateAll 方法
}
}
}
面向对象编程中的所有课
自己练习: C# 在线编译器