武器クラスへのプレイヤー位置情報の渡し方

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
あまさん
記事: 4
登録日時: 10年前

武器クラスへのプレイヤー位置情報の渡し方

#1

投稿記事 by あまさん » 10年前

こんにちは。
皆さんから意見を聞きたくて、このトピックを立てました。

現在、c++でシューティングゲームを制作しています。
そこで、以下の様なクラスがあります。(簡素にしています)

コード:

class Character
{
public:

	Character(void);
	virtual ~Character(void);

	virtual void update(void) = 0;
	virtual void draw(void);

	//位置アクセサ
	int getX(void);
	int getY(void);
	void setX(int x);
	void setY(int y);
private:
	//左上座標
	int x, y;
};


class Player :
	public Character
{
public:
	Player(void);
	~Player(void);

	void update(void);
	void draw(void);
private:
	Weapon *weapon;
};

コード:

class Weapon
{
public:
	Weapon(void);
	~Weapon(void);

	//弾などの描画、更新関数
	virtual void draw(void) = 0;
	virtual void update(void) = 0;
};


class RapidShotWeapon :
	public Weapon
{
public:
	RapidShotWeapon(void);
	~RapidShotWeapon(void);

	void update(void);
	void draw(void);
};
今現在、上記のWeaponクラス、RapidShotWeaponクラスを作っています。
作成している途中で、RapidShotWeaponクラスのupdate()関数にて、Playerクラスの座標情報を知る必要が出てきました。
そこで、
  • Weaponクラスのupdate()関数の引数で座標を持ってくるようにする
  • RapidShotWeaponクラスのコンストラクタの引数でPlayerクラスのポインタを持ってくるようにする
の2つの方法が自分の中でパッと思いつきましたが、
前者については、他の武器を実装する場合に、Playerクラスの座標情報を知る必要がない場合がすでに考えられているという点であまり好ましくなさそうだと感じています。
後者については、Playerクラスが持つRapidShotWeaponクラスがPlayerクラスを参照できるという点が、これも好ましくなさそうだと感じます。
自分では他に納得できそうな案が思いつかず、困り果てています。

皆さんは、以上のような問題の例ならば、どのような実装を行いますか?

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: 武器クラスへのプレイヤー位置情報の渡し方

#2

投稿記事 by h2so5 » 10年前

updateの引数で渡すのが自然だと思います。Playerクラスの座標が必要でないならば使わなければいいだけなので。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 武器クラスへのプレイヤー位置情報の渡し方

#3

投稿記事 by softya(ソフト屋) » 10年前

コントローラクラスが座標などを中継してはどうしょう。
そうすれば、Weaponクラス側がPlayerクラスの直接参照を必要としなくなります。
コントローラクラスは各クラスの依存ベタベタになりますが、その他のクラスの独立性は高まります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: 武器クラスへのプレイヤー位置情報の渡し方

#4

投稿記事 by usao » 10年前

最も簡単には,
プレイヤーの座標を取得するための関数 を用意すれば良いのではないでしょうか.

あまさん
記事: 4
登録日時: 10年前

Re: 武器クラスへのプレイヤー位置情報の渡し方

#5

投稿記事 by あまさん » 10年前

h2so5 さんが書きました:updateの引数で渡すのが自然だと思います。Playerクラスの座標が必要でないならば使わなければいいだけなので。
なるほど。確かに必要ないならば使わないという考え方もありますね…。
softya(ソフト屋) さんが書きました:コントローラクラスが座標などを中継してはどうしょう。
そうすれば、Weaponクラス側がPlayerクラスの直接参照を必要としなくなります。
コントローラクラスは各クラスの依存ベタベタになりますが、その他のクラスの独立性は高まります。
外部のクラスを使う手はあまり考えていませんでした。
Playerクラスを参照しないけど、情報は取得することができるのは良いですね。
usao さんが書きました:最も簡単には,
プレイヤーの座標を取得するための関数 を用意すれば良いのではないでしょうか.
それはグローバル関数か、softyaさんのように外部クラスを用意するということでしょうか?


色々意見があって参考になります。
しかしやはり、どこか妥協するという感じになるのでしょうか。
これはそもそもクラスの設計が間違いということなんでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: 武器クラスへのプレイヤー位置情報の渡し方

#6

投稿記事 by softya(ソフト屋) » 10年前

何故クラス同士を疎結合にするか、カプセル化は何のためかを常に考えて作れば自然と収まる形に近づくと思います。
疎結合やカプセル化はバグを出さない・メンテナンス性を上げる手段にすぎないのです。何時でも綺麗で完璧な答えは難問です。
試行錯誤は一生続きますよ。失敗もあるし。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: 武器クラスへのプレイヤー位置情報の渡し方

#7

投稿記事 by usao » 10年前

>それはグローバル関数か、softyaさんのように外部クラスを用意するということでしょうか?

どちらでも良いと思います.
ともかくその時点でのプレイヤの位置という情報をどこかからどうにかして引っ張ってきてくれさえすれば.

(>RapidShotWeaponクラスがPlayerクラスを参照
 というのを避けたいということであれば間に何かしらワンクッション挟めば良い
 という意味においては同じ)

あまさん
記事: 4
登録日時: 10年前

