敵クラスから自機クラスの情報を得たい

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

敵クラスから自機クラスの情報を得たい

#1

投稿記事 by arita » 4ヶ月前

こんにちは。
c++でゲームを作ろうとしています。そこで敵クラスから自機クラスの関数を呼ぶ必要が出てきました。
少し前の同じようなスレッドを読み、そのかたの参考にしていたサイト()。そこで敵クラスから自機クラスの関数を呼ぶ必要が出てきました。
少し前の同じようなスレッドを読み、そのかたの参考にしていたサイト(https://bituse.info/game/shot/13)も見てみましたがうまくいきません。
そこで改めて同じような質問をさせて頂きます、ご容赦ください。
具体的な内容に入ります。
まず環境を述べます。OSはWindows、コンパイラはVisual Studio、ライブラリはOpensiv3dです。
今までcを使っていて最近c++を使い始めました。基本的なクラスの概念が理解できる程度です。また、ポインタはアドレスを持つことを知っている程度であまり使えません。c++の設計を今回の簡単なゲームを通して学ぼうと思っています。
設計はGameクラスの中にPlayerクラスのインスタンスplayer,Enemyクラスのインスタンスの配列enemyです。
またGameクラスはOpensiv3dのシーンマネージャーという機能から呼ばれるため、GameクラスがMyAppを継承していたり、独自のコンストラクタがありますが内容はGameクラス自体で完結しているので影響はないと思いますが念のため書かせていただいてます。また、Arrayは動的配列です。
以下コードです。関係がないところは割愛しています。

Game.hpp

コード:

#include"Player.hpp"
#include"Enemy.hpp"

class Game: public MyApp::Scene{

private:

  Player player;
  Array<Enemy*> enemy;

public:

  Game(const InitData& init);
  void update() override;
  void draw() const override;

}

Game.cpp

コード:

#include"Game.hpp"

Game::Game(const InitData& init)
	: IScene(init){
	
	}

void Game::update()
{
		player.update();
		for (size_t i = 0; i < enemy.size(); i++) {
			enemy[i]->update();
		}
}

void Game::draw(){
}

Player.hpp

コード:

class Player{
private:

  int _x;

public:
 void update();
  void draw() const;
}
Player.cpp

コード:

#include"Player.hpp"

void Player::update(){
}

void Player::draw()const{
}

Enemy.hpp

コード:

class Enemy{
private:

  int _x;

public:
 void update();
  void draw() const;
  
  void shot();
}
Enemy.cpp

コード:

#include"Enemy.hpp"

void Enemy::update(){
}

void Enemy::draw()const{
}

void Enemy::shot(){
//ここでplayerの情報を扱いたいです。
}
PlayerやEnemyのメンバー変数は10個ほど扱う予定です。

よろしくお願いいたします。

アバター
あたっしゅ
記事: 439
登録日時: 10年前
住所: 東京23区
連絡を取る:

Re: 敵クラスから自機クラスの情報を得たい

#2

投稿記事 by あたっしゅ » 4ヶ月前

Windows 10 Pro 64bit 、Visual Studio2019 Community に OpenSiv3D v0.4.3 をインストールしましたが、

’MyApp’ 識別子がクラス名でも名前識別子でもありません。

と出て、ビルドできませんでした。
VTuber:
東上☆海美☆(とうじょう・うみみ)
http://atassyu.rosx.net/vtuber/index.html
レスがついていないものを優先して、レスすみみ。時々、見当外れなレスしみみ。

中の人:
手提鞄あたっしゅ、[MrAtassyu]
http://ameblo.jp/mratassyu/
Pixiv: 666303
手提鞄屋魚有店(てさげかばんやうおありてん)

arita
記事: 6
登録日時: 4ヶ月前

Re: 敵クラスから自機クラスの情報を得たい

#3

投稿記事 by arita » 4ヶ月前

あたっしゅさん、返信ありがとうございます。
siv3dのインストールまでしていただきお手数をおかけします。
MyAppの部分は割愛したところに書かれていました。また、;が抜けているところなどが見つかったため改めて単体で実行できるものを再提示させていただきます、失礼しました。

設計としてはMain.cppのMainの関数から始まり、while文のSystem::Updateがsiv3d独自のシーンマネージャーを毎ループ呼び、登録されたGameクラスが更新していく形になっています。また、シーンマネージャーを使うために共通の処理を書いたCommon.hppを各々のクラスでインクルードしています。


Main.cpp

コード:

#include"Common.hpp"
#include"Game.hpp"

void Main() {
	// シーンを設定
	MyApp manager;
	manager
		.add<Game>(State::Game);

		while (System::Update()) {

			if (!manager.update())
			{
				break;
			}
		}


}

Common.hpp

コード:

#pragma once
# include <Siv3D.hpp> // OpenSiv3D v0.4.2

// シーンの名前
enum class State
{
	Game
};

// ゲームデータ
struct GameData
{
	
};

// シーン管理クラス
using MyApp = SceneManager<State, GameData>;




Gameクラス
Game.hpp

コード:

#pragma once
#include"Common.hpp"
#include"Player.hpp"
#include"Enemy.hpp"

class Game : public MyApp::Scene {

private:

	Player player;
	Array<Enemy*> enemy;

public:

	Game(const InitData& init);
	void update() override;
	void draw() const override;

};


Gameクラス
Game.cpp

コード:

#include "Game.hpp"

Game::Game(const InitData& init)
	: IScene(init) {

}

void Game::update()
{
	player.update();
	for (size_t i = 0; i < enemy.size(); i++) {
		enemy[i]->update();
	}
}

void Game::draw()const {
}
Playerクラス
player.hpp

コード:

#include"Common.hpp"
class Player {
private:

	int _x;

public:
	void update();
	void draw() const;
};



Playerクラス
player.cpp

コード:

#include "Player.hpp"


void Player::update() {
	Print << U"ok";
}

void Player::draw()const {
}

Enemyクラス
Enemy.hpp

コード:

#include"Common.hpp"

class Enemy {
private:

	int _x;

public:
	void update();
	void draw() const;

	void shot();
};

Enemyクラス
Enemy.cpp

コード:

#include "Enemy.hpp"

void Enemy::update() {
}

void Enemy::draw()const {
}

void Enemy::shot() {
	//ここでplayerの情報を扱いたいです。
}

よろしくお願いします。

アバター
usao
記事: 1635
登録日時: 8年前

Re: 敵クラスから自機クラスの情報を得たい

#4

投稿記事 by usao » 4ヶ月前

Enemy::Shot()メソッドで情報が欲しいならば,最も単純な話としては,このメソッドの引数に情報を取ればよいだけではないでしょうか?
そうしない理由があるのであれば,質問に際して明言すべきでしょう.

GameがEnemyを保有しているということから,Enemyの公開メソッドはGameが呼ぶことになるのだと思われ,
また,GameはPlayerをも保有している存在なのであるから,
GameからEnemyの各メソッドに引数としてPlayerに関する必要な情報を渡すことは簡単に実現できるのではないかと思うのですが.

アバター
あたっしゅ
記事: 439
登録日時: 10年前
住所: 東京23区
連絡を取る:

Re: 敵クラスから自機クラスの情報を得たい

#5

投稿記事 by あたっしゅ » 4ヶ月前

 とりあえず、ビルドは出来ました。
 以下は、ネット検索してみつかったもの

https://qiita.com/tyanmahou/items/595ff692573f4f0b2490
Siv3D から OpenSiv3D に乗り換えよう - Qiita(ja)

https://shizenkarasuzon.hatenablog.com/ ... /28/211339
【C++】Visual Studio 2019 に OpenSiv3D を導入する - とある科学の備忘録(ja)

https://siv3d.github.io/ja-jp/community/community/
コミュニティ - Siv3D(ja)

https://siv3d.jp/bbs/patio.cgi
Siv3D ユーザー助け合い所(ja)

https://siv3d.jp/bbs/patio.cgi?read=474&ukey=0
STLの描画(ja)

https://qiita.com/Reputeless/items/5bc7 ... 9%E3%82%8B
Siv3D の 3D プログラムテクニック集 - Qiita(ja)

https://qiita.com/yagiri000/items/d07afd84934d5c62bc7c
C++Siv3D 入門講座 Vol.00 はじめに - Qiita(ja)

https://siv3d.jp/bbs/patio.cgi?read=396
OpenSiv3d 専用 BBS(ja)

 で、渋3D の機能を使っていないプログラムだが、

コード:

class TXY {
protected:
	float _x;
	float _y;

public:
			TXY(): _x( 0.0f ), _y( 0.0f ) {}
			TXY(const float xx, const float yy ): _x(xx), _y(yy) {}
	float	getR2(TXY& a) {
				const float xx = a._x - _x;
				const float yy = a._y - _y;

				return xx * xx + yy * yy;
			}
};


class Player: public TXY {
public:
	void update();
	void draw() const;
};


class Enemy: public TXY {
public:
	void update();
	void draw() const;

	void shot();
};


class Game : public MyApp::Scene {
private:
	Player player;
	Array<Enemy*> enemy;

public:
	Game(const InitData& init);
	void update() override;
	void draw() const override;
};
//
// 以下、どっかで...
//
const int R2=1*1;

for (size_t i = 0; i < enemy.size(); i++) {
    if( player.getR2(enemy[ i ])<R2 ) {
        // player と enemy[ i ] の衝突処理
    }
}   
上記のままではコンパイルできませんが、こんな感じで、どうでしょう。
VTuber:
東上☆海美☆(とうじょう・うみみ)
http://atassyu.rosx.net/vtuber/index.html
レスがついていないものを優先して、レスすみみ。時々、見当外れなレスしみみ。

中の人:
手提鞄あたっしゅ、[MrAtassyu]
http://ameblo.jp/mratassyu/
Pixiv: 666303
手提鞄屋魚有店(てさげかばんやうおありてん)

arita
記事: 6
登録日時: 4ヶ月前

Re: 敵クラスから自機クラスの情報を得たい

#6

投稿記事 by arita » 4ヶ月前

usaoさん、あたっしゅさん。返信ありがとうございます。

usaoさんの仰った引数に情報を渡す方法の場合、今後playerの座標以外も渡す必要がでた場合もすべて引数に渡していく感じなのでしょうか?C++による設計方法をあまり見たことないので知識がありません。ぜひご教授をお願いします。

あたっしゅさん、多くのサイトの提示ありがとうございます。最後の衝突処理の部分ですがGameクラスの中のメゾットとして入れていくのでしょうか。また、入れる場合Gameクラスの中のオブジェクト同士の判定や処理はすべてGameクラスのメンバとして扱っていくのでしょうか、それとも別のファイルか何かに分けるのセオリーでしょうか?ご教授していただけると幸いです。

アバター
usao
記事: 1635
登録日時: 8年前

Re: 敵クラスから自機クラスの情報を得たい

#7

投稿記事 by usao » 4ヶ月前

arita さんが書きました:
4ヶ月前
usaoさんの仰った引数に情報を渡す方法の場合、今後playerの座標以外も渡す必要がでた場合もすべて引数に渡していく感じなのでしょうか?C++による設計方法をあまり見たことないので知識がありません。ぜひご教授をお願いします。
単純に引数で渡すことで話が済むなら問題はないのでは.
(それでは何かしらの問題があるならば別の手を考える必要があるが)

引数の個数が増えたときに「たくさん並んでて嫌」とかならstructとか何かである程度の塊の形で渡してやれば
引数の個数という見た目はとりあえずどうとでもなるし,
playerに関する複数の情報が必要とかなら Player 型(の参照とか)をまるっと渡すとかでも良いかもしれないし.

arita
記事: 6
登録日時: 4ヶ月前

Re: 敵クラスから自機クラスの情報を得たい

#8

投稿記事 by arita » 4ヶ月前

usaoさん、回答ありがとうございます。
引数に構造体を使用できるのを知りませんでした。これでプログラムが先に進めそうです。ありがとうございました。

アバター
usao
記事: 1635
登録日時: 8年前

Re: 敵クラスから自機クラスの情報を得たい

#9

投稿記事 by usao » 4ヶ月前

Enemy::Shot()とかEnemy::Update()とかが,実際にどれだけの情報を必要とすることになるのかがまだ定まっていないような状態なら,
(綺麗じゃないかもしれないけど)例えば,とりあえずこんな形にでもしておくとか.

コード:

//Player
class Player
{
public:
  //現在の位置を返す
  int GetPosition() const {  return m_Position;  }
private:
  int m_Position;  //位置
};

//ゲームデータへのアクセス手段
class IGameContext
{
public:  //必要な情報の取得手段を提供

  //Playerに関する情報の取得手段を返す
  virtual const Player &GetPlayer() const = 0;
  
  //※例えば,
  //現在のスコアだとか経過時間だとかを参照して動きを変えるようなEnemyを実装したくなったとしたら,
  //以下のようなメソッドをここに増やせばいい
  
  //現在のゲームスコアを返す
  virtual unsigned int GetGameScore() const = 0:
  //現在のステージ開始時刻からの経過時間を返す
  virtual unsigned int GetElapsedTimeStepFromStageStart() const = 0;
};

//Enemy::Update()は,引数に与えらえたオブジェクトを介して必要な情報を取得する
void Enemy::Update( const IGameContext &IGC )
{
  //Playerの現在の位置を取得
  int CurrentPlayerPosition = IGC.GetPlayer().GetPosition();

  //...
}

arita
記事: 6
登録日時: 4ヶ月前

Re: 敵クラスから自機クラスの情報を得たい

#10

投稿記事 by arita » 4ヶ月前

usaoさん、返信ありがとうございます。
書いて頂いたコードでゲームの根幹がきれいにまとまりそうです。自分一人では確実にここまで至れませんでした、ありがとうございます。

アバター
あたっしゅ
記事: 439
登録日時: 10年前
住所: 東京23区
連絡を取る:

Re: 敵クラスから自機クラスの情報を得たい

#11

投稿記事 by あたっしゅ » 4ヶ月前

とりあえず、動くコードを。参考:OpenSiv3D プロジェクトのテンプレート

// Common.h

コード:

#pragma once
// Common.h
//
//
#include <Siv3D.hpp> // OpenSiv3D v0.4.2


// シーンの名前
enum class State
{
	Game
};

// ゲームデータ
struct GameData
{

};

// シーン管理クラス
using MyApp = SceneManager<State, GameData>;

//
class TXY {
public:
	Vec2	m_xy;

			TXY() { m_xy = RandomVec2(Scene::Rect() ); }
			TXY(const float xx, const float yy ): m_xy(xx, yy) {}
	double	getR2(TXY& a) {
				const double xx = a.m_xy.x - m_xy.x;
				const double yy = a.m_xy.y - m_xy.y;

				return xx * xx + yy * yy;
			}
};


// end.
// Player.h

コード:

#pragma once
// Player.h
//
//
#include <Siv3D.hpp> // OpenSiv3D v0.4.3

#include "Common.h"
//
//
//
class Player: public TXY {
public:
	void update();
	void draw() const;
};


// end.
// Player.cpp

コード:

// Player.cpp
//
//
#include <Siv3D.hpp> // OpenSiv3D v0.4.3

#include "Common.h"
#include "Player.h"

void Player::update() {
	m_xy = Cursor::Pos();
}

void Player::draw()const {
}


// end.
// Game,h

コード:

#pragma once
// Game.h
//
//
#include <Siv3D.hpp> // OpenSiv3D v0.4.3

#include "Common.h"
#include "Player.h"
#include "Enemy.h"
//
//
//
class Game : public MyApp::Scene {

private:
	Texture			cat;
	Player			player;

public:
	Array<Enemy*>	enemy;
					Game(const InitData& init);
	void			update() override;
	void			draw() const override;

};


// end.
// Game.cpp

コード:

#include "Game.h"
// Game.cpp
//
//
Game::Game(const InitData& init): IScene(init) 
{
	// 猫のテクスチャを用意
	cat = Texture(Emoji(U"🐛"));
	enemy << new Enemy();
	enemy << new Enemy();
	enemy << new Enemy();
	enemy << new Enemy();
	enemy << new Enemy();
}

void Game::update()
{
	player.update();
	for (size_t i = 0; i < enemy.size(); i++) {
		enemy[ i ]->update();

		const double R2 = 20.0 * 20.0;
		if (player.getR2( *enemy[ i ] ) < R2 ) {
			System::Exit();
		}
	}
}

void Game::draw() const {
	//Print << enemy.size();
	for (size_t i = 0; i < enemy.size(); i++) {
		// 大きさをアニメーションさせて猫を表示する
		cat.resized(100 + Periodic::Sine0_1(1s) * 20).drawAt(enemy[ i ]->m_xy);
	}
}


// end.
// Enemy.h

コード:

#pragma once
// Enemy.h
//
//
#include <Siv3D.hpp> // OpenSiv3D v0.4.3

#include "Common.h"
//
//
//
class Enemy: public TXY {
public:
	void update();
	void draw() const;

	void shot();
};


// end.
// Enemy.cpp

コード:

// Enemy.cpp
//
//
#include"Enemy.h"


//
//
//
// 猫のテクスチャを用意
//const Texture cat(Emoji(U"🐈"));


void Enemy::update() {
}

void Enemy::draw() const {
}

void Enemy::shot() {
	//ここでplayerの情報を扱いたいです。
}


// end.
// Main.cpp

コード:

// Main.cpp
//
// https://dixq.net/forum/viewtopic.php?f=3&t=21022&sid=3967390df6b7a989c5de300db2c021df
//
#include <Siv3D.hpp> // OpenSiv3D v0.4.3

#include "Common.h"
#include "Game.h"
//
//
//
void Main()
{
	// シーンを設定
	MyApp manager;

	manager.add<Game>(State::Game);

	// 背景を水色にする
	Scene::SetBackground(ColorF(0.8, 0.9, 1.0));

	// 大きさ 60 のフォントを用意
	const Font font(60);

	// 猫のテクスチャを用意
	const Texture cat(Emoji(U"🐈"));

	// 猫の座標
	Vec2 catPos(640, 450);

	while (System::Update())
	{
		// テキストを画面の中心に描く
		font(U"Hello, Siv3D!🐣").drawAt(Scene::Center(), Palette::Black);

		// 大きさをアニメーションさせて猫を表示する
		cat.resized(100 + Periodic::Sine0_1(1s) * 20).drawAt(catPos);

		// マウスカーソルに追従する半透明の赤い円を描く
		Circle(Cursor::Pos(), 20).draw(ColorF(1, 0, 0, 0.5));

		// [A] キーが押されたら
		if (KeyA.down())
		{
			// Hello とデバッグ表示する
			Print << U"Hello!";
		}

		// ボタンが押されたら
		if (SimpleGUI::Button(U"Move the cat", Vec2(600, 20)))
		{
			// 猫の座標を画面内のランダムな位置に移動する
			catPos = RandomVec2(Scene::Rect());
		}

		// 現在のシーンを実行
		if (!manager.update())
		{
			break;
		}
	}
}


//
// = アドバイス =
// Debug ビルドではプログラムの最適化がオフになります。
// 実行速度が遅いと感じた場合は Release ビルドを試しましょう。
// アプリをリリースするときにも、Release ビルドにするのを忘れないように!
//
// 思ったように動作しない場合は「デバッグの開始」でプログラムを実行すると、
// 出力ウィンドウに詳細なログが表示されるので、エラーの原因を見つけやすくなります。
//
// = お役立ちリンク =
//
// OpenSiv3D リファレンス
// https://siv3d.github.io/ja-jp/
//
// チュートリアル
// https://siv3d.github.io/ja-jp/tutorial/basic/
//
// よくある間違い
// https://siv3d.github.io/ja-jp/articles/mistakes/
//
// サポートについて
// https://siv3d.github.io/ja-jp/support/support/
//
// Siv3D ユーザコミュニティ Slack への参加
// https://siv3d.github.io/ja-jp/community/community/
//
// 新機能の提案やバグの報告
// https://github.com/Siv3D/OpenSiv3D/issues
//
// end.
マウスカーソルを、虫の中央付近に合わせると、プログラムを終了します。
VTuber:
東上☆海美☆(とうじょう・うみみ)
http://atassyu.rosx.net/vtuber/index.html
レスがついていないものを優先して、レスすみみ。時々、見当外れなレスしみみ。

中の人:
手提鞄あたっしゅ、[MrAtassyu]
http://ameblo.jp/mratassyu/
Pixiv: 666303
手提鞄屋魚有店(てさげかばんやうおありてん)

arita
記事: 6
登録日時: 4ヶ月前

Re: 敵クラスから自機クラスの情報を得たい

#12

投稿記事 by arita » 4ヶ月前

あたっしゅさん、返信ありがとうございます。
送って頂いたコードを動かしたところ無事(?)怪しいプログラムが動きました。siv3dをここまで使ってくださりありがとうございます。

返信

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