STGのアイテムの実装

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

STGのアイテムの実装

#1

投稿記事 by tt » 14年前

C言語でSTGをつくっています。環境はVisual C++ 2010 Express Editionで,ライブラリはDXライブラリです。
敵を倒したら得点や体力がupするアイテムが倒した敵の位置から出現するようにアイテムを実装したのですが,なぜか敵を倒した位置のままで止まってしまい,動きません。また,複数個アイテムを出現させようとすると,消えてしまいます(同時に1つしか出現させられません)。
なぜでしょうか?

コード:

//アイテムの構造体
typedef struct{
	double x,y,speed;
	int flag,kind,range;
}item_t;
item_t item[item_kosuu];

//アイテムの種類によって発動させる効果を変化させる
void ItemEffect()
{
	for(int i=0; i<item_kosuu; i++){
	   switch(item[i].kind)
	   {
		   case 1:
			   Player.score++;
			   break;
		   case 2:
			   Player.hp++;
			   break;
		   case 3:
			   bomb.kosuu++;
			   break;
		   default:
			   break;
	   }
	}
}

//アイテムの描画
void Itemdraw()
{
	for(int i=0; i<item_kosuu; i++){
	   if(item[i].flag == 1)
	   {
		   switch(item[i].kind)
		   {
			   case 1:
				   DrawGraph(item[i].x,item[i].y,item1,TRUE);
				   break;
			   case 2:
				   DrawGraph(item[i].x,item[i].y,item2,TRUE);
				   break;
			   case 3:
				   DrawGraph(item[i].x,item[i].y,item3,TRUE);
				   break;
			   default:
				   break;
		   }
	   }
	}
}
//省略 Playerの弾と敵の当たり判定
//敵に弾が当たったらそこにアイテムを出現させy座標をあげていき落としていく
for(int i=0; i<item_kosuu; i++){
																	item[i].x=enemy[s].x;
																	item[i].y=enemy[s].y;
																	item[i].flag=1;
																	item[i].range=20;
																	if(item[i].flag==1)
																	{
																		double ix,iy;
																		ix=Player.x-item[i].x;
																		iy=Player.y-item[i].y;
																		item[i].y+=2;
																		Itemdraw();
																		if(sqrt(ix*ix+iy*iy) < Player.range+item[i].range)
																		{
																			ItemEffect();     
																			item[i].flag=0;
																		}
																	}
																}


翡翠

Re: STGのアイテムの実装

#2

投稿記事 by 翡翠 » 14年前

54行目からのfor文内で、毎回x、y座標やフラグが初期化されているように感じます。
なので、アイテムの初期化は item.flag が0の時のみ行われるようにすると、
アイテムが落ちてくるようになると思います。

また、アイテムの個数文ループを回しているので、
すべてのアイテムが同時に同じ場所に出現しているようです。
なので、先ほどの flag などを初期化した際に、
break でループを抜ける処理が必要だと思われます。


間違っていたらすみません……

翡翠

Re: STGのアイテムの実装

#3

投稿記事 by 翡翠 » 14年前

すみません、少々追記です

最後の for 文が、自機の弾と敵が当たった時のみ処理が行われる場合、
アイテムは敵に弾が当たるたびに少し落下、みたいな変な描写になってしまいます。

なので、「自機の弾が敵に当たった時」にアイテムの初期化処理を行い、
「すでに出現しているアイテム」の処理は別にしないといけません。

tt

Re: STGのアイテムの実装

#4

投稿記事 by tt » 14年前

アイテムが落ちてきて,それを回収する当たり判定まではとれました。ありがとうございます。
しかし,if(sqrt(ix*ix+iy*iy) < Player.range+item.range)を満たすときにすべてItemEfect関数が発生してしまうので,スコアを+1したいのに一気に+900になってしまったりします。この処理を1回だけに抑えるにはどうすればいいですか?

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

Re: STGのアイテムの実装

#5

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

まず、アイテムの当たり判定で衝突したアイテムしかItemEfectしてはいけません。つまりItemEfect内でループで処理するのは間違いです。
それと衝突判定は発生しているアイテムif(item.flag == 1)以外は無視しないといけません。
あとアイテムと自機が衝突してアイテムは消滅するのでitem.flag=0;で消さないといけません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

tt

Re: STGのアイテムの実装

#6

投稿記事 by tt » 14年前