Re: 武器クラスへのプレイヤー位置情報の渡し方

#8

投稿記事 by あまさん » 10年前

softya(ソフト屋) さんが書きました:何故クラス同士を疎結合にするか、カプセル化は何のためかを常に考えて作れば自然と収まる形に近づくと思います。
疎結合やカプセル化はバグを出さない・メンテナンス性を上げる手段にすぎないのです。何時でも綺麗で完璧な答えは難問です。
試行錯誤は一生続きますよ。失敗もあるし。
言われてみればそうですね…。なんでも上手くいくように作ろうと考えてしまって答えがでなくては良くないですし。
usao さんが書きました:>それはグローバル関数か、softyaさんのように外部クラスを用意するということでしょうか?

どちらでも良いと思います.
ともかくその時点でのプレイヤの位置という情報をどこかからどうにかして引っ張ってきてくれさえすれば.

(>RapidShotWeaponクラスがPlayerクラスを参照
 というのを避けたいということであれば間に何かしらワンクッション挟めば良い
 という意味においては同じ)
そうですね。直接参照を持たないという点ではどれも大差ないですね

皆さん、様々な意見ありがとうございました。
完璧にするには難しいことがよく分かりました。
それでも、それなりに納得がいきそうな案ができそうです。なのでこのトピックは解決としますね。

ISLe()

Re: 武器クラスへのプレイヤー位置情報の渡し方

#9

投稿記事 by ISLe() » 10年前

解決しているようですが、わたしがふだん使っている手法を書いておきます。
この掲示板で過去に同じ話題で書いたこともあるのですが。

RapidShotWeaponにはあらかじめゲームコンテキストというオブジェクトへのポインタを渡しておきます。
ゲームコンテキストは、直接関連を持たないオブジェクトの情報が必要な処理へのインターフェースです。

例えばゲームコンテキストへのポインタがpContextだとして、
pContext->GetShotTarget()->GetPosition()
というふうにショットが向かう先の座標を取得します。

GetShotTargetでショットが向かう先を対象にしたインターフェースを取得します。
直接Playerクラスとはしないで抽象化し、インターフェースを実装する先で柔軟に対応できるようにします。
インターフェース(へのポインタ)を挟むことで、直接の関係を持たないソースファイルには定義を非公開とすることができます。

コンテキストからどのようなインターフェースを取得できるようにすると良いかは設計によりますが、インターフェースを取得する際に引数も使えますし、けっこう少ない数にまとめることができるので複雑にはなりません。
インターフェースからさらにインターフェースを取得するような構造にすればソースファイルの依存関係をさらに絞り込めます。
あらかじめ必要なインターフェースを全部用意できれば良いのですが、なかなか難しいことなのですよね。

あまさん
記事: 4
登録日時: 10年前

Re: 武器クラスへのプレイヤー位置情報の渡し方

#10

投稿記事 by あまさん » 10年前

ISLe() さんが書きました:解決しているようですが、わたしがふだん使っている手法を書いておきます。
この掲示板で過去に同じ話題で書いたこともあるのですが。

RapidShotWeaponにはあらかじめゲームコンテキストというオブジェクトへのポインタを渡しておきます。
ゲームコンテキストは、直接関連を持たないオブジェクトの情報が必要な処理へのインターフェースです。

例えばゲームコンテキストへのポインタがpContextだとして、
pContext->GetShotTarget()->GetPosition()
というふうにショットが向かう先の座標を取得します。

GetShotTargetでショットが向かう先を対象にしたインターフェースを取得します。
直接Playerクラスとはしないで抽象化し、インターフェースを実装する先で柔軟に対応できるようにします。
インターフェース(へのポインタ)を挟むことで、直接の関係を持たないソースファイルには定義を非公開とすることができます。

コンテキストからどのようなインターフェースを取得できるようにすると良いかは設計によりますが、インターフェースを取得する際に引数も使えますし、けっこう少ない数にまとめることができるので複雑にはなりません。
インターフェースからさらにインターフェースを取得するような構造にすればソースファイルの依存関係をさらに絞り込めます。
あらかじめ必要なインターフェースを全部用意できれば良いのですが、なかなか難しいことなのですよね。
閉じたのにわざわざ有り難うございます。
結局はそれと似たような実装の仕方をしました。
実装してみると以外にもスッキリした感じになり、此処で意見を聞いて良かったと思います。
構造については経験でうまいことしていく必要がありそうだなと、実装しながら感じました。難しいですね・・・。

ISLe()

Re: 武器クラスへのプレイヤー位置情報の渡し方

#11

投稿記事 by ISLe() » 10年前

ゲーム内オブジェクトの基底クラスにコンテキストをリレーする仕組みを隠し、どこでもGetContext()できるようにするとさらに便利です。
#プラットフォームがコンテキストを持つような場合でも内包できるのでプラットフォームに依存することはありません。

常にファクトリーメソッド経由でインスタンスを構築することになりますが、リストに登録したりを同時に処理できる(隠せる)ので、むしろメリットのほうが大きいと思います。

ふつうにシングルトンとか使える環境ならそこまでしなくてもいいかもしれませんが、あらかじめそうしておくことで移植性は高くなります。

閉鎖

“C言語何でも質問掲示板” へ戻る