ゲーム開発に役立つプログラミングデザインパターンは何ですか?[閉まっている]


129

私はデザインパターンに関する書籍をいくつか持っており、いくつかの記事を読みましたが、どのプログラミングデザインパターンがゲーム開発に役立つかを直感的に理解することはできません。

たとえば、モデルビューコントローラー、シングルトン、ファクトリー、コマンドなどのいくつかのデザインパターンを詳しく説明したデザインパターンを含むActionScript 3という本があります。

これを初めて知った人として、これらのどれが役立つか、または実際、これらのどれが私が学び、使用しようとしている設計パターンであるかを理解できません。おそらく、私が気づいていないゲームプログラミング固有のデザインパターンが他にありますか?

ゲーム開発で特定のデザインパターンを使用した経験がある場合は、ぜひ聞いてください。それが使用された理由、コードサンプル、またはオンラインリソースについての推論は、それらがあれば非常に役立ちます。私は現在、ActionScript 3とC ++の実装に最も興味を持っていますが、あらゆる言語の経験と例から間違いなく恩恵を受けることができます。

ありがとう!


「おそらく、私が気づいていない他の、より多くのゲームプログラミング固有のデザインパターンがありますか?」-いいえ、これらのパターンは汎用的なものであり、使用している言語の機能を拡張するためにさらに適用されます。アプリケーションの主題とは関係ありません。
キロタン

3
@Kylotanそれぞれのデザインパターンは特定の問題に効果的な方法で対処することを目的としているため、特定の問題セットを与えられたデザインパターンはこの性質上、他のデザインパターンよりも有用であるように思えます。これらの問題セットは、ゲーム開発に固有のものです。確かに、いくつかのガイドラインがありますか、あなたの経験に基づいて、他のデザインパターンよりも頻繁に使用する特定のデザインパターンがありますか?
jcurrie33

誰かが出発して1000の異なるデザインパターンを学ぶ前に、これこれ
BlueRaja-ダニーPflughoeft

@ BlueRaja-DannyPflughoeft Seconリンクは無効です。再送信できますか?
Emadpres

回答:


163

いくつかの提案とともに、より軽快な応答のために。これらを実装の推奨事項としてではなく、可能な使用例として受け取らないでください。

  • ビルダー:データに基づいて、コンポーネントベースのエンティティを一度に1つのコンポーネントに設定します
  • ファクトリメソッド:ファイルから読み取られた文字列に基づいてNPCまたはGUIウィジェットを作成する
  • プロトタイプ:初期プロパティとともに1つの汎用「Elf」文字を保存し、それを複製してElfインスタンスを作成します。
  • シングルトン:このスペースは意図的に空白のままにします。
  • アダプター:既存のコードのように見えるレイヤーにラップすることにより、オプションのサードパーティライブラリを組み込みます。DLLで非常に便利です。
  • 合成:レンダリング可能なオブジェクトのシーングラフを作成するか、ウィジェットのツリーからGUIを作成します
  • ファサード:シンプルなインターフェースを提供することで、複雑なサードパーティライブラリを簡素化して、後の生活を楽にします。
  • フライウェイト:NPCの共有アスペクト(モデル、テクスチャ、アニメーションなど)を個々のアスペクト(位置、健康など)とは別に、ほとんど透明な方法で保存します。
  • プロキシ:サーバー上でより大きく複雑なクラスを表す小さなクラスをクライアント上に作成し、ネットワーク経由でリクエストを転送します。
  • 責任の連鎖:入力をハンドラの連鎖として処理します。グローバルキー(例:スクリーンショット用)、次にGUI(例:テキストボックスにフォーカスがある場合、またはメニューが表示されている場合)、ゲーム(例:キャラクターを移動するため)
  • コマンド:ゲーム機能をカプセル化して、コンソールに入力したり、保存および再生したり、ゲームのテストに役立つスクリプトを作成したりできます。
  • メディエーター:さまざまなコンポーネントで動作する小さなメディエータークラスとしてゲームエンティティを実装します(たとえば、AIコンポーネントにデータを渡すためにヘルスコンポーネントから読み取る)
  • オブザーバー:ゲームロジックがコードのレンダリングに関する知識を必要とせずに、必要に応じて視覚表現を変更するために、キャラクターのレンダリング可能な表現に論理表現からのイベントをリッスンさせます
  • 状態:NPC AIをいくつかの状態の1つとして保存します。攻撃、放浪、逃亡。それぞれが独自のupdate()メソッドと、必要な他のデータ(たとえば、攻撃または逃げるキャラクターの保存、さまよう場所など)を持つことができます。
  • 戦略:使用している地形の種類に応じて、A *検索のヒューリスティックを切り替えるか、同じA *フレームワークを使用して経路探索とより一般的な計画の両方を行うこともできます。
  • テンプレートメソッド:一般的な「戦闘」ルーチンをセットアップし、各ステップを処理するためのさまざまなフック関数を使用します。弾薬を減らし、ヒット率を計算し、ヒットまたはミスを解決し、ダメージを計算します。攻撃スキルの各タイプは、独自の方法でメソッドを実装します

