弾幕が正常に動作しない

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

弾幕が正常に動作しない

#1

投稿記事 by missingno » 12年前

度々お世話になります。
このたびみなさんのおかげで大分プログラミングも進みいよいよステージを作ろうかというところまできました。
ここでまたもや障害にぶち当たりました。
弾幕を作ってそれを雑魚に撃たせるプログラム自体は滞りなく動いたのですが、雑魚を大量に登場させたとき弾幕が正常に動作しませんでした。
どうやらある雑魚を倒した直後に別の雑魚が弾を撃つ命令があると、倒した雑魚の座標から弾が発射されるようです。(うまく説明できません。すみません)

単体で登場させたときや、同じ弾幕の敵の場合そのようなことは起こらなかったです。
原因がさっぱりですのでご助力をお願いします。

以下ソースです。例によって関係ありそうなところだけピックアップしています。大筋は龍神録プログラミングの館さんの内容と変わっていません。
私のPCとの相性のせいかただ今とてもBBCodeが見にくくなっているのでろくに整理してないコードですがどうかご容赦ください。

コード:

//enemy.cpp  ショットを撃つ部分と撃破処理に関わるところ
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(enemy[i].direction==1)//right
					enemy[i].img=12*enemy[i].color+(enemy[i].count/10)%4+8;
				if(enemy[i].direction==2)//left
					enemy[i].img=12*enemy[i].color+(enemy[i].count/10)%4+8;
				if(enemy[i].direction==0)//front
					enemy[i].img=12*enemy[i].color+(enemy[i].count/10)%4;

				if(enemy[i].x<-30||FIELD_MAX_X+30<enemy[i].x||enemy[i].y<-30||FIELD_MAX_Y+30<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);
			}
		}
	}
}

//out.cpp enemy_death_judge関数がint型の理由は後で説明します
int enemy_death_judge(int s)
{
	int i;
	if(enemy[s].hp>=enemy[s].hp_max/5)
	{
		se_flag[11]=1;
		return 0;
	}
	if(enemy[s].hp<enemy[s].hp_max/5&&enemy[s].hp>0)
	{
		se_flag[12]=1;
		return 0;
	}
	if(enemy[s].hp<0)
	{
		enemy[s].flag=0;
		se_flag[14]=1;
		enter_del_effect(s);
		for(i=0;i<BARRAGE_MAX;i++)
		{
			if(shot[i].flag!=0)
			{
				if(s==shot[i].ID)
				{
					shot[i].flag=2;
				}
			}
		}
		return 1;
	}
	return -1;
}

void cshot_and_enemy()
{
	int i,s;
	for(i=0;i<CSHOT_MAX;i++)
	{
		if(cshot[i].flag>0)
		{
			for(s=0;s<ENEMY_MAX;s++)
			{
				if(enemy[s].flag>0)
				{
					if(out_judge_cshot(i,s))
					{
						cshot[i].flag=0;
						enemy[s].hp-=cshot[i].power;
						enemy_death_judge(s);
					}
				}
			}
		}
	}
}

またもう一つ質問があるのですが龍神録のコードで撃ち返し弾を実装するにはどうすればいいですか。
enemy_death_judge関数がint型なのもそれのための悪あがきの名残です。このままではバグるので消去する予定です。

コード:

if(enemy_death_judge(n)==1)
{
	shot[n].bullet[k].x=enemy[n].x;
	shot[n].bullet[k].y=enemy[n].y;
	shot[n].bullet[k].speed=2;
	shot[n].bullet[k].angle=shotatan2(n);
	shot[n].bullet[k].flag=1;
}
上記のような感じでいけそうだったんですけどダメでした。

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

Re: 弾幕が正常に動作しない

#2

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

マジックナンバーが多いのと、謎の変数名、そのまま動かないコードなので答えが返らないんじゃないかと思います。
もう少し解説が必要だと思います。 あとデバッガやPrintfDXで変数の内容の変化は確認されていますか?

撃ち返し弾の件は、龍神録などの変数や構造体に詳しくないので何とも言えません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

KRNKRS
記事: 40
登録日時: 12年前
連絡を取る:

Re: 弾幕が正常に動作しない

#3

投稿記事 by KRNKRS » 12年前

打ち返し弾というとつまり反射弾みたいなものでしょうか?

となると、弾の座標を確認して、反射させたい場所に来たら座標を加算する値(たとえばspeedという名前の変数)に「-1」をかけてあげればよろしいかと。
以下例(一部省略)

コード:

//弾全部の座標を確認する
for(i=0; i<BULLET_MAX; i++){
  //弾のX座標が0以下になったら
  if(bullet[i].x < 0){
      //speedに-1をかける
      bullet[i].speed *= -1;
  } 
}
間違っていたらすみません。

【追記】
あ、これではy座標も変わってしまいますね。
確か私のときはY座標用のspeed変数とX座標用のspeed変数を用意してたような。
でもたぶん正しい使い方ではないかもしれません。
申し訳ありません。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: 弾幕が正常に動作しない

#4

投稿記事 by ISLe » 12年前

