ゲームプログラミング:CSVで敵を出現させたい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
roxas11000510113

ゲームプログラミング:CSVで敵を出現させたい

#1

投稿記事 by roxas11000510113 » 9年前

こんにちは、私、現在横スクロールアクションを作ろうとしている大学2年生のものです。
すこし困ったことがあるのでお邪魔させていただきます。現在CSV(エクセル)を使って敵を出現させようとしているのですが、なかなか上手くいきません。あるページを参考にしたのですが、できません。原因はおそらくif(c==EOF)のところだと思うのですが、解決策が見つかりません。一緒に考えてはいただけないかと思ってお邪魔させていただきました。?また、それともほかのところが間違っているのでしょうか?
もしそうなら指摘していただければ幸いです。現段階ではコンパイルが成功したのにエラーが出てしまいます。「~.exeは動作を停止しました。」というものです。その後いろいろ試したのですが、敵が出てこなかったり、うんざりしています。他にも、おすすめのやり方を紹介していただけると嬉しいです。
よろしくお願いします

あと一つ申し訳ないのですが、ソースののせ方がわかりません。どうすればよいでしょうか?

ミスティ

Re: ゲームプログラミング:CSVで敵を出現させたい

#2

投稿記事 by ミスティ » 9年前

ファイル添付はユーザー登録すると可能になりますよ。
ソースコードだけならcodeタグで囲んで張り付けてください。

roxas11000510113

Re: ゲームプログラミング:CSVで敵を出現させたい

#3

投稿記事 by roxas11000510113 » 9年前

>>ミスティさん

返信ありがとうございました。よく見たらページに書いてありましたね。よく読んでいませんでした。申し訳ありません

コード:

//main文
#include"Player.h"
#include"BackGround.h"
#include"Enemy.h"
#include"Box.h"
#pragma warning(disable:4996)

