web-dev-qa-db-ja.com

関連するオブジェクトをモジュール式に実装するにはどうすればよいですか?

質問のタイトルをできるだけ一般的に適用できるようにしようとしましたが、それをうまく表現したかどうかはわかりません。それは私が抱えている非常に具体的な問題によって引き起こされたものであり、この質問の残りの部分では、それについて説明しようと思います。

グラフィック、物理学、衝突*を備えた小さなゲームエンジンを書こうとしています。私はこれらのそれぞれを別々に実装しようとしています。衝突できない(火の効果?)グラフィック表示された物理的に移動するオブジェクト、または物理学によってレンダリングまたは制御されない衝突オブジェクト(目に見えないバリア)があることは完全に考えられます。ただし、多数のオブジェクトには3つすべてが必要です。

3つのピースをほぼ完全に独自のクラスに分離できると確信しています。ただし、1つの例外は、すべて同じ位置とオブジェクトのangular方向)を参照する必要があることです。

当初は、それぞれを独自のクラスに入れて、実際のゲームオブジェクトを多重継承で構築することを考えていましたが、データを共有する必要があることを考えると、それがうまくいくかどうかはわかりませんでした。

次のオプションは、各オブジェクトを適切な位置と方向のデータへのポインターで初期化することでしたが、それらを特別なメンバーのように扱うのは奇妙に感じました。 。 。私は各クラスが他のクラスに対してできるだけ無知であるように振る舞うことを望みます、そして私が各クラスを独立して設計しているなら私は決してポインターをしません。

また、各クラスに独自の位置データを設定し、組み合わせクラス(友情またはゲッター/セッターのいずれかを介して)ですべてを強制的に一致させることもできますが、それも正しくありませんでした。

私はGoogleで通常行われていることに関する情報を検索しようとしましたが、見つけたほとんどすべてがシステムの特定の部分に焦点を合わせており、すべてを統合することについてはあまり語っていませんでした。私は哲学的すぎるだけですか、それともこれを行うためのより良い方法がありますか?

重要な場合は、C++を使用しています。

ありがとう。


*自分で実装しても意味がないことは知っていますが、それはすべて楽しみのためです。

4
Jordan

スーパークラスではなくサービス

これらは関連するオブジェクトではなく、ゲームオブジェクトの状態が変化したときに出入りする可能性のあるゲームオブジェクトの動作の側面です。それらをスーパークラスではなくサービスとして考えてください。ゲーム内の動作は時間の経過とともにゲームオブジェクトの状態に強く依存する可能性があるため、これらは純粋に構成要素にも適していません。

「ゴースト」オブジェクトは、目に見えて動いている場合がありますが、固体オブジェクトを通過することはできますが、魔法の障壁を通過できない場合があり、生体組織と衝突したときに損傷を与える可能性があります。それは魔法の武器によってのみダメージを受けることができます。

ごめんなさい

ゲームプログラミングは難しく、このレベルでは主にモデリングの複雑さが原因です。ハックして自分のアイデアを入手したり(楽しんでいる場合)、既存のゲームエンジンを調べて、他の人が何をしたかを確認します(例: nreal Engineのソースコード

3
Steven A. Lowe

あなたは自然にエンティティコンポーネントシステムに向かって進んでいます。

enter image description here

OOPの考え方を何年も適用している場合、実行するのが最も難しい最後のステップは、それらの共有コンポーネントを生データしかし、ECSの真の柔軟性を実際に理解できるようになるのはその時だけです。私は、コンポーネントを生データにした2回目の反復まで、実際には頑固に抵抗しました。

これがすべて間違っているように見え、カプセル化と情報隠蔽の完全な違反であるという感覚を打ち消す方法は、通常、1つまたは2つのシステムのみが特定のコンポーネントにアクセスし、多くの場合、実際に変換(変更)する1つのシステムのみであることを覚えておくことです。データ。結果として、コンポーネント内の不変条件を維持することは、実際にはそれほど難しくありません。また、すべてを処理する粗いシステムで、より広いコンポーネント間不変条件を簡単に維持できるようにする傾向があります。

エンティティはコンポーネントの単なるコンテナです(エンティティごとに最大1つのコンポーネントタイプインスタンスがあります)。コンポーネントは単なる生データです。システムはエンティティ/コンポーネントを処理し、これら3つの間の機能の唯一のプロバイダーです。また、システムは一般に相互に分離されており、通常は相互に関数を呼び出しません。ほとんどのシステムは、次のようなループパターンにも似ています。

for each entity with these specific components:
    do something with the components

たとえば、上記のレンダリングシステムは次のようになります。

for each entity with pos/velocity and Sprite components:
    render Sprite component at pos

移動システムは次のようになりますが、次のようになります。

for each entity with pos/velocity components:
    pos += velocity * time_elapsed
0
user204677