これは通常、メッセージを使用して行われます。このサイトの他の質問には、ここやそこなど、たくさんの詳細があります。
特定の例に答えるにはMessage
、オブジェクトが処理できる小さなクラスを定義する方法があります。例:
struct Message
{
Message(const Objt& sender, const std::string& msg)
: m_sender(&sender)
, m_msg(msg) {}
const Obj* m_sender;
std::string m_msg;
};
void Obj::Process(const Message& msg)
{
for (int i=0; i<m_components.size(); ++i)
{
// let components do some stuff with msg
m_components[i].Process(msg);
}
}
このようにしてObj
、コンポーネント関連のメソッドでクラスインターフェイスを「汚染」することはありません。メッセージの処理を選択できるコンポーネントもあれば、無視するコンポーネントもあります。
最初に、このメソッドを別のオブジェクトから直接呼び出すことができます。
Message msg(obj1, "EmitForce(5.0,0.0,0.0)");
obj2.ProcessMessage(msg);
この場合は、obj2
さんはPhysics
メッセージを選択し、処理することが行う必要があるものは何でもします。完了すると、次のいずれかになります。
Position
コンポーネントが選択する「SetPosition」メッセージを自分に送信します。
- または
Position
、変更のためにコンポーネントに直接アクセスします(すべてのオブジェクトにPosition
コンポーネントがあるとは限りませんが、Position
コンポーネントがの要件である可能性があるため、純粋なコンポーネントベースの設計ではかなり間違っていますPhysics
)。
通常、メッセージの実際の処理を次のコンポーネントの更新まで遅らせることをお勧めします。それをすぐに処理することは、他のオブジェクトの他のコンポーネントにメッセージを送信することを意味する可能性があります。
おそらく後で、より高度なシステムを使用する必要があります。非同期メッセージキュー、オブジェクトのグループへのメッセージの送信、コンポーネントごとのメッセージの登録/登録解除などです。
上記のMessage
ように、クラスは単純な文字列の汎用コンテナにすることができますが、実行時の文字列の処理は実際には効率的ではありません。文字列、整数、浮動小数点数などの一般的な値のコンテナを使用できます。名前を付けて、さらにはIDを付けて、さまざまなタイプのメッセージを区別できます。または、特定のニーズに合わせて基本クラスを派生させることもできます。あなたのケースでは、目的の力ベクトルEmitForceMessage
から派生しMessage
て追加するを想像できますが、そうする場合はRTTIの実行時のコストに注意してください。