int WINAPI WinMain(HINSTANCE hinstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
	ChangeWindowMode(true);	

	if(DxLib_Init()==-1)
	{
		return -1;
	}

	SetTransColor(0,255,255);	

	SetDrawScreen(DX_SCREEN_BACK);		

	Player *hero=new Player(1,-4,7);	

	Box *asiba[3];

	for(int i=0;i<3;i++)
	{
		asiba[0]=new Box(30,230);
		asiba[1]=new Box(140,180);
		asiba[2]=new Box(299,200);
	}

	BackGround *haikei[2];	

	for(int i=0;i<2;i++)
	{
		haikei[0]=new BackGround(0,0);
		haikei[1]=new BackGround(630,0);		
	}
	

	FILE* fp;//
	data enemydata[3];//構造体
	char buf[100];//バッファ
	int c=0;
	int col=1;//列
	int row=0;//行

	//バッファ初期化
	memset(buf,0,sizeof(buf));

	fp = fopen("EnemyData.csv","r");//ファイルを開く

	while(fgetc(fp)!='\n');//ヘッダーを読み飛ばす。
	
	while(1)
	{
		while(1)
		{
			if(c==EOF) break;//ファイルの終わりに来たらループを抜ける。

			c=fgetc(fp);//fpに入れたファイルの文字を一文字ずつ読み込む		

			if(c!=','&&c!='\n') strcat(buf,(const char*)&c);//カンマ化改行でなければ文字としてつなげる

			else break;//カンマが抜けたらループを抜ける。
		}

		switch(col)
		{
		//セルに書かれた文字をatoi()で数値に変更。
		case 1:enemydata[row].x=atoi(buf);break;
		case 2:enemydata[row].y=atoi(buf);break;
		case 3:enemydata[row].speed=atoi(buf);break;
		case 4:enemydata[row].CMAX=atoi(buf);break;

		}
		memset(buf,0,sizeof(buf));//バッファ初期化
		col++;//列数を足す

		if(c=='\n')//読み込んだ文字が改行なら
		{
			col=1;//列数を1に戻す
			row++;//行を増やす。=CSVの下の行に移動
		}	

	}	
	Enemy *monster[3];

	for(int i=0;i<3;i++)//オブジェクト生成
	{
		monster[i]=new Enemy(enemydata[i].x,enemydata[i].y,enemydata[i].speed,enemydata[i].CMAX);
	}
	

	/*for(int i=0;i<3;i++)
	{
		monster[0]=new Enemy(200,360,0.5,90);
		monster[1]=new Enemy(400,360,0.5,90);
		monster[2]=new Enemy(600,360,0.5,90);
	}
	*/

	while(true)
	{
		ClearDrawScreen();

		//背景の描画
		for(int i=0;i<2;i++)
		{
			haikei[i]->BackDraw();
			haikei[i]->BackScroll(hero->GetX());			
		}
		//-----------------------	


		bool a[2];
		//適当な配列を二個生成
		/*for(int i=0;i<2;i++)
		{
		a[i] = haikei[0]->GetScrollFlag();//両方にScrollFlagを取った関数を代入		
		}
		*/
	
		//以下、敵に関する情報

		for(int i=0;i<3;i++)
		{
			monster[i]->EnemyScroll(a,(int)hero->GetX());
			monster[i]->EnemyDraw();
			monster[i]->DamageCheck((int)hero->GetX(),(int)hero->GetY(),(int)hero->GetW(),(int)hero->GetH(),hero->GetAFlag());
			monster[i]->EnemyMove();

		}

		/*
		for(int i=3;i<7;i++)
		{
		monster[i]->EnemyScroll(a,(int)hero->GetX());
		monster[i]->EnemyDraw();
		monster[i]->DamageCheck((int)hero->GetX(),(int)hero->GetY(),(int)hero->GetW(),(int)hero->GetH(),hero->GetAFlag());
		}
		*/

		//ここから下はプレイヤーの動き
		hero->PlayerMove(a);
		hero->PlayerAtack();
		hero->Doge();		
		hero->PlayerJump();
		hero->PreChakchi();

		for(int i=0;i<3;i++)
		{
			hero->PlayerChakchi(asiba[i]->GetX(),asiba[i]->GetY(),asiba[i]->GetW(),asiba[i]->GetH());
		}

		for(int i=0;i<3;i++)
		{
			hero->PDamageCheck(monster[i]->GetEX(),monster[i]->GetEY(),monster[i]->GetEW(),monster[i]->GetEH(),monster[i]->GetFlag());
		}
		hero->PlayerDraw();


		for(int i=0;i<3;i++)
		{			
			asiba[i]->BoxDraw();
		}

		//DrawFormatString(500,450,-1,"敵データ:%d",enemydata[2].x);

		ScreenFlip();

		if(CheckHitKey(KEY_INPUT_ESCAPE) || ProcessMessage()==-1) break;

	}

	delete hero;

	for(int i=0;i<3;i++)
	{
		delete asiba[i];
	}

	for(int i=0;i<2;i++)
	{
		delete haikei[i];	
	}


	for (int i=0;i<3;i++)
	{
		delete monster[i];
	}



	DxLib_End();

	return 0;
}

コード:

//Enemy.h
#pragma once
#ifndef H_ENEMY
#define H_ENEMY

#include"Struct.h"
#include"Player.h"
class Enemy
	:public Player
{
private:
	data rect;
	bool Flag;
	int SX;	
	int MoveCount;//XまたはY座標にどれだけ動いたかを数える
	float MoveWay;
	
public:
	Enemy(float x,float y,float speed,int CMAX);
	~Enemy();
	void EnemyScroll(bool SF,int pX);
	void EnemyMove();
	void EnemyDraw();
	void DamageCheck(int pX,int pY,int pW,int pH,bool paF);
	void SetFlag(bool SF);
	bool GetFlag();
	int GetEX();
	int GetEY();
	int GetEW();
	int GetEH();
	int GetHP();
	
	
};


typedef enum tag_Move{Nomove,Pattern1,Pattern2,Pattern3}Move;

#endif

コード:

#include"Enemy.h"

Enemy::Enemy(float x,float y,float speed,int CMAX):Player(this->rect.x,this->rect.y,this->HP)
{
	this->rect.x=x;
	this->rect.y=y;
	this->rect.Graph=LoadGraph("img/wall.png");
	this->Flag=true;
	GetGraphSize(this->rect.Graph,&this->rect.w,&this->rect.h);
	this->MoveWay=0;
	this->MoveCount=0;
	this->rect.speed=speed;
	this->rect.CMAX=CMAX;
	this->HP=HP;
	
}
Enemy::~Enemy()
{}

