ファイルの分割方法が分かりません

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

ファイルの分割方法が分かりません

#1

投稿記事 by sadora3 » 8年前

今までMain.cppに全部書いてきたコードをファイル分割してみたのですが、Bullet.cppでプレイヤーと敵の座標取得が出来ません。
どうすればいいのでしょうか。

言語:C++
OS:Windows10
コンパイラ:VisualStudio2010

コード:

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

PLAYER Player;
ENEMY Enemy[ENEMY_NUM];

int ProcessLoop(){
	if(ProcessMessage() != 0){  return 0;  }
	if(ClearDrawScreen() != 0){ return 0;  }
	return 1;
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int){
	SetOutApplicationLogValidFlag(FALSE);
	ChangeWindowMode(TRUE);
	SetGraphMode(640, 480, 16);
	SetBackgroundColor(0, 0, 0);
	if(DxLib_Init() == -1 || SetDrawScreen(DX_SCREEN_BACK) != 0){   return -1;  }

	Player.Init();
	for(int i = 0; i < ENEMY_NUM; i++){
		Enemy[i].Init(i);
	}

	while(ProcessLoop() && !CheckHitKey(KEY_INPUT_ESCAPE)){
		Player.Update();
		for(int i = 0; i < ENEMY_NUM; i++){
			Enemy[i].Update();
		}

		Player.Draw();
		for(int i = 0; i < ENEMY_NUM; i++){
			Enemy[i].Draw();
		}
		ScreenFlip();
	}
	DxLib_End();
	return  0;
}

コード:

//Main.h
#ifndef _MAIN
#define _MAIN

#include"DxLib.h"

#define ENEMY_NUM (3)

struct VECTOR2{
	float X;
	float Y;
};
#endif

コード:

//Player.cpp
#include"Player.h"

#define PLAYER_MOVE_SPEED (5)

void PLAYER::Init(){
	Pos.X = 320;
	Pos.Y = 400;
}

void PLAYER::Update(){
	if(CheckHitKey(KEY_INPUT_RIGHT)){
		Pos.X += PLAYER_MOVE_SPEED;
	}
	if(CheckHitKey(KEY_INPUT_LEFT)){
		Pos.X -= PLAYER_MOVE_SPEED;
	}
	if(CheckHitKey(KEY_INPUT_UP)){
		Pos.Y -= PLAYER_MOVE_SPEED;
	}
	if(CheckHitKey(KEY_INPUT_DOWN)){
		Pos.Y += PLAYER_MOVE_SPEED;
	}
}

void PLAYER::Draw(){
	DrawCircle((int)Pos.X, (int)Pos.Y, 20, GetColor(0,0,255), TRUE);
}

コード:

//Player.h
#ifndef _PLAYER
#define _PLAYER

#include"Main.h"

class PLAYER{
private:
	VECTOR2 Pos;
public:
	void Init();
	void Update();
	void Draw();

	VECTOR2 GetPos(){	return Pos;	}
};

#endif

コード:

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

ENEMY_BULLET EnemyBullet[ENEMY_NUM];

void ENEMY::Init(int i){
	Number = i;

	//座標の設定
	Pos.X = 150.0f + 170.0f * Number;
	Pos.Y = -50.0f;

	SetShotInterval();	//次に撃つ弾の射撃間隔の設定
	Life = 1000;		//体力の設定
}

void ENEMY::Update(){
	if(Life < 1){	return;	}		//敵が死んでたら入らない
	ShotInterval--;					//射撃までのカウントを減らす

	if(ShotInterval < 0){
		EnemyBullet[Number].Set(Number);
	}

	if(Pos.Y < 50){
		Pos.Y += 1;
	}

	EnemyBullet[Number].Update();

}

void ENEMY::Draw(){
	DrawCircle((int)Pos.X, (int)Pos.Y, 20, GetColor(255,0,0), TRUE);

	for(int i = 0; i < ENEMY_NUM; i++){
		EnemyBullet[i].Draw();
	}
}

コード:

//Enemy.h
#ifndef _ENEMY
#define _ENEMY

#include"Main.h"

