ゲームのアーキテクチャ/デザインパターンに関するアドバイス
私はしばらくの間2D RPGに取り組んでいますが、デザインに関するいくつかの悪い決定を下したことに気付きました。特に問題を引き起こしているものがいくつかあるので、他の人がそれらを克服するためにどのようなデザインを使用したのか、または使用するのだろうかと思っていました。 少し背景を説明するために、私は去年の夏休みに仕事を始めました。最初はC#でゲームを作成していましたが、約3か月前にC ++に切り替えることにしました。C ++を頻繁に使用してからしばらく経っていたので、C ++の適切なハンドルを取得したかったので、このような興味深いプロジェクトが良い動機付けになると考えました。ブーストライブラリを広く使用しており、グラフィックスにはSFMLを、オーディオにはFMODを使用しています。 かなりの量のコードが書かれていますが、それを廃棄して最初からやり直すことを検討しています。 ここに私が持っている主要な関心分野があり、他の人がそれらを解決したり、解決したりする適切な方法について意見を聞きたいと思いました。 1.循環的な依存関係 C#でゲームを実行していたとき、C#での問題ではないので、これについて実際に心配する必要はありませんでした。C ++に移行すると、これはかなり大きな問題になり、間違って設計したのではないかと思うようになりました。クラスを分離する方法を想像することはできませんが、それでもクラスに自分のしたいことをさせることができます。依存関係チェーンの例をいくつか示します。 ステータス効果クラスがあります。このクラスには、キャラクターに効果を適用するためのいくつかのメソッド(Apply / Unapply、Tickなど)があります。例えば、 virtual void TickCharacter(Character::BaseCharacter* character, Battles::BattleField *field, int ticks = 1); この関数は、ステータス効果を与えられたキャラクターがターンするたびに呼び出されます。Regen、Poisonなどのエフェクトを実装するために使用されます。ただし、BaseCharacterクラスとBattleFieldクラスへの依存関係も導入します。当然、BaseCharacterクラスは、現在どのステータスエフェクトがアクティブになっているかを追跡する必要があるため、循環依存関係になります。バトルフィールドは戦闘パーティーを追跡する必要があり、パーティークラスには別の循環依存関係を導入するBaseCharactersのリストがあります。 2-イベント C#では、キャラクター、バトルフィールドなどのイベントにフックするためにデリゲートを広範囲に使用しました(たとえば、キャラクターのヘルスが変化したとき、ステータスが変更されたとき、ステータスエフェクトが追加/削除されたときなどにデリゲートがありました。)そして、戦場/グラフィックコンポーネントがそれらのデリゲートにフックして、その効果を強化します。C ++では、似たようなことをしました。明らかに、C#デリゲートに直接相当するものはないため、代わりに次のようなものを作成しました。 typedef boost::function<void(BaseCharacter*, int oldvalue, int newvalue)> StatChangeFunction; そして私のキャラクタークラスで std::map<std::string, StatChangeFunction> StatChangeEventHandlers; キャラクターのステータスが変更されるたびに、マップ上のすべてのStatChangeFunctionを繰り返し呼び出します。動作しますが、これは物事を行うための悪いアプローチであることが心配です。 3-グラフィックス これは大きなことです。これは私が使用しているグラフィックスライブラリとは関係ありませんが、概念的なものです。C#では、グラフィックスを、ひどいアイデアだとわかっている多くのクラスと結合しました。今回はそれを分離したいので、別のアプローチを試みました。 グラフィックを実装するために、ゲームに関連するすべてのグラフィックを一連の画面として想像していました。つまり、タイトル画面、キャラクターステータス画面、マップ画面、インベントリ画面、バトル画面、バトルGUI画面があり、基本的にこれらの画面を必要に応じて積み重ねてゲームグラフィックを作成することができます。アクティブな画面が何であれ、ゲーム入力を所有します。 ユーザー入力に基づいて画面をプッシュおよびポップする画面マネージャーを設計しました。 たとえば、マップ画面(タイルマップの入力ハンドラー/ビジュアライザー)で起動ボタンを押した場合、スクリーンマネージャーへの呼び出しを発行して、メイン画面をマップ画面上に押してマップをマークします。描画/更新されない画面。プレーヤーはメニューをナビゲートし、必要に応じてより多くのコマンドをスクリーンマネージャーに発行して、新しいスクリーンをスクリーンスタックにプッシュし、ユーザーがスクリーンを変更/キャンセルするとそれらをポップします。最後に、プレーヤーがメインメニューを終了したら、ポップメニューからポップしてマップ画面に戻り、描画/更新するようにコメントして、そこから移動します。 バトル画面はより複雑になります。背景として機能する画面、戦闘の各パーティを視覚化する画面、および戦闘のUIを視覚化する画面があります。UIはキャラクターイベントにフックし、それらを使用してUIコンポーネントをいつ更新/再描画するかを決定します。最後に、使用可能なアニメーションスクリプトを使用するすべての攻撃は、画面スタックからポップする前に、追加のレイヤーを呼び出して自身をアニメーション化します。この場合、すべてのレイヤーが一貫して描画可能で更新可能としてマークされ、バトルグラフィックスを処理する画面のスタックを取得します。 私はまだスクリーンマネージャを完全に動作させることができていませんが、しばらくはできると思います。それについての私の質問は、これは価値のあるアプローチですか?悪いデザインの場合、必要なすべての画面を作成するのに多くの時間を費やす前に、今すぐ知りたいと思います。ゲームのグラフィックをどのように構築しますか?