撃ち返し弾というのは、敵が死ぬときにバラバラと撃つ弾のことですよね。

敵のインデックスと弾のインデックスは別管理なので、空いてる弾のインデックスを探して使う必要があります。
『龍神録プログラミングの館』の『敵にショットを撃たせてみよう』の章によると、敵の弾を撃つにはenter_shot関数を呼び出すだけで良さそうですが。

アイテムを出すため敵のインデックスを記録していますが、撃ち返し弾は敵が既に死んでいるので、特別な値を持たせて敵のインデックスと区別しなければいけません。
弾に記録されている敵のインデックスを使っている箇所も撃ち返し弾に対応させる必要があります。

死んだときに弾を一発出すだけならこれで良いのですが、バラバラと出したいときには、継続して撃ち返し弾を撃つ処理が必要になります。
敵が死んだとき、撃ち返し弾をひとしきり撃ったら自動消滅する姿のないキャラを生成する感じになります。

missingno

Re: 弾幕が正常に動作しない

#5

投稿記事 by missingno » 12年前

>ISLeさん
そのような感じで撃ち返し弾のシステム自体は実装できました。
ただ依然として弾幕が正常に動作していないという問題は存在しているのでそれがどうも…

>KRNKRSさん
そのような弾幕には非常に興味がありますが今回お聞きしているのはそれではありません。

>softyaさん
かなり時間がかかってしまいましたが、ようやく原因が分かりました。
敵を撃破した場合や一度に大量の敵が出てくるとき、enter_shot関数内のforループ処理が追いつかず、違う値に弾幕を識別する数値が代入されているようです。
(うまく説明できません。申し訳ありません)
もっとも私自身C言語についての理解が浅い面もあるので、これが正しいという保証はありませんが…。

とりあえず龍神録の関数とそのまま置き換えて使える関数を用意したので、お手数ですがこれで確かめてくださいませんか?
・一度に10体近く(私が試したのは13~20体)の敵が出る
・そのうち1体でもいいから違う弾幕を撃つ敵がいる
・自機がショットで敵をある程度倒している(ノーショットでも確認)
以上の状況であればある程度の再現性があると思います。

コード:

//enemy.cpp
void enter_shot(int i)
{
	int j;
	for(j=0;j<SHOT_MAX;j++)
	{
		if(shot[j].flag==0)
		{
			memset(&shot[j],0,sizeof(shot_t));
			shot[j].flag=1;
			shot[j].knd=enemy[i].blknd;
			shot[j].num=i;
			shot[j].cnt=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].ang)*enemy[i].sp;
				enemy[i].y+=sin(enemy[i].ang)*enemy[i].sp;
				enemy[i].x+=enemy[i].vx;
				enemy[i].y+=enemy[i].vy;
				enemy[i].cnt++;
				if(enemy[i].x<-30||FIELD_MAX_X+30<enemy[i].x||enemy[i].y<-30||FIELD_MAX_Y+30<enemy[i].y)
				{
					enemy[i].flag=0;
				}
				if(enemy[i].bltime==enemy[i].cnt)
				{
					enter_shot(i);
				}
			
			}else{
				printfDx("%dが不正です",enemy[i].pattern);
			}
		}
	}
}

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

Re: 弾幕が正常に動作しない

#6

投稿記事 by Tatu » 12年前

問題になっている現象の確認に必要なのは
龍神録プログラミングの館で配布されているプロジェクトと
missingnoさんが使用したcsvファイルではないですか?

投稿されたコードは元々のコードとほぼ同様なので
置き換えても意味がないと思います。

正常に動く場合とその現象が起こっている場合の両方を
動画にして見せてくれるとわかりやすいと思います。

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

Re: 弾幕が正常に動作しない

#7

投稿記事 by Tatu » 12年前

missingnoさんが書かれている現象とは別の現象ですが
四聖龍神録v2.83では敵を倒すと同時に出てきた敵が
倒した敵のショットを引き継いでしまうというバグがあります。
無題.png
添付画像は左側の二列の弾の列を発生させた敵を倒したら
右側に出現した敵が青い弾の列を発生させたところです。
通常は青い弾の列は発生しません。

missingno

Re: 弾幕が正常に動作しない

#8

投稿記事 by missingno » 12年前

>Tatuさん
龍神録のコードを自分のバグが再現できるように組み直していたところ、自分のバグの原因が見つかりました。
龍神録の館では敵に弾を撃たせるときの弾源座標を
enemy[shot[n].num].x,enemy[shot[n].num].y
というふうに表します。
私はそれをいちいち入力する手間を省くため敵座標を取得する関数を作っていたのですがそこには
enemy[n].x,enemy[n].y
と書かれていました。となると敵を倒してしまった場合当然[]内の値がずれてくるので弾幕がうまく表示されなかったようです。

私のくだらないミスでご心配をおかけしました。ご助言をありがとうございました。

>倒した敵のショットを引き継いでしまうというバグがあります。
こちらの問題にも遭遇するかもしれませんが、とりあえず疑問は解消されたのでこのトピックは解決にさせていただきます。

閉鎖

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