class ENEMY{
private:
	VECTOR2 Pos;		//座標
	int Life;			//体力
	int ShotInterval;	//次に撃つ弾の射撃間隔
	int Number;			//番号
public:
	void Init(int i);
	void Update();
	void Draw();

	VECTOR2 GetPos(){	return Pos;	}
	void SetShotInterval(){	ShotInterval = rand() % 200 + 100;	}
};

#endif

コード:

//Bullet.cpp
#include"Bullet.h"
#include<math.h>
#include"Player.h"
#include"Enemy.h"

#define BULLET_SPEED (8)
#define BULLET_3WAY_ROT (25 * 3.14f / 180)

PLAYER Player2;
ENEMY Enemy2[ENEMY_NUM];

void ENEMY_BULLET::Set(int i){
	if(!ShotFlag){
		Number = i;

		ShotFlag = true;

		VECTOR2 PlayerPos = Player2.GetPos();
		VECTOR2 EnemyPos = Enemy2[Number].GetPos();

		float TargetRot = atan2f(PlayerPos.Y - EnemyPos.Y, PlayerPos.X - EnemyPos.X);

		for(int j = 0; j < 3; j++){
			Pos[j] = EnemyPos;
		}

		Vec[0].X = cosf(TargetRot - BULLET_3WAY_ROT) * BULLET_SPEED;
		Vec[1].X = cosf(TargetRot) * BULLET_SPEED;
		Vec[2].X = cosf(TargetRot + BULLET_3WAY_ROT) * BULLET_SPEED;

		Vec[0].Y = sinf(TargetRot - BULLET_3WAY_ROT) * BULLET_SPEED;
		Vec[1].Y = sinf(TargetRot) * BULLET_SPEED;
		Vec[2].Y = sinf(TargetRot + BULLET_3WAY_ROT) * BULLET_SPEED;
	}
}

void ENEMY_BULLET::Update(){
	if(ShotFlag){
		for(int i = 0; i < 3; i++){
			Pos[i].X += Vec[i].X;
			Pos[i].Y += Vec[i].Y;
		}

		if(Pos[0].Y > 480 && Pos[1].Y > 480 && Pos[2].Y > 480){
			ShotFlag = false;
			Enemy2[Number].SetShotInterval();	//次に撃つ弾の射撃間隔の設定
		}
	}
}

void ENEMY_BULLET::Draw(){
	if(ShotFlag){
		for(int i = 0; i < 3; i++){
			DrawCircle((int)Pos[i].X, (int)Pos[i].Y, 7, GetColor(255,255,0), TRUE);
		}
	}
}

コード:

//Bullet.h
#ifndef _BULLET
#define _BULLET

#include"Main.h"

class ENEMY_BULLET{
private:
	bool ShotFlag;		//射撃フラグ
	VECTOR2 Pos[3];		//3Way弾の座標
	VECTOR2 Vec[3];		//3Way弾の移動ベクトル
	int Number;
public:
	void Set(int i);
	void Update();
	void Draw();
};

#endif

アバター
usao
記事: 1887
登録日時: 11年前

Re: ファイルの分割方法が分かりません

#2

投稿記事 by usao » 8年前

複数のソースファイルに分けて書くのがはじめてなのであれば,
いきなり手元のコードを分け方が曖昧なままに分けるのではなく
まずは簡単な小さな例で試してみてはいかがでしょうか.

たとえば,こんな規模のやつとかから.

コード:

//main.cpp
#include "DataValue.h"

int main()
{
  SetDataValue( 5 );
  printf( "%d\n", GetDataValue() );
  return 0;
}

コード:

//DataValue.h
void SetDataValue( int );
int GetDataValue();

コード:

//DataValue.cpp
static int TheDataValue = 0;

void SetDataValue( int NewValue ){  TheDataValue = NewValue;  }
int GetDataValue(){  return TheDataValue;  }

sadora3
記事: 175
登録日時: 11年前

Re: ファイルの分割方法が分かりません

#3

投稿記事 by sadora3 » 8年前