いくつかのパターンは、インスピレーションの欠如のために除外されました。


シングルトンに関する非常に啓発的な議論はここにあります:misko.hevery.com/2008/08/25/root-cause-of-singletons
アンドリューワン

戦略パターンの+1。上記の正確な目的で使用しました(異なるA *ヒューリスティックをプラグインします)。
マイクストロベル

1
この答えのおかげで、それらはどこでも聞いている通常の「シングルトン」よりもデザインパターンのように聞こえます
...-jokoon

素晴らしい例のリスト。シングルトンパターンの慢性的な乱用(変装したグローバルステート)にも関わらず、正当な用途があります。実際に1つしか持っていない(または欲しい)リソースを表す場合。これは、ハードウェアのラップ(キーボード/マウスなど)やリエントラントでないライブラリのラップ(これが発生し、すべての言語に魔法の同期キーワードがあるわけではない)のようなものです。
チャースター

11
ハードウェアリソースにシングルトンを使用することはまだありません。ビデオカードやモニターが年を追うごとに増えていったように、1つしかないと思われるアイテムは後で増加する傾向があります。同様に、一部のAPIでは、1つのゲームパッドを理解するために2つのジョイスティックを読む必要があります。だから、もしあなたが何かの一つだけを必要とするなら、ただ一つをインスタンス化して、おそらく必要ではないt意的な制限を強制しないでください。
キロタン

59

私はまさにそのトピックに関する本を書きました:ゲームプログラミングパターン。そこにある章はあなたに役立つかもしれません。


2
+1私は誰かがそれにリンクしてくれることを望んでいましたが、著者が持っていることがわかりました!そこにあるコンポーネントパターンの説明は非常に役に立ちました。完全なコード例を使用して説明してみてください。
CodexArcanum

2
ええ-数年前にリンクを読んだことを覚えています。これらの記事を終了する必要があります!
onedayitは

2
これで本が完成しました:)
デュサン

1
既存のプログラミングの知識をゲームのプログラミングに変換するのに役立つ素晴らしいリソース。書いてくれてありがとう!

このゲームプログラミングパターンの説明は、実際には、ソフトウェアデザインパターンブックが実際にやったことのない方法で-デザインパターン-を理解するのに役立ちました!これは部分的にはゲーム開発の力(私に話しかけ、開発全体を改善できる言語の具体例)ですが、文章が非常に優れているため、より大きな部分を占めています。
クズカイ

19

Brandon EichがCoders at Work提唱する意味があったことの1つは、パターンがハッキングと回避策であるということです。[パターン]は、言語に何らかの欠陥を示しています。これらのパターンは無料ではありません。無料のランチはありません。したがって、適切なビットを追加する言語の進化を探している必要があります。

