色々問題が発生してどうしたらいいか分からない

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

色々問題が発生してどうしたらいいか分からない

#1

投稿記事 by missingno » 6年前

何度もお世話になります。
このたび龍神録の館を参考にしつつアレンジしてプログラミングをしていたのですがこのたびどうすればいいか分からない問題が発生しました。
私が作っているシューティングゲームでは多くの種類の敵キャラが登場する予定なのでコードをそのように書き換えたところこれらの問題が起きました。

1.データの最初の敵しか表示されない
csvファイルに何体かの違う種類の敵を表示させるよう記述したところ最初の一体しか表示されなくなりました。
最初の一体のデータを変更したところ思った通りに変更されコードを書き換える前は正常に複数体表示できていたのでコーディングの問題だと思います。

2.弾幕が欠けて描画される
円形弾を多く撃たせるプログラムを書いたところ第一波は正常に描画されますが第二波以降は欠けて描画されます。
設定している1弾幕に持たせる最大弾数明らかに超えておらず何が原因かさっぱりです。

3.敵および弾が透ける
敵が弾を撃つシークエンスに入ると敵や弾が半透明になってフレームや自機に重なっても透けて描画されます。
描画順などは間違ってはいません。

4.nway弾が自機を狙わない
これはそのままです。nway弾が自機を狙ってくれません。
また、今はnway弾の計算をするのに"(way-1)*angle/2"というような式を用いていますが1wayの時でも同じ計算式で求められる式があれば教えていただきたいです。

以下、コードです。一部変数名が異なる以外は龍神録の館のコードとほぼ同じです。

コード:

//enemy.cpp
void enemy_enter()
{
	int i,j,t;
	for(t=0;t<ENEMY_ORDER_MAX;t++)
	{
		if(enemy_order[t].count==stage_count)
		{
			if((i=enemy_num_search())!=-1)
			{
				enemy[i].flag =1;
				enemy[i].count=0;
				enemy[i].pattern=enemy_order[t].pattern;
				enemy[i].kind=enemy_order[t].kind;
				enemy[i].color=enemy_order[t].color;
				enemy[i].x=enemy_order[t].x;
				enemy[i].y=enemy_order[t].y;
				enemy[i].speed=enemy_order[t].speed;
				enemy[i].batime=enemy_order[t].batime;
				enemy[i].bakind=enemy_order[t].bakind;
				enemy[i].blkind=enemy_order[t].blkind;
				enemy[i].blcolor=enemy_order[t].blcolor;
				enemy[i].wtime=enemy_order[t].wait;
				enemy[i].hp=enemy_order[t].hp;
				enemy[i].hp_max=enemy[i].hp;
				enemy[i].vx=0;
				enemy[i].vy=0;
				enemy[i].angle=0;
				for(j=0;j<10;j++)
					enemy[i].item[j]=enemy_order[t].item_n[j];
			}
		}
	}
}

void enter_shot(int i)
{
	int j;
	for(j=0;j<BARRAGE_MAX;j++)
	{
		if(shot[j].flag==0)
		{
			memset(&shot[j],0,sizeof(shot_t));
			shot[j].flag=1;
			shot[j].kind=enemy[i].bakind;
			shot[j].ID=i;
			shot[j].count=0;
			return;
		}
	}
}




void enemy_act()
{
	int i;
	for(i=0;i<ENEMY_MAX;i++)
	{
		if(enemy[i].flag==1)
		{
			if(0<=enemy[i].pattern&&enemy[i].pattern<ENEMY_PATTERN_MAX)
			{
				enemy_pattern[enemy[i].pattern](i);
				enemy[i].x+=cos(enemy[i].angle)*enemy[i].speed;
				enemy[i].y+=sin(enemy[i].angle)*enemy[i].speed;
				enemy[i].x+=enemy[i].vx;
				enemy[i].y+=enemy[i].vy;
				enemy[i].count++;
				if(cos(enemy[i].angle)*enemy[i].speed>0.3||enemy[i].vx>0.3)
					enemy[i].img=12*enemy[i].color+(enemy[i].count/10)%4+8;
				if(cos(enemy[i].angle)*enemy[i].speed<-0.3||enemy[i].vx<-0.3)
				{
					enemy[i].img=12*enemy[i].color+(enemy[i].count/10)%4+8;
					enemy[i].direction=2;
				}
				if(cos(enemy[i].angle)*enemy[i].speed<0.3&&cos(enemy[i].angle)*enemy[i].speed>-0.3&&enemy[i].vx<0.3&&enemy[i].vx>-0.3)
					enemy[i].img=12*enemy[i].color+(enemy[i].count/10)%4;

				if(enemy[i].x<-50||FIELD_MAX_X+50<enemy[i].x||enemy[i].y<-50||FIELD_MAX_Y+50<enemy[i].y)
				{
					enemy[i].flag=0;
				}
				if(enemy[i].batime==enemy[i].count)
				{
				enter_shot(i);
				}
			
			}else{
				printfDx("enemy[i].pattern error!",enemy[i].pattern);
			}
		}
	}
}

