ゲームキャラクターコンポーネント
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)(成功したかどうかを示すboolを返す)メソッドを持ちます。Update()メソッドはインベントリの内容を出力する必要があります。Character.cs: コンポーネントのコレクションを保持するCharacterクラスをGame名前空間に作成します。キャラクターにはNameプロパティと以下のメソッドが必要です:AddComponent(IComponent component)- キャラクターにコンポーネントをアタッチしますGetComponent<T>()where T : IComponent - 型Tの最初のコンポーネントを返します。見つからない場合はnullを返しますUpdateAll()- アタッチされている各コンポーネントの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": 値を読み込み、health component の TakeDamage を呼び出す
// - "heal": 値を読み込み、health component の Heal を呼び出す
// - "add_item": アイテム名を読み込み、inventory component の AddItem を呼び出す
// - "remove_item": アイテム名を読み込み、inventory component の RemoveItem を呼び出す
// - "update": キャラクターの UpdateAll を呼び出す
}
}
}