C言語でのファイルの分割はずっと前ですが、出来ていました。なのでそう意味では初めてではないのですが、C++では初めてです。
ですので、usaoさんが提示してくれたソースコードはすぐ分かりました。
Main.cppで宣言したPLAYERクラスのインスタンスと、ENEMYクラスのインスタンスをBullet.cppで使う方法が分かりません。
Main.cppで宣言したのですから、ENEMY_BULLET::Set(int i)をMain.cppにもっていけば上手くいくと思うのですが、そんなことできませんよね・・・。

アバター
usao
記事: 1887
登録日時: 11年前

Re: ファイルの分割方法が分かりません

#4

投稿記事 by usao » 8年前

私の簡素な例と,あなたのコードとの間には ある程度共通点がある と思いますが,いかがでしょうか.


私の:
 TheDataValue が,あるソースファイル( DataValue.cpp ) 内に定義されていて,
別のソースファイル( main.cpp )側から,必要に応じて値の読み書きを行っている.

あなたの:
 PLAYERクラスのインスタンスと、ENEMYクラスのインスタンス が,あるソースファイル( Main.cpp )で定義されていて,
 別のソースファイル( Bullet.cpp )側から,必要に応じて使いたい.


#「ENEMY_BULLET::Set(int i) のケースであれば書き方としてはどういう形が良いのか」といった話はまた別にあるとしても.

sadora3
記事: 175
登録日時: 11年前

Re: ファイルの分割方法が分かりません

#5

投稿記事 by sadora3 » 8年前

おおー出来ました!
関数の引数で渡していけば出来るんですね。ただ、非常にめんどくさいですね・・・。
ありがとうございました!

コード:

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

PLAYER Player;
ENEMY Enemy[ENEMY_NUM];

int ProcessLoop(){
	if(ProcessMessage() != 0){  return 0;  }
	if(ClearDrawScreen() != 0){ return 0;  }
	return 1;
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int){
	SetOutApplicationLogValidFlag(FALSE);
	ChangeWindowMode(TRUE);
	SetGraphMode(640, 480, 16);
	SetBackgroundColor(0, 0, 0);
	if(DxLib_Init() == -1 || SetDrawScreen(DX_SCREEN_BACK) != 0){   return -1;  }

	Player.Init();
	for(int i = 0; i < ENEMY_NUM; i++){
		Enemy[i].Init(i);
	}

	while(ProcessLoop() && !CheckHitKey(KEY_INPUT_ESCAPE)){
		Player.Update();
		for(int i = 0; i < ENEMY_NUM; i++){
			Enemy[i].Update(Player.GetPos(), &Enemy[i]);
		}

		Player.Draw();
		for(int i = 0; i < ENEMY_NUM; i++){
			Enemy[i].Draw();
		}
		ScreenFlip();
	}
	DxLib_End();
	return  0;
}

コード:

//Main.h
#ifndef _MAIN
#define _MAIN

#include"DxLib.h"

#define ENEMY_NUM (3)

struct VECTOR2{
	float X;
	float Y;
};

#endif

コード:

//Player.cpp
#include"Player.h"

#define PLAYER_MOVE_SPEED (5)

void PLAYER::Init(){
	Pos.X = 320;
	Pos.Y = 400;
}

void PLAYER::Update(){
	if(CheckHitKey(KEY_INPUT_RIGHT)){
		Pos.X += PLAYER_MOVE_SPEED;
	}
	if(CheckHitKey(KEY_INPUT_LEFT)){
		Pos.X -= PLAYER_MOVE_SPEED;
	}
	if(CheckHitKey(KEY_INPUT_UP)){
		Pos.Y -= PLAYER_MOVE_SPEED;
	}
	if(CheckHitKey(KEY_INPUT_DOWN)){
		Pos.Y += PLAYER_MOVE_SPEED;
	}
}

void PLAYER::Draw(){
	DrawCircle((int)Pos.X, (int)Pos.Y, 20, GetColor(0,0,255), TRUE);
}

コード:

//Player.h
#ifndef _PLAYER
#define _PLAYER

#include"Main.h"

class PLAYER{
private:
	VECTOR2 Pos;
public:
	void Init();
	void Update();
	void Draw();

	VECTOR2 GetPos(){	return Pos;	}
};

#endif

コード:

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

ENEMY_BULLET EnemyBullet[ENEMY_NUM];