//shot_common.cpp
int GetEnemyX(int n)//敵のx座標を取得する関数です
{
	return enemy[n].x;
}

int GetEnemyY(int n)//敵のy座標を取得する関数です
{
	return enemy[n].y;
}

//nway弾を任意の方向へ撃たせるものです
void Nway(double x,double y,int kind,int color,int way,double range,double speed,double angle,int se,int n,int k)
{
	int a=(way-1)*angle/2;
	for(int i=0;i<way;i++)
	{
		if(shot[n].flag!=2 && (k=shot_search(n))!=-1)
		{
			shot[n].bullet[k].kind =kind;
			shot[n].bullet[k].angle=a+i*range;
			shot[n].bullet[k].flag=1;
			shot[n].bullet[k].x=x;
			shot[n].bullet[k].y=y;
			shot[n].bullet[k].color=color;
			shot[n].bullet[k].count=0;
			shot[n].bullet[k].speed=speed;
			se_flag[se]=1;
		}
	}	
}

//shot.cpp
int shot_search(int n)
{
	int i;
	for(i=0;i<SHOT_BULLET_MAX;i++)
	{
		if(shot[n].bullet[i].flag==0)
		{
			return i;
		}
	}
	return -1;
}

//graph.cpp…このファイル内の関数は使用している画像の関係上龍神録の館のソースとは大きく異なります
void graph_enemy()
{
	int i;
	for(i=0;i<ENEMY_MAX;i++)
	{
		if(enemy[i].flag==1)
		{
			if(enemy[i].direction==2)
				DrawRotaGraphF(enemy[i].x+FIELD_X,enemy[i].y+FIELD_Y,1.0f,0.0f,img_enemy[enemy[i].kind][enemy[i].img],TRUE,TRUE);
			DrawRotaGraphF(enemy[i].x+FIELD_X,enemy[i].y+FIELD_Y,1.0f,0.0f,img_enemy[enemy[i].kind][enemy[i].img],TRUE,FALSE);
		}
	}
}

void graph_board()
{
	DrawRectGraph(0,0,0,0,416,16,img_board,TRUE,FALSE);//upper frameground
	DrawRectGraph(0,16,0,16,32,448,img_board,TRUE,FALSE);//left side frameground
	DrawRectGraph(0,464,0,464,416,16,img_board,TRUE,FALSE);//bottom frameground
	DrawRectGraph(416,0,416,0,224,480,img_board,TRUE,FALSE);//right side frameground
}

void graph_bullet()
{
	int i,j;
	SetDrawMode(DX_DRAWMODE_BILINEAR);
	for(i=0;i<BARRAGE_MAX;i++)
	{
		if(shot[i].flag>0)
		{
			for(j=0;j<BARRAGE_MAX;j++)
			{
				if(shot[i].bullet[j].flag!=0)
				{
					SetDrawBlendMode(DX_BLENDMODE_ADD,255);
					DrawRotaGraphF(shot[i].bullet[j].x+FIELD_X,shot[i].bullet[j].y+FIELD_Y,1.0,
								   shot[i].bullet[j].angle+PI/2,img_bullet[shot[i].bullet[j].kind][shot[i].bullet[j].color],TRUE);
					if(shot[i].bullet[j].effect==1)
						SetDrawBlendMode(DX_BLENDMODE_NOBLEND,0);
				}
			}
		}
	}
	SetDrawMode(DX_DRAWMODE_NEAREST);
}

void graph_cshot()
{
	for(int i=0;i<CSHOT_MAX;i++)
	{
		if(cshot[i].flag>0)
		{
			DrawRotaGraphF(cshot[i].x+FIELD_X,cshot[i].y+FIELD_Y,1.0,PI/2*3,img_cshot[cshot[i].kind][1],TRUE);
		}
	}
}


void graph_main()
{
	graph_enemy();
	graph_cshot();
	graph_ch();
	graph_bullet();
	graph_board();
}

