作成中のゲームの新しいパワーアップ システムを設計しています。サイド スクローラーです。パワーアップは円形のオブジェクトとして表示され、プレイヤーはそれらに触れたり移動したりしてパワーを取得する必要があります。その後、パワーアップが有効になり、数秒後に無効になります。各パワーアップには、独自の期間が定義されています。簡単にするために、パワーアップは X 秒ごとに生成されます (画面に配置されます)。
私は PowerUpManager を作成しました。これは、新しいパワーアップをいつ作成し、どこに配置するかを決定する仕事をするシングルトンです。
次に、Powerup 基本クラスと、新しい Powerup ごとにその基本クラスを継承するクラスを作成しました。すべてのパワーアップは、3 つの状態のいずれかになります: 無効、画面に配置、プレイヤーが拾う。プレーヤーがパワーアップを拾わずに移動した場合、パワーアップは画面を終了し、配置された状態から無効な状態に戻る必要があるため、再度配置できます。
(私が) 設定した要件の 1 つは、新しい Power up クラスをコーディングするときにコードの変更を最小限に抑えることです。私ができる最善のことは、1 つのコードでした: PowerUpManager のコンストラクター。ここで、すべてのパワーアップを保持するコンテナーに新しいパワーアップを追加する必要があります。
PowerupManager::PowerupManager()
{
available = {
new PowerupSpeed(),
new PowerupAltWeapon(),
...
};
}
PowerUpManager の詳細 (質問は近日公開予定です!): 使用可能と呼ばれる PowerUp (基本クラス) へのポインターのベクトルを保持します。これは、ゲーム内の各パワーアップのコピーを 1 つ保持する最初のコンテナーです。さまざまな状態を処理するために、いくつかのリストがあります: 現在配置されているパワーアップへのポインターを保持するリストと、現在アクティブなパワーアップへのポインターを保持する別のリストです。また、新しいパワーアップを配置するかどうか、どこに配置するか、およびピックアップされなかったパワーアップをクリーンアップするかどうかを決定するすべてのゲーム ティックが呼び出されるメソッドもあります。最後に、プレイヤーがパワーアップに遭遇したときに呼び出され、パワーアップをアクティブにするメソッドがあります (配置リストからアクティブ リストに移動し、パワーアップの activate メソッドを呼び出します)。
最後に、全体像を理解したら、質問: クライアント コードが特定のパワーアップが現在アクティブかどうかを確認する方法が必要でした。例: プレイヤーは武器を持っていますが、その武器を一時的に置き換えるパワーアップがあります。入力をポーリングし、プレーヤーが武器を発射したいことを認識した場合、正しい発射メソッドを呼び出す必要があります。通常の武器発射メソッドではなく、代替武器のパワーアップ発射メソッドです。
この特定の需要についてしばらく考えた結果、次のように思いつきました。
template <typename T>
T* isActivated() // Returns a pointer to the derived Powerup if it exists in the activated list, or nullptr if it doesn't
{
for(Powerup *i : active) // Active is a list of currently active power ups
{
T *result = dynamic_cast<T*>(i);
if(result)
return result;
}
return nullptr;
}
したがって、クライアント コードは次のようになります。
PowerUpAltWeapon *weapon = powerUpManager->isActivated<PowerUpAltWeapon>();
if(weapon)
...
解決策はエレガントですっきりしていると思いましたが、基本的には基本型を派生型に変換しようとしています。それが機能しない場合は、次の派生型を試します... if / else if の長いチェーンは、ループで偽装されているだけです。これは、先ほど説明したガイドラインに違反していますか? ヒットするまで、if / else if の長いチェーンで基本型をすべての派生型にキャストしませんか? 別の解決策はありますか?
2 つ目の質問は、PowerupManager コンストラクターでさまざまなパワーアップをすべて構築する必要をなくす方法はありますか? 新しいパワーアップを導入したい場合、現在変更が必要な場所はここだけです。そこを解消できたら面白いのに…