void ENEMY::Init(int i){
	Number = i;

	//座標の設定
	Pos.X = 150.0f + 170.0f * Number;
	Pos.Y = -50.0f;

	SetShotInterval();	//次に撃つ弾の射撃間隔の設定
	Life = 1000;		//体力の設定
}

void ENEMY::Update(VECTOR2 PlayerPos, ENEMY* Enemy){
	if(Life < 1){	return;	}		//敵が死んでたら入らない
	ShotInterval--;					//射撃までのカウントを減らす

	if(ShotInterval < 0){
		EnemyBullet[Number].Set(Number, PlayerPos, Pos);
	}

	if(Pos.Y < 50){
		Pos.Y += 1;
	}

	EnemyBullet[Number].Update(Enemy);

}

void ENEMY::Draw(){
	DrawCircle((int)Pos.X, (int)Pos.Y, 20, GetColor(255,0,0), TRUE);

	for(int i = 0; i < ENEMY_NUM; i++){
		EnemyBullet[i].Draw();
	}
}

コード:

//Enemy.h
#ifndef _ENEMY
#define _ENEMY

#include"Main.h"

class ENEMY{
private:
	VECTOR2 Pos;		//座標
	int Life;			//体力
	int ShotInterval;	//次に撃つ弾の射撃間隔
	int Number;			//番号
public:
	void Init(int i);
	void Update(VECTOR2 PlayerPos, ENEMY* Enemy);
	void Draw();

	VECTOR2 GetPos(){	return Pos;	}
	void SetShotInterval(){	ShotInterval = rand() % 200 + 100;	}
};

#endif

コード:

//Bullet.cpp
#include"Bullet.h"
#include<math.h>

#define BULLET_SPEED (8)
#define BULLET_3WAY_ROT (25 * 3.14f / 180)

void ENEMY_BULLET::Set(int i, VECTOR2 PlayerPos, VECTOR2 EnemyPos){
	if(!ShotFlag){
		Number = i;
		ShotFlag = true;

		float TargetRot = atan2f(PlayerPos.Y - EnemyPos.Y, PlayerPos.X - EnemyPos.X);

		for(int j = 0; j < 3; j++){
			Pos[j] = EnemyPos;
		}

		Vec[0].X = cosf(TargetRot - BULLET_3WAY_ROT) * BULLET_SPEED;
		Vec[1].X = cosf(TargetRot) * BULLET_SPEED;
		Vec[2].X = cosf(TargetRot + BULLET_3WAY_ROT) * BULLET_SPEED;

		Vec[0].Y = sinf(TargetRot - BULLET_3WAY_ROT) * BULLET_SPEED;
		Vec[1].Y = sinf(TargetRot) * BULLET_SPEED;
		Vec[2].Y = sinf(TargetRot + BULLET_3WAY_ROT) * BULLET_SPEED;
	}
}

void ENEMY_BULLET::Update(ENEMY* Enemy){
	if(ShotFlag){
		for(int i = 0; i < 3; i++){
			Pos[i].X += Vec[i].X;
			Pos[i].Y += Vec[i].Y;
		}

		if(Pos[0].Y > 480 && Pos[1].Y > 480 && Pos[2].Y > 480){
			ShotFlag = false;
			Enemy->SetShotInterval();	//次に撃つ弾の射撃間隔の設定
		}
	}
}

void ENEMY_BULLET::Draw(){
	if(ShotFlag){
		for(int i = 0; i < 3; i++){
			DrawCircle((int)Pos[i].X, (int)Pos[i].Y, 7, GetColor(255,255,0), TRUE);
		}
	}
}

コード:

//Bullet.h
#ifndef _BULLET
#define _BULLET

#include"Main.h"
#include"Enemy.h"

class ENEMY_BULLET{
private:
	bool ShotFlag;		//射撃フラグ
	VECTOR2 Pos[3];		//3Way弾の座標
	VECTOR2 Vec[3];		//3Way弾の移動ベクトル
	int Number;
public:
	void Set(int i, VECTOR2 PlayerPos, VECTOR2 EnemyPos);
	void Update(ENEMY* Enemy);
	void Draw();
};

#endif

閉鎖

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