コンパイラデザイナーではなくゲームプログラマーとして、使用する言語を進化させるオプションはほとんどありませんが、言語や要件に合わせて独自のスタイルを進化させることを学ぶことができます。パターンはこれの一部ですが、特にブランドンが言うように、パターンが顕著なパフォーマンス、メモリ、またはコードの俊敏性のコストを失うことはめったにないため、パターンを使用しないことは別の部分です。MVCは、ゲームの多くの要素に適したパターンではありません。シングルトンは、不完全なC ++静的初期化ルールの回避策であり、おそらくこれらを行うべきではありません。ファクトリは複雑なオブジェクトの作成を単純化します-オブジェクトは最初からもっとシンプルにすべきかもしれません。人気のあるパターンは、必要なときに頼るツールです 最初は複雑なものを構築するために使用したいツールではなく、複雑なものを管理します。

優れた(ゲーム)コードはパターンを使用する場合と使用しない場合があります。パターンを使用する場合は問題ありません。言語に依存しない高度なレベルで他のプログラマーにコード構造を説明するための優れたコミュニケーションツールです。パターンを使用せずにコードの方が優れていると思う場合は、パターンに勝てないでください。


4
はい、元の本で明らかにされたものの1つ(ただし、しばしば見落とされます)は、C ++ / SmalltalkではなくC向けに書かれている場合、「継承」パターンが含まれていた可能性があります。既に組み込まれているGoFパターンの一部が含まれている可能性があります
。– Kylotan

13
オリジナルの本(GoFではなく、Alexanderによるオリジナルのオリジナルの本)でしばしば見落とされていたもう1つのことは、パターンは実装ではなくコミュニケーションのためのツールであるということでした。設計者は、実装についてより高いレベルで通信できます。また、可能な場合に使用する必要があるというわけではないため、反復しているため識別されます。

1
ただし、用語を単に持っているだけで、問題について推論し、そのようなアプローチがいつ優れたソリューションであるかを認識できます。最良のパターンは通常、熟練した経験豊富な労働者によって時間の経過とともに洗練されてきましたが、これらの成文化された例がなければ、それほど熟練していない労働者は同じパターン自体を発見しません。
キロタン

用語を持っていることは素晴らしいことであり、パターンの定義の一部は、それが何らかの問題に対する繰り返しの良い解決策であることです。残念ながら、スキルの低い労働者はほとんどシングルトンを見つけて、まだ問題がない場合でもすべての問題にそれを適用する傾向があります。

この応答をありがとう。ソフトウェアの設計によって生じた問題を解決するために設計パターンが作成されたことを読んでホッとしました。大きなソフトウェア全体の構造は、実際に何かをコーディングし始める前に、最初から最後まで考え抜かれるべきだと思います。機能を一度に一度に実装することはできません。特定の各機能について考える必要があり、ソフトウェアのグローバル構造を混乱させないか、ソフトウェアがどのように処理されるかを邪魔しないかどうかを確認する必要があります。振る舞います。タスクを複数のプログラマに分割すると、矛盾が生じる場合があります
...-jokoon

7

もちろん、他の人が言ったように、すべてのパターンは適切な状況で有用であり、それらの使用方法を学ぶことの一部は、いつ使用するかを学ぶことです。しかし、Daniel Sanchez-Crespo Dalmauによる優れた書籍 『Core Techniques and Algorithms in Game Programming』には、ゲームプログラミングで特に役立つ6つのプログラミングパターンと6つのユーザビリティパターンがリストされています。

プログラミング:

  • シングルトン:多くの人がそうするように、私はこれを嫌いではありません。シングルプレイヤープレーヤーやキーボードリーダーなどに使用できます。
  • ファクトリ:オブジェクトを効率的に作成および破棄できます。
  • 戦略:AI戦略をエレガントに変更できます。
  • 空間インデックス:空間データセットでクエリを実行できます。
  • Composite:便利なオブジェクト階層を設定します。
  • フライウェイト:同一の敵のようなものを一般化することにより、メモリを解放します。