//load.cpp
void load_excel()
{
	int n,num,i,fp;
	char fname[32]={"./dat/csv/test.csv"};
	int input[64];
	char inputc[64];

	fp=FileRead_open(fname);
	if(fp==NULL)
	{
		printfDx("read error!\n");
		return;
	}
	for(i=0;i<2;i++)
		while(FileRead_getc(fp)!='\n');

	n=0,num=0;
	while(1)
	{
		for(i=0;i<64;i++)
		{
			inputc[i]=input[i]=FileRead_getc(fp);
			if(inputc[i]=='/')
			{
				while(FileRead_getc(fp)!='\n');
				i=-1;
				continue;
			}
			if(input[i]==','||input[i]=='\n')
			{
				inputc[i]='\0';
				break;
			}
			if(input[i]==EOF)
			{
				goto EXFILE;
			}
		}
		switch(num)
		{
		case 0:enemy_order[n].count=atoi(inputc);break;
		case 1:enemy_order[n].pattern=atoi(inputc);break;
		case 2:enemy_order[n].kind=atoi(inputc);break;
		case 3:enemy_order[n].color=atoi(inputc);break;
		case 4:enemy_order[n].x=atoi(inputc);break;
		case 5:enemy_order[n].y=atoi(inputc);break;
		case 6:enemy_order[n].speed=atoi(inputc);break;
		case 7:enemy_order[n].batime=atoi(inputc);break;
		case 8:enemy_order[n].bakind=atoi(inputc);break;
		case 9:enemy_order[n].blcolor=atoi(inputc);break;
		case 10:enemy_order[n].hp=atoi(inputc);break;
		case 11:enemy_order[n].blkind=atoi(inputc);break;
		case 12:enemy_order[n].wait=atoi(inputc);break;
		case 13:enemy_order[n].item_n[0]=atoi(inputc);break;
		case 14:enemy_order[n].item_n[1]=atoi(inputc);break;
		case 15:enemy_order[n].item_n[2]=atoi(inputc);break;
		case 16:enemy_order[n].item_n[3]=atoi(inputc);break;
		case 17:enemy_order[n].item_n[4]=atoi(inputc);break;
		case 18:enemy_order[n].item_n[5]=atoi(inputc);break;
		case 19:enemy_order[n].item_n[6]=atoi(inputc);break;
		case 20:enemy_order[n].item_n[7]=atoi(inputc);break;
		case 21:enemy_order[n].item_n[8]=atoi(inputc);break;
		case 22:enemy_order[n].item_n[9]=atoi(inputc);break;
		}
		num++;
		if(num==22)
		{
			num=0;
			n++;
		}
	}

EXFILE:
	FileRead_close(fp);
}

質問が多いうえとても長く拙いコードで申し訳ありません。もしコードのほかの部分が見たいのであればその都度書き加えます。

beatle
記事: 1280
登録日時: 8年前
住所: 埼玉
連絡を取る:

Re: 色々問題が発生してどうしたらいいか分からない

#2

投稿記事 by beatle » 6年前

たくさん問題が発生しても慌てないで,1つずつ解決しましょう.
まず複数の敵のロードから直したら如何でしょう.

パッとコードを見て気になったのは,load_excel()のwhile(1)の中身です.
numが恐らくCSVの横方向に対応すると思います.
switch(num)を見ると,numが0から22,つまり横方向の要素が23個あることを期待してます.

しかし,numが21の状態でswitch文の実行を終えると,直後にnum++され,numが22となり,if文でnumが0となります.
したがって,switch(num)の時点では,numは0から21までしか変化しません.
つまりCSVの横方向の要素が22個でないと上手く動きません.

switch文のcase 22が要らないのか,if(num==22)が間違っているのかは分かりませんが,どちらかはミスだろうと思います.

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

Re: 色々問題が発生してどうしたらいいか分からない

#3

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

プログラムの機能追加は、部分的に動作を確認しながら徐々に行わないと訳の分からないことになりがちです。
なので、いっぺんに直そうとせず部分部分で解決して行きましょう。
どうにも分からない場合は、今のコードを保存しておいて一時的に部分的に昔のコードに戻してみるのも良いでしょう。
とにかく考えることを限定的にして分かりやすくする解決への早道です。

まず、「1.データの最初の敵しか表示されない」から解決して行きましょう。
csvの読み込みが正常かを確認します。

私の書いたprintfデバッグ法です。これでcsvの読み込んだ値が期待通りかprintfしてみてください。
「簡単RPG講座 番外編。 デバッグ入門 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/blog.php?u=114&b=982&c=2
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

missingno

Re: 色々問題が発生してどうしたらいいか分からない

#4

投稿記事 by missingno » 6年前

>>switch文のcase 22が要らないのか,if(num==22)が間違っているのかは分かりませんが,どちらかはミスだろうと思います.
龍神録の館のソースと見比べてみたところこの部分に間違いがありました。if(num==23)にしたところ求める結果を得ることができました。
ありがとうございます。

>>私の書いたprintfデバッグ法です。これでcsvの読み込んだ値が期待通りかprintfしてみてください。
申し訳ありません。c++は一通り(さらっと)学んだのですがポインタだけは理解をすっ飛ばしています。だから、書いてあることの意味が少ししかわかりませんでした。
とりあえず、load_excel()関数部分だけ抜き出して別のプロジェクトにコピペし、そのあと読み込んだcsvファイルをprintfで出力するということですか。

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

Re: 色々問題が発生してどうしたらいいか分からない

