コンポーネントベースのアーキテクチャを使用して効果的なゲームオブジェクト相互作用スキームを設計するにはどうすればよいですか?


14

これは設計上の質問です...これはもっと一般化できると思いますが、私はそれに苦労しています。ゲームオブジェクトインタラクションのデザインについて疑問に思っています。これが私の例です(2Dパズルプラットフォーム)。

プレイヤーがレベルを進めようとしているとしましょう。さまざまな方向に向けることができる多くのライトがあります。以下は、これらのライトオブジェクトがどのように相互作用するかの例です。

  • ある光は、プレイヤーがギャップを越えることができるプラットフォームを投影します
  • 1つのライトは、触れるものの摩擦係数を下げ、別のライトはそれを増やします
  • 1つのライトはすべてのライトの効果を無効にします。これにより、そのライトがオンのときにプラットフォームが消え、摩擦調整剤が無効になります。
  • 等...

コンポーネントアーキテクチャを使用する場合、この問題に対処する最良の方法は何ですか?各主要オブジェクトのコンポーネントは明らかであり、環境への影響を明確に定義する方法もあります。相互作用を「解決」するクラス(そのようなものはすぐに混乱する可能性があります)?特定の時間に相互作用しているオブジェクトの結合オブジェクトを作成するためのデコレータパターンの使用法 これに役立つデータ構造?

また、これらのインタラクションにオーディオを接続しますか?オーディオをシステムに接続することは、可視性やプレーヤーの移動/衝突など、他のプロパティを接続するのと同じように思えます。

コンポーネントが追加されるにつれて、新しいコンポーネントをほとんど変更せずに処理できる堅牢なシステムがあればよいのは明らかですが、これをどのように設計するかについてはよくわかりません。

その他の情報:私が使用しているエンジンは、IceCreamと呼ばれるXNAエンジンです。



2
ただし、Joeが提供するリンクの「質問」とは対照的に、ここには実際の質問があります。
ダッシュトムバン

2
コンポーネントシステムを使用して、コードで特定のゲームの要件を設計する方法についての質問です(@Christopher:どちらが役立つか、Unityを使用していますか?Torque?Proprietary?)
LearnCocos2D

2
私はあなたのゲームプレイのアイデアが好きです=)
ネイラー

回答:


5

オブジェクト指向システムでは、Xを実行する最善の方法であるという質問に対する唯一の本当の答えは、何かを実行して実行するために考えられる最も単純な方法でXを実行することです。表現が簡単になります。コードを書く前に適切なパターンを選択することに関しては、始めから間違った答えに悩まされる良い方法です。パターンとコンポーネントのすべての考えを溶かし、現在の場所から始めて、次の手順に従うだけです(軽いコンポーネントを実装したと仮定します)。

  1. プロジェクトコンポーネントにライトコンポーネントにコードを追加します。(これを機能させます。)
  2. そのコンポーネントを新しいコンポーネントにコピーし、プラットフォームのものを削除して、適切なオブジェクトの摩擦を減らすためのコードを追加します。(これを機能させ、#1がまだ機能することを確認します。)
  3. そのコンポーネントを新しいコンポーネントにコピーし、「新しい」コードを削除して、他のコンポーネントの効果を無効にするものを追加します。(これを機能させてから、#1と#2が機能することを確認してください。)

この時点で、(おそらく)重複したコードが大量にあります。共通のコードを関数または別のクラス(基本クラスなど)または適切と思われるものに抽出します。「ライトコンポーネント」から始めたからといって、LightComponentが適切なベースであるとは限りません。ライトコンポーネントを構成するコードは、実際には「コンポーネント」ではなく、一連の関数や、新しいコンポーネントに(メンバー変数として)集約される個別のクラスで最も適切に表される可能性があります。 )。


これを答えとしてマークしているのは、「どのように設計すればよいか...」と真に答えるからです。このおかげで、間違いなく正しい道を歩むことができました。
クリストファーホレンシュタイン

2

一般的に、タイプAのオブジェクトがタイプBのオブジェクトと対話するとき、何らかの効果Cが必要です。これは、 「ダブルディスパッチ」とれ、C言語のようにエレガントに行うのは非常に困難です。

効果的で保守が難しい方法は、オブジェクトのタイプに応じて、一連のswitchおよびifステートメントだけです。あなたはそれを書くのは汚い気がするでしょうが、それは仕事を終わらせるでしょう。

Visitorパターンは、厄介なタイプのスイッチングを隠し、より堅牢なソリューションですが、設定するclumbersomeことができます。

通常、コード内のあらゆる種類のタイプ切り替えは匂いですが、ここでは、通常は単一のタイプに基づいて機能を切り替え、2つのタイプに基づいて機能を切り替える多態性を一般化しようとしています。多型はOOPの基盤であるため、臭いではありません。


2

そうねぇ。これは、執筆中に頭の中で調理したものです。

あなたの周りの適切な距離にあるすべてのライトノードを取得します。

各ライトについて、その効果範囲を表すポリゴンをフレームバッファーオブジェクトにレンダリングします。したがって、光の円錐は、FBOに1種類のピクセルの円錐を作成します。パス内の各ノードタイプを適切な優先度でレンダリングします。緑のチャンネルが摩擦、赤が重力、青とアルファが他の何かのように、情報を各ピクセルにエンコードできます。

巧妙なカラーブレンディングテクニックは、興味深い効果を生み出すことができます。各レベルには独自のブレンディングルールを設定できます。また、脈動重力などのサイケデリックなダイナミックエフェクト用にフラグメントシェーディングを追加することもできます。

最後に、マンドッドがどのピクセルに触れているかを確認し、事前に計算された領域の端に近づくたびにビットマップの再計算を行います。

私のアイデアを説明するために2分で作成された大まかなスケッチ:

図

編集:実際には、これは、必要なものが特定の色を発する1つのライトコンポーネントだけであることを意味します。どの色が何をするかに関するルールは、完全にどこか他の場所になります。多くのデータをprピクセルの32ビットにエンコードできます。または、相互に影響しない異なる属性を含む複数のFBOを使用できます。1つの重力/摩擦FBOと1つの1ビット衝突FBOを使用できます。これを選択した場合、当然、ライトをレンダリングするFBOにフラグを立てる必要があります。


ご意見ありがとうございます。私はビジュアルに本当に感謝しており、これはメカニックが舞台裏でどのように機能するかについて本当に考えさせられました。
クリストファー・ホレンシュタイン

へえ、問題ありません。あなたの正確な質問には答えていませんが、いくつかの問題には特別な解決策が必要です。幸運を!
ネイラー

0

オブザーバーパターンは最適なソリューションの1つです。メッセージは、実際に関心のあるオブジェクト(コンポーネント)にのみ送信されます。したがって、受信者はこのメッセージ/イベントタイプをサブスクライブする必要があります。

多くのシグナル/スロット実装があります。たとえば、C ++には sigslotライブラリがあります

詳細については、Qtシグナルとスロットについてお読みください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.