なんとか点数の制御はできました。ありがとうございました。
最後にもうひとつだけ質問なのですが,東方妖々夢のように,霊撃で弾幕が桜点に変換されて自機に吸収されるって言うのはどういう処理をしているのでしょうか?

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

Re: STGのアイテムの実装

#7

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

tt さんが書きました:なんとか点数の制御はできました。ありがとうございました。
最後にもうひとつだけ質問なのですが,東方妖々夢のように,霊撃で弾幕が桜点に変換されて自機に吸収されるって言うのはどういう処理をしているのでしょうか?
ここのルールなのですが、あとで見る他の人が参考になるようになるべく修正したソースコードは貼ってくださいね。
ソースコードを見せてもらうと潜在バグなどの問題がある場合にアドバイスできるのでメリットもあります。

で、私は東方に詳しくないので吸収に関してはコメントしかねます。
動画とか貼ってもらうと推測では書き込めますよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 15年前
住所: 北海道札幌市
連絡を取る:

Re: STGのアイテムの実装

#8

投稿記事 by Dixq (管理人) » 14年前

弾幕が桜になるのはこの辺でしょうか。
[youtube][/youtube]
[8:34]

アイテム吸収の機能は既に実装されています。
計算している関数は calc.cpp > calc_item_indraw() で、
その関数は calc_item() から呼ばれています。
そして、.stateが1の時、吸収状態となるので、吸収させたいイベントが発生した時点で、.stateを1にすれば良いと思います。
桜に変える処理としては、アイテムの構造体に

.TransSakuraFlag

とでも変数を一つ追加しておき、通常falseで初期化しておきます。
桜に変えるイベントが発生した時点でtrueにし、trueの時は、アイテムを桜として表示するなどでいかがでしょうか。

tt

Re: STGのアイテムの実装

#9

投稿記事 by tt » 14年前

返信送れて申し訳ございません。
ここのルールなのですが、あとで見る他の人が参考になるようになるべく修正したソースコードは貼ってくださいね。
ソースコードを見せてもらうと潜在バグなどの問題がある場合にアドバイスできるのでメリットもあります。
ItemEfect関数をなくして直接その処理をItem関数に加えました(雑なやり方ですが)。そして,敵との当たり判定をとったときに,itemの初期化を行いました。そうしたらうまくいきました。

コード:

void Item(){
	for(int i=0; i<item_kosuu; i++){
		if(item[i].flag==1)
		{
			double ix,iy;
			ix=Player.x-item[i].x;
			iy=Player.y-item[i].y;
			item[i].y+=2;
			Itemdraw();
			if(sqrt(ix*ix+iy*iy) <  Player.range+item[i].range)
			{     
				item[i].flag=0;
				switch(item[i].kind)
				{
					case 1:
						Player.score++;
						if(CheckSoundMem(sound_item)==0)
						{
                            StopSoundMem(sound_item);
                            PlaySoundMem(sound_item,DX_PLAYTYPE_BACK);
						}
						break;
					case 2:
						Player.hp++;
						if(CheckSoundMem(sound_item)==0)
						{
                            StopSoundMem(sound_item);
                            PlaySoundMem(sound_item,DX_PLAYTYPE_BACK);
						}
						if(CheckSoundMem(sound_extend)==0)
						{
                            StopSoundMem(sound_extend);
                            PlaySoundMem(sound_extend,DX_PLAYTYPE_BACK);
						}
						break;
					case 3:
						bomb.kosuu++;
						if(CheckSoundMem(sound_item)==0)
						{
                            StopSoundMem(sound_item);
                            PlaySoundMem(sound_item,DX_PLAYTYPE_BACK);
						}
						break;
					default:
						break;
				}
			}
		}
	}
}
アイテム吸収の機能は既に実装されています。
計算している関数は calc.cpp > calc_item_indraw() で、
その関数は calc_item() から呼ばれています。
実は,大変申し訳ないことに「龍神録プログラミングの館」ではなく「シューティングゲームの館」を参考にしてつくっています。しかし龍神録の39章を拝見したらとてもわかりやすくかかれていたので,アイテムに関してはこちらを参考につくってみます。

tt

Re: STGのアイテムの実装

#10

投稿記事 by tt » 14年前

吸収処理もちゃんと実装できました!ありがとうございます!
解決に印いれときます。

閉鎖

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