void Enemy::EnemyScroll(bool SF,int pX)
{
	this->PadINPUT=GetJoypadInputState(DX_INPUT_KEY_PAD1);
	if(SF==true&&this->PadINPUT&PAD_INPUT_RIGHT&&pX>300)
	{
		this->rect.x-=2;	

		if(CheckHitKey(KEY_INPUT_Z))
		{
			this->rect.x-=3;
		}		
	}
}

void Enemy::EnemyMove()
{	
	if(this->MoveWay==0)
	{
		this->rect.x-=this->rect.speed;
		this->MoveCount++;
		
		if(this->MoveCount>=this->rect.CMAX)
		{
			this->MoveCount=0;
			this->MoveWay=1;
		}
	}
	if(this->MoveWay==1)
	{
		this->rect.x+=this->rect.speed;
			this->MoveCount++;

			if(this->MoveCount>=this->rect.CMAX)
			{
				this->MoveCount=0;
				this->MoveWay=0;
			}		
		}
	
}

void Enemy::DamageCheck(int pX,int pY,int pW,int pH,bool paF)
{	
	if(this->Flag==true)
	{
		if(paF==true)
		{
			if(((pX>=this->rect.x&&pX<=this->rect.x+this->rect.w)||
				(this->rect.x>=pX&&this->rect.x<=pX+pW))&&
				((pY>=this->rect.y&&pY<=this->rect.y+this->rect.h)||
				(this->rect.y>=pY&&this->rect.y<=pY+pH)))
			{
				this->HP-=1;

				if(this->HP<=0)
				{
					this->Flag=false;				
				}	
			}
		}
	}
}

void Enemy::SetFlag(bool SF)
{
	this->Flag=SF;
}

bool Enemy::GetFlag()
{
	return this->Flag;
}

int Enemy::GetEX()
{
	return this->rect.x;
}

int Enemy::GetEY()
{
	return this->rect.y;
}

int Enemy::GetEW()
{
	return this->rect.w;
}

int Enemy::GetEH()
{
	return this->rect.h;
}

int Enemy::GetHP()
{
	return this->HP;
}


void Enemy::EnemyDraw()
{
	if(this->Flag==true)
	{
		DrawGraph((int)this->rect.x,(int)this->rect.y,(int)this->rect.Graph,true);
	}

	//DrawFormatString(460,20,GetColor(255,255,0),"敵のY:%f",this->rect.y);

	if(this->Flag==true)
	{
		DrawBox((int)this->rect.x,(int )this->rect.y,((int)this->rect.x+(int)this->rect.w),(int)this->rect.y+(int)this->rect.h,-1,false);
	}
	/*
	for(int i=0;i<3;i++)
	{
		DrawFormatString(550,60,GetColor(255,255,0),"方向:%f",this->MoveCount);
	}
	*/
}

コード:

//data構造体
#pragma once
#ifndef H_STRUCT
#define H_STRUCT

#include"DXlib.h"

typedef struct tag_data
{
	float x,y;//座標(敵、プレイヤー共通)
	int CMAX;//敵が動く限界これを超えると反対に移動する。
	float speed;//敵が動くスピード
	int	h,w;//絵の幅と高さ(プレイヤー、敵共通)
	int Graph,AGrah;//Graph=普通の絵を入れる(プレイヤー敵共通、AGraph=プレイヤーが攻撃するときの絵)

}data;


#endif

コード:

//CSV(エクセルで作った)
x座標,y座標,速さ,動ける範囲
200,390,0.6,80
100,100,1,60
300,380,0.7,80

ファイル読み込みはmain文の40~90行目です。ファイル処理をmain文に書いてしまっていますが、後で修正します。今は、ファイル読み込みを成功させることだけを考えているので。怪しいと思っているのが59行目だと私は考えているのですが、解決策が見つかりません。「~.exeは動作を停止しました。」と出てしまいます。そして、55行目のwhile文を消そうとすると、敵が出てこなくなります。何かこうしたほうがいい、自分はこうしているというものなどがあれば、回答してくださると助かります。結構長い時間悩んでいます。どうかよろしくお願いします。


後、書き忘れていましたが、環境はvisual studio2010 のDXライブラリを使っています。

以下は自分がファイル読み込みをする時に参考にしたURLです。
http://bituse.info/game/shot/11

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

