1

背景:
私は現在ゲームに取り組んでいます。このゲームでは、プレーヤーが操作できる椅子、テーブル、絵画など、いくつかの種類の家具があります。このために、GameObjectこれらすべてのオブジェクトに共通するすべてのもの(描画、位置変数の保持など)を処理する抽象クラスを作成しました。家具には、幅と高さ(整数)、ユーザーが家具を操作することを選択したときに何が起こるかなど、いくつかの異なるパラメーターがあります(例:椅子->プレーヤーが近くにいる場合、座っている場合、テーブル->何もない、絵画->距離に関係なく調べる)。家具はメニューから作成でき、選択したピースのある種の識別子(現在は整数)を返します。

質問:
さまざまな家具をどのように実装すればよいですか?
1つの方法は、家具ごとにサブクラスを作成することです。しかし、これには2つの欠点があります。まず、その多くのクラスを管理するのは困難です。次に、家具を作成するときに、識別子に基づいてGameObjectの正しいサブクラスを作成する必要があります(フォローアップの質問を参照)。

私にとって最も論理的なオプションは、コンストラクターで幅と高さのパラメーターを受け取る一般的なクラスと、ユーザーがオブジェクトをクリックしたときに実行できる実行可能/その他のインターフェイスを作成することです。さまざまな値をデータベースに保存し、識別子に基づいて取得することもできますが、Runnablesを外部に保存できないため、さまざまなアクションで問題が発生し、ソリューション1と同じ問題が発生します。現在のオブジェクトに対して1つを選択する必要がある多くの異なるクラス。

フォローアップの質問: 家具の種類とアクションによっては、追加のメソッドを備えたより高度なサブクラスが必要になる可能性があります。その場合、前の質問の解決策に関係なく、識別子に応じて実装するものを選択するという問題が残ります。巨大なswitchステートメントを使用してさまざまなクラスをインスタンス化したくないので、これを回避する方法はありますか?

ゲームはAndroidプラットフォーム用ですが、将来のIOSポートがある可能性があるため、Java固有の回答は望ましくありませんが、許容できます。

4

3 に答える 3

2

ジェネリッククラスを忘れてください。最初のオプションで示したように、サブクラスを作成する必要があります。あなたの欠点について:

その多くのクラスを管理するのは難しいでしょう

なんで?サブクラスを作成する場合は、次のようにします。

GameObject chair = new Chair();

ジェネリックモードに従うと、次のようになります。

GameObject chair = new GameObject(Type.CHAIR);

両方を作成するのはほとんど同じ努力ですが、最初のものを使用するとはるかに多くの利点があります。違いは、多くの条件付き検証を行わずに2番目のアプローチでさまざまなアクションを処理できないことです。また、コアは既存のオブジェクトと高度に結合されます。つまり、クラスの1つを変更する場合はコアを変更する必要があり、その逆も同様です。最初のオプションを使用すると、次のようなことができます。

selectedObject.makeAction();

保持しているインスタンスに基づいて正しいアクションを呼び出します。一般的なアプローチに従うと、次のようになります。

if(selectedObject.getType() == Type.CHAIR) {
    //do char action. Notice that this ins't even a method provided by GameObject, you will need to get this from another place, since the GameObject is generic.
}     if(selectedObject.getType() == Type.TABLE) {
     //do table action
} if....

家具が作成されるとき、GameObjectの正しいサブクラスは識別子に基づいて何らかの形で作成される必要があります

私はあなたの主張を理解できませんでした。IDに基づいて作成する必要はなく、適切なクラスを作成するだけです。オブジェクトを作成するときは、オブジェクトタイプをすでに知っているので、正しいクラスをインスタンス化する必要があります。

于 2012-10-18T11:08:04.003 に答える
1

私は間違いなく、さまざまな種類の家具のサブクラスを用意することにします。

メニューが識別子を返す代わりに、インスタンス化する必要のあるクラス名を返すメニューを考えるかもしれません(メニューを表示するときに、どのクラスが各エントリを表すかがわかっていると思います)。このようにして、説明している識別子の問題を回避できます。

各ピースで実行できるアクションに関しては、インターフェースを使用できます。

各家具クラスは、可能なアクションに応じて一連のインターフェイスを実装します。

Interface IExaminable {
  public <result> examine();
}

Interface IBuyable {
  public <result> buy();
}

次に、オブジェクトがisntanceof演算子で検査可能かどうかを簡単に確認できます(必要な場合)。

それが役に立てば幸い

于 2012-10-18T11:04:15.437 に答える
1

すべてのifとbutを考慮せずに、問題の完全な設計ソリューションを考え出すのは非常に困難です。

ただし、ゲームの重要な部分の1つは、アイテム(家具、絵画など)と、各アイテムに対して実行できるアクションとの関係です。これは、この関係をモデル化する方法です(compositionを使用):

アクション:ゲームアクションを表すインターフェイス。PerformActionと呼ばれる単一のメソッドが含まれています。

SittingAction:Actionを実装する具象クラス。座るためのゲームアクションを表します。座るアクションを実行するためのコードを定義するperformActionメソッドを実装します。

ExamineAction:Actionを実装する具象クラス。アイテムを調べるためのゲームアクションを表します。検査アクションを実行するためのコードを定義するperformActionメソッドを実装します。

同様に、ゲームで実行できるアクションのタイプごとに1つのアクションを定義できます。

GameItem:ゲーム内のアイテムを表すクラス。アイテム名、幅、幅、深さなど、すべてのアイテムに共通のプロパティと、これらのプロパティのゲッターとセッターが含まれています。GameItem'has-'タイプActionのインスタンス変数と、Actionパラメーターを使用してActionを初期化するコンストラクター。GameItemは、ユーザーがGameItemを操作するときに呼び出すことができるonInteractionというメソッドも定義します。このメソッドは、Actionインスタンス変数でperformActionメソッドを呼び出すことにより、GameItemに関連付けられたアクションを実行するタスクを委任します。したがって、GameItemをインスタンス化するクラスは、GameItemに関連付けられたアクションを表すGameItemコンストラクターに適切なアクションを渡す必要があります。ユーザーがアイテムを操作するときは、onIneractionメソッドを呼び出すだけです。

GameController:ユーザーイベントをリッスンし、操作されたGameItemのonIneractionメソッドを呼び出すクラス。

それでおしまい。清潔でシンプル。どのアイテムに対してどのアクションを実行するかをチェックするためのifelseステートメントは必要ありません。Simpyは、適切なActionインスタンスを使用してすべてのGameItemインスタンスをインスタンス化し、ユーザー入力をリッスンするGameControllerに、操作されたGameItemのonIneractionメソッドを呼び出させます。

于 2012-10-18T17:49:29.623 に答える