私は夏の間 C# を学んでおり、今までの経験から小さなプロジェクトを作りたいと思っています。ある種のテキストベースのアドベンチャー ゲームに決めました。
ゲームの基本構造には、多数のセクター (または部屋) が含まれます。部屋に入ると、説明といくつかのアクションなどが出力されます。その部屋にあるものを調べ、拾い、使用する能力。おそらく戦闘システムなどです。セクターは、最大4つの他のセクターに接続できます。
とにかく、このためのコードを設計する方法について紙にアイデアを走り書きしていると、コードの一部の構造に頭を悩ませています。
プレイヤー クラスと、レベル/ダンジョン/エリアを表す「レベル」クラスを決定しました。このレベルのクラスは、相互接続された多数の「セクター」で構成されます。いつでも、プレーヤーはレベル内の特定のセクターに存在します。
だからここに混乱があります:
論理的には、player.Move(Dir d)
このようなメソッドはレベル オブジェクトの「現在のセクター」フィールドを変更する必要があります。これは、クラスPlayerがクラスLevelについて知る必要があることを意味します。うーん。また、LevelはPlayerオブジェクトを操作する必要がある場合があります (たとえば、プレーヤーが部屋に入る、何かに待ち伏せされる、在庫から何かを失う)。では、LevelもPlayerオブジェクトへの参照を保持する必要があるのでしょうか?
これは気分が悪いです。すべてが他のすべてへの参照を保持する必要があります。
この時点で、私が使用している本からデリゲートについて読んだことを思い出しました。C++ の関数ポインターについては知っていますが、デリゲートに関する章では、一種の「イベント ベース」プログラミングの観点から例が示されていましたが、それについてはあまり理解していませんでした。
これにより、次のようにクラスを設計するというアイデアが得られました。
プレーヤー:
class Player
{
//...
public delegate void Movement(Dir d); //enum Dir{NORTH, SOUTH, ...}
public event Movement PlayerMoved;
public void Move(Dir d)
{
PlayerMoved(d);
//Other code...
}
}
レベル:
class Level
{
private Sector currSector;
private Player p;
//etc etc...
private void OnMove(Dir d)
{
switch (d)
{
case Dir.NORTH:
//change currSector
//other code
break;
//other cases
}
}
public Level(Player p)
{
p.PlayerMoved += OnMove;
currSector = START_SECTOR;
//other code
}
//etc...
}
これはこれを行う良い方法ですか?
デリゲートの章がこのように提示されていなければ、私はそのような「イベント」を使用することを考えなかったでしょう. では、コールバックを使用せずにこれを実装するにはどうすればよいでしょうか?
細かいことまで書く癖があります…すみませんv__v