Re: ゲームプログラミング:CSVで敵を出現させたい

#4

投稿記事 by usao » 9年前

strcat()って,そんな使い方して大丈夫なの…? (line 63)
オフトピック
あと,データファイル側には小数があるように見えるけど
全部atoi()になってますね.

roxas11000510113

Re: ゲームプログラミング:CSVで敵を出現させたい

#5

投稿記事 by roxas11000510113 » 9年前

<< usao さん
返信ありがとうございました。
そして、atoi()ご指摘ありがとうございました。
atofに変更しました。
ですが、まだ動きません。strcat()が少しおかしいとのことですが、
何がおかしいのでしょうか?全く見当がつかずに困っています。

旅路のきのこ

Re: ゲームプログラミング:CSVで敵を出現させたい

#6

投稿記事 by 旅路のきのこ » 9年前

こんにちは!
59行目と61行目ですが、逆にしたほうが良くはないでしょうか?
61行目でEOFが入ったときに、63行目でおかしなことにならないか心配です。

後は、見間違いかもしれませんが、55行目のwhileを抜けるbreakが見当たらない気がします。

naohiro19
記事: 256
登録日時: 13年前
住所: 愛知県

Re: ゲームプログラミング:CSVで敵を出現させたい

#7

投稿記事 by naohiro19 » 9年前

Boost Spirit ライブラリなら簡単にできますよー。
https://sites.google.com/site/boostjp/tips/parser

Let's boostの解説ページ。
http://www.kmonos.net/alang/boost/classes/spirit.html

旅路のきのこ

Re: ゲームプログラミング:CSVで敵を出現させたい

#8

投稿記事 by 旅路のきのこ » 9年前

すいません、あとstrcatですが、渡されたポインタからヌル文字が現れるまで付け加えるので、1バイトだけ付け加えてくれる、というわけではありません。
で、cにEOFが入ったときに、63行目のstrcatで、えらいことになっている可能性があります。
まあ、strcatは普通は文字列を連結するときに使うので、こういう場合は大人しくbuf=c;とかで代入するほうがいいのかもしれません。

旅路のきのこ

Re: ゲームプログラミング:CSVで敵を出現させたい

#9

投稿記事 by 旅路のきのこ » 9年前

何度もすみません。深く考えずに書き込んでいたので、おかしなことを言ってしまっていました。

多分、c==EOFのときに55行目のwhileを抜けるのが必要でしょうから、59行目のif文を57行目のwhileの外に出してはどうでしょうか?(これに関して僕は意味不明なことを申し上げてしまっていました)

61行目を実行してc==EOFになったときに63行目で思いもよらない動作をするかもしれないということはおそらく本当なので、そこの処理をきちんとするといいと思います。

他、気になったことです。
・53行目のループを抜けたときにcには必要なデータが入っているのかもしれませんが、バッファに付け加える前にもう一度c=fgetc(fp)を行ってしまっても大丈夫なのでしょうか?
・fclose(fp)が見当たらないようです。




テキスト処理をするのは個人的なことですが、すごく面倒に感じているので、naohiro19さんの言うようにライブラリを使うのもいいと思います。
僕の場合はよく別のスクリプト言語でテキストファイルをバイナリに変えます。
では。

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

Re: ゲームプログラミング:CSVで敵を出現させたい

#10

投稿記事 by usao » 9年前

> strcat(buf,(const char*)&c);

あー,
・リトルエンディアン
・sizeof(int) > sizeof(char)
という条件下であれば 結果として 文字を追加できてるってことなんですね.
オフトピック
参考にしたというWebサイトがこの書き方になってるんですね.

>buf=c;とか
ではなく あえて
わざわざ strcat を持ち出してきてまで…

roxas11000510113

Re: ゲームプログラミング:CSVで敵を出現させたい

#11

投稿記事 by roxas11000510113 » 9年前

返信大変遅れて申し訳ございません。

皆さんご回答ありがとうございます。
真剣に回答してくださってとてもうれしいです。

実は今現在、テスト勉強などで忙しいため、プログラムどころではなくなってしまっています。

7月の終わりまでは手が付けられないかもしれません。

余裕ができたら指摘されたとおりにやってみようと思います。

誠に申し訳ないのですが、もう少しおつきあいしてくださると助かります。

申し訳ございません。

閉鎖

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