使いやすさ:

  • シールド:劇的なアクションの偶発的な起動から保護します。
  • 状態:世界/ UIステータスの視覚的な合図。
  • 自動モードキャンセル:ゲームをより直感的に機能させます。
  • 磁気:自動照準と簡単なユニット選択。
  • フォーカス:気を散らすUI要素を排除します。
  • 進捗状況:広く有用です。

この本は、もちろん、これらのそれぞれについてさらに詳しく説明しています。


入力いただきありがとうございます!私はその本に気づいていませんでしたが、あなたの投稿の結果、今それを調べます。再度、感謝します!
jcurrie33

2
キーボードリーダーのシングルトンはまさに私が尋ねなければならない状況です-あなたは本当にそれをあなたのメイン関数の初期に設定されたグローバルなポインタにするだけではありませんか?実際に2つのキーボードリーダーを誤ってインスタンス化したことがありますか?

シングルトンを憎んでください。それは2つのことを不十分に行います。グローバルアクセスとアリティ。多くの場合、開発者はグローバルアクセス==シングルトンと考えています。そこは非常に比べていくつかの問題は、真のシングルトンを必要とし、シングルトンで解決する場合よりエレガントであることがより可能性がいくつか。
deft_code

7

エンティティシステムは、すばらしい種類のパターンです。それは、OOPのトリックではないので、厳密にはデザインパターンではありません。ただし、OOPと組み合わせることができます。

いくつかの良いリンク(イントロの先頭から開始):


3
「それは、厳密に[sic] OOPではないため、厳密には設計パターンではありません。」デザインパターンはOOPとは関係ありません。どちらかといえば、OOP自体がデザインパターンです。設計パターンは、OOPの外だけでなく、ソフトウェア開発全体の外にも現れます。

ありOOP design patterns、通常のクラス/オブジェクト間の関係と相互作用を示すこと。他にも多くのデザインパターンがあります。OOPは一連の概念であり、実際のパターンではありません。Design pattern概念でもあります。
右上

6
セマンティックについて話す代わりに、私が出した応答の有用性を評価してはいけませんか?
ワーナイト

6

それらのすべて。シングルトンを除く。[/ flippancy]


ゲーム開発で頻繁に使用した1つまたは2つのデザインパターンに名前を付けてもらえますか?設計パターンに関する初心者として、「それらのすべて」は特に役立つ応答ではありません。ただし、ご回答いただきありがとうございます。
jcurrie33

5
「どのパターンを使用しましたか?」「どの変数名を使用しましたか?」それは個人的なスタイルと要件とドメインに帰着します。ある時点で、おそらくこれまでに名前が付けられたパターンを使用するでしょう。おそらく、名前が付けられていないものをさらに多く使用し、新しいものを発明することもあります。

@ jcurrie33:申し訳ありませんが、私は最初にシングルトンを掘ることに抵抗できませんでした。;)
カイロタン

6

パターンについてではなく、その背後にある基本原則についてです。では、「デザインパターン:オブジェクト指向における再利用のための」(1995) ;:、4(ガンマ、エーリッヒ・リチャードヘルム、ラルフ・ジョンソン、およびジョン・ブリシディース)のギャングは、オブジェクト指向設計のための唯一の2つの原則をお勧めします(1)プログラムへの実装ではなくインターフェイスであり、(2)クラスの継承よりもオブジェクトの構成を優先します。

これら2つの原則は、ゲーム開発の多くのタスクで非常に役立ちます。たとえば、多くのゲームプログラマーは、深いクラス階層を使用してゲームエンティティを表現しています。構成に基づく別のアプローチがあります-コンポーネントベースのゲームオブジェクト。このアプローチに関する記事さらにリンク。これは、デコレータパターンの例です。