#5

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

missingno さんが書きました: >>私の書いたprintfデバッグ法です。これでcsvの読み込んだ値が期待通りかprintfしてみてください。
申し訳ありません。c++は一通り(さらっと)学んだのですがポインタだけは理解をすっ飛ばしています。だから、書いてあることの意味が少ししかわかりませんでした。
ポインタを避けて自由に龍神録に機能追加が出来ると思えませんが、今回のcsvの件だけに限れば不要だと思います。
csvから読み込まれた構造体のメンバ変数値を確認するだけです。
missingno さんが書きました: とりあえず、load_excel()関数部分だけ抜き出して別のプロジェクトにコピペし、そのあと読み込んだcsvファイルをprintfで出力するということですか。
分けても良いですが、分けなくても確認できると思います。
分けたほうが勉強にはなるでしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
Tatu
記事: 445
登録日時: 9年前
住所: 北海道

Re: 色々問題が発生してどうしたらいいか分からない

#6

投稿記事 by Tatu » 6年前

「2.弾幕が欠けて描画される」について
BARRAGE_MAXとSHOT_BULLET_MAXはそれぞれ何を表しているかを考えて
弾の描画処理を見直してください。

「3.敵および弾が透ける」について
弾を描画するときに毎回加算ブレンドになり、
ノーブレンドに戻るのはshot.bullet[j].effectが1の時だけのようです。
加算ブレンドになるのはshot.bullet[j].effectが1の時だけなのではないでしょうか?

misssingno

Re: 色々問題が発生してどうしたらいいか分からない

#7

投稿記事 by misssingno » 6年前

>>tatuさん
2.と3.についてはあなたの助言をもとに見直したところあっさり治りました。
大変ありがとうございます。

アバター
Tatu
記事: 445
登録日時: 9年前
住所: 北海道

Re: 色々問題が発生してどうしたらいいか分からない

#8

投稿記事 by Tatu » 6年前

「4.nway弾が自機を狙わない」について
狙う方向をangle、wayの間隔をrangeとして
弾の飛ぶ方向は
1wayならばangle
2wayならばangle-0.5*range,angle+0.5*range
3wayならばangle-range,angle,angle*range
...
と考えてはどうでしょうか。

この場合、4way,5way,nwayではどうなるでしょうか。

missingno

Re: 色々問題が発生してどうしたらいいか分からない

#9

投稿記事 by missingno » 6年前

Tatuさん大変ありがとうございました。おかげで無事解決することができました

コード:

void Makebullet(double x,double y,int kind,int color,double speed,double angle,int se,int n,int k)
{
	if(shot[n].flag!=2 && (k=shot_search(n))!=-1)
	{
		shot[n].bullet[k].kind =kind;
		shot[n].bullet[k].angle=angle;
		shot[n].bullet[k].flag=1;
		shot[n].bullet[k].x=x;
		shot[n].bullet[k].y=y;
		shot[n].bullet[k].color=color;
		shot[n].bullet[k].count=0;
		shot[n].bullet[k].speed=speed;
		se_flag[se]=1;
	}
}

void Nway(double x,double y,int kind,int color,int way,double range,double speed,double angle,int se,int n,int k)
{
	double a=angle-range*(way-1)/2;
	for(int i=0;i<way;i++)
	{	
		Makebullet(x,y,kind,color,speed,a+i*range,se,n,k);
	}	
}
Tatuさんの助言に従った通りのコードは以上のようになっています。現在はいろいろ考えた末に元々考えていた形式に戻すことにしました。

コード:

void Nway(double x,double y,int kind,int color,int way,double range,double speed,double angle,int se,int n,int k)
{
	double a=angle-range/2;
	for(int i=0;i<way;i++)
	{	
		Makebullet(x,y,kind,color,speed,a+i*range/(way-1),se,n,k);
	}	
}
原因は関数Nway内の角度を持たせている変数aをint型で宣言していたことでした。とても情けないミスです。
何はともあれ、長い間お付き合いくださり、まことにありがとうございます。

追加で質問なんですけど今後私はこの掲示板を利用することが多々あると思います。プログラムも初めて日が浅いので日々壁にぶち当たりどうやって乗り越えようか必死で考えているような始末です。
そこでこれから疑問・不具合がでたときに今回のようにある程度溜めてから投稿するのがいいのでしょうか。それとも1つ1つ投稿したほうがいいのでしょうか。
追加で申し訳ありませんが教えていただければ幸いです。

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

Re: 色々問題が発生してどうしたらいいか分からない

#10

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

溜めないほうが良いと思います。

その前に、一気に色んな所を直すの止めたほうが良いと思います。
1箇所を直したら、pritnfやらデバッガで変更できているのを確認してください。
これはアマでもプロでも変わりません。プログラムが出来るようになるために必要な技能なのです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

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