ゲームデザインで使用されるコンポーネントは、ステートフルな戦略パターンに似ています。これは、当然、C / C ++ / Java / C#の外部のクロージャー、および内部のコンポーネントオブジェクトとして表されます。デコレータパターンはプロキシに似ています。その所有権とデータフローは、ゲームのコンポーネントシステムについて話すときに通常意味するものとは逆です。

また、コンポーネントは互いに対話し、Mediator、Observer、Composerなどのパターンを取り込む必要があります。「コンポーネントベースのゲーム」は、それ自体が複合デザインパターンです。
CodexArcanum

@ CodexArcanum、Observer、明確に、しかし必ずしもそうではないメディエーター(代わりに責任のチェーンを使用できます)。GameObject(GameObjectComponentで構成される)がGameObjectComponent自体(必須ではない)である場合にのみComposerです。
右上

6

不思議定期的なテンプレートパターンは、仮想メソッドと仮想関数呼び出しから来ることができ、パフォーマンスの低下を避けるために本当に便利です。

これは、必要なインターフェイスを持つ基本クラスタイプのコンテナを実際に持つ必要はないが、同様の名前の動作とインターフェイスが必要な場合に適切なパターンになります。

たとえば、コンパイル時に型の違いがわかっている複数のプラットフォームまたはエンジン(dxとopengl)のクラスをコンパイルするときにこれを使用できます。


私は、OS抽象化レイヤーが仮想であることを常に嫌っていました。2つのOS抽出レイヤーが必要になることはありません。CRTPを使用する方がはるかに優れています。
deft_code

たぶん私は年寄りですが、DX / OpenGLまたはプラットフォームインターフェイスにCRTPを使用することすらありません。コンパイルするには遅すぎます-typedefを使用するだけです。CRTPは、クラス間でインターフェイスと実装を共有したいが、他の関係がない場合に適しています。1つの構造体だけを選択する場合ではありません。

4

私が長年にわたって進化させたデザインパターンは、私にとって非常に有用でしたが、「ブローカー定義セット」と呼ぶものです。GOFの用語でそれを要約する方法は議論の余地があるように見えますが、StackOverflowでそれについて書いこの質問は、それについていくらか詳しく説明します。

コアコンセプトは、クリーチャーの種のようなモデルの一部のプロパティを設定し、プロパティの可能な値ごとに対応する定義オブジェクト(値ごとに1つの共有オブジェクト)を設定し、その動作を指定することです。そして、これらは中央ブローカー(GOFに関しては、レジストリ、ファクトリー、またはその両方かもしれません)を介してアクセスされます。私の使用法では、ランタイムモーフィズムの目的で弱いバインディングを容易にするために、通常はスカラーキーを介してアクセスされます。


これがどのようにシングルトンであるかはまったくわかりません。フライウェイトパターンについて説明するとき、「レジストリ」という言葉は冗長です。これは単なるフライウェイトです。

SOスレッドからの私の理解は、定義がクラスとして設定されているため、人々がシングルトンをその一部であると特定したことです。Registryに関しては、Factoryと置き換えたり組み合わせたりできる場合に、どのように冗長になるかわかりません。
カオス

-1は、パターンが迅速に通信する程度まで、これはおそらく私が見た最大の失敗です。この説明を真剣に受け止めることはできません。

イエス様、あなたのためにクッキーを切ることができなかったことをご容赦ください。「エンティティシステム」の回答も、GOFの用語ですぐに要約できないため、投票するつもりですか。
カオス

1
ある程度の「cookie-cutter」、または少なくとも意味の明確さは、パターンが有用であるために必要なものです。「フライウェイト」や「シングルトン」などの用語は一般的に理解されているため、相互に排他的です。1つ目は、複数のインスタンス間でデータを自動的に共有することです。2番目は、インスタンスを1つだけ持つことです。デザインの選択が役に立たなかったり、悪いとさえ言っているわけではありませんが、「十分に近い」パターン名を詰め込むと、誰もが混乱するだけです。(特にCWでは、個人的にdownvotesを取らないでください。)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.