ページ 11

弾幕の作成について

Posted: 2011年10月07日(金) 04:49
by クラバック
こんにちは。いつもお世話になっております。
弾幕を作っていたのですが、行き詰ってしまったので質問させて頂きました。

ボスから10個の弾がバラ撒かれ、100カウントかけて停止し、その60カウント後に、10個の弾のそれぞれが自分以外の弾を直線で結ぶように弾が展開される弾幕を作成しています。
ですが私の力が及ばず、実行結果は何故か画面の左上に変な風に弾が伸びてしまい、また、線分はどうにか描けるのですが、直線に描くことが出来ません。
void makeBullet()は、二つの座標を渡したら、その座標を結ぶ線分状に弾を配置する関数、
double getRand_5(double, double)は、渡された2値間のランダムな数を返す関数、
double shotatan3(double, double, double, double)は、渡された2つの座標の成す角度を返す関数です。
ご指導ご鞭撻の程、宜しくお願い致します。

コード:

void hosizora(){
#define HOSIZORA 1000
#define STOPCOUNT 100 //弾が静止するまでのカウント
	int l, k, i, s, h, m, t=boss_shot.cnt%HOSIZORA;//t=0~999
	int t2=boss_shot.cnt;
	static double spd[10];
	static double distance[10];
	static double x[10], y[10];
	static int f;
	static double box1[10][10];
	static double box2[10][10];
	void makeBullet(double x1, double y1, double x2, double y2, double angle, int divide, int knd, int col, int flag, double spd, int state, int eff, int eff_detail, int cnt, int till);//二つの座標を渡したら、その座標を結ぶ線分状に弾を配置する関数
	if(t2==0){
		f=0;
		for(i=0;i<10;i++){
			spd[i] = getRand_5(4,10);
			distance[i] = getRand_5(500,900);
		}
	}
	if(t2==100){
		for(i=0;i<10;i++){
			if((k=search_boss_shot())!=-1){
				boss_shot.bullet[k].x = boss.x;
				boss_shot.bullet[k].y = boss.y;
				boss_shot.bullet[k].angle = rang(PI);
				boss_shot.bullet[k].spd = distance[i]/STOPCOUNT/2;
				boss_shot.bullet[k].knd = 4;
				boss_shot.bullet[k].col = 0;
				boss_shot.bullet[k].state = 0;
				boss_shot.bullet[k].flag = 1;
				boss_shot.bullet[k].eff_detail = 1;
			}
		}
	}
	for(i=0;i<BOSS_BULLET_MAX;i++){
		if(boss_shot.bullet[i].flag>0){
			if(boss_shot.bullet[i].state == 0){
				if(boss_shot.bullet[i].cnt<STOPCOUNT){
					boss_shot.bullet[i].spd -= boss_shot.bullet[i].spd/(STOPCOUNT-boss_shot.bullet[i].cnt);
				}else if(boss_shot.bullet[i].cnt>=STOPCOUNT){
					x[f] = boss_shot.bullet[i].x;//fには0~9まで順番に入る
					y[f] = boss_shot.bullet[i].y;
					boss_shot.bullet[i].cnt=0;
					boss_shot.bullet[i].state = 1;
					f<9?f++:f=0;
				}
			}
			if(boss_shot.bullet[i].state == 1){
				if(boss_shot.bullet[i].cnt==30){
					for(h=0;h<9;h++){
						for(m=h+1;m<10;m++){			
							box2[h][m] = shotatan3(x[h], y[h], x[m], y[m]);//二次元配列box2に、それぞれの要素間の角度を格納
						}
					}
					boss_shot.bullet[i].cnt=0;
					boss_shot.bullet[i].state=2;
				}
			}
			if(boss_shot.bullet[i].state==2){
				if(boss_shot.bullet[i].cnt==30){
					for(h=0;h<9;h++){
						for(m=h+1;m<10;m++){
							makeBullet(x[h], y[h], x[m], y[m], box2[h][m], 40, 2, GetRand(9), 1, 0, 10, 1, 0, 0, 60);
						}
					}
				}
			}		
		}
	}
}
void makeBullet()定義

コード:

void makeBullet(double x1, double y1, double x2, double y2, double angle, int divide, int knd, int col, int flag, double spd, int state, int eff, int eff_detail, int cnt, int till){
//二つの座標を渡したら、その座標を結ぶ線分状に弾を配置する関数
	int i,k;
	for(i=0;i<divide+1;i++){
		if((k=search_boss_shot())!=-1){
			boss_shot.bullet[k].x = x1+(x2-x1)/divide*i;
			boss_shot.bullet[k].y = (x1+(x2-x1)/divide*i)*tan(angle);
			boss_shot.bullet[k].knd = knd;
			boss_shot.bullet[k].col = col;
			boss_shot.bullet[k].flag = flag;
			boss_shot.bullet[k].angle = angle;
			boss_shot.bullet[k].spd = spd;
			boss_shot.bullet[k].state = state;
			boss_shot.bullet[k].eff		   = eff;
			boss_shot.bullet[k].eff_detail = eff_detail;
			boss_shot.bullet[k].cnt		   = cnt;
			boss_shot.bullet[k].till = till;
		}
	}
}

Re: 弾幕の作成について

Posted: 2011年10月07日(金) 11:21
by Tatu
makeBulletの定義でy座標の計算に
引数のy1,y2が使われていないようですが
それでよいのでしょうか?

Re: 弾幕の作成について

Posted: 2011年10月08日(土) 14:12
by Tatu
弾幕を作成してみました。
[nico]http://www.nicovideo.jp/watch/sm15824832[/nico]

弾幕関数

コード:

void boss_shot_bulletE239(){
	int t=boss_shot.cnt%420;
	int BNUM=boss_shot.cnt/420+2;
	double const D=64;
	int const OUT_RANGE=120;
	int i,j;
	double x,y,angle;
	double dx,dy;


	//中弾発生
	if(t==0){
		for(i=0;i<BNUM;i++){
			boss_bullet_on3(1,1,1,1,1,-20,boss.x,boss.y,i*PI2/BNUM+rang(PI/2/BNUM),0,4+rang(0.5),0,0,1,0,0,1);
		}
	}

	for(i=0;i<BOSS_BULLET_MAX;i++){
		if(boss_shot.bullet[i].flag==1 && boss_shot.bullet[i].cnt>=0){
			switch(boss_shot.bullet[i].state){
			case 1://減速中
				boss_shot.bullet[i].spd-=boss_shot.bullet[i].spd/(60-boss_shot.bullet[i].cnt);
				if(boss_shot.bullet[i].spd==0){
					boss_shot.bullet[i].cnt=0;
					boss_shot.bullet[i].state=2;
				}
				break;
			case 2://中弾と中弾をつなぐ直線上にカード弾を発生させる
				if(boss_shot.bullet[i].cnt==60){
					for(j=0;j<BOSS_BULLET_MAX;j++){
						if(boss_shot.bullet[j].state==2 && i!=j){//他の中弾を探す
							//他の中弾に向かう方向に弾を発生させる
							x=boss_shot.bullet[i].x;
							y=boss_shot.bullet[i].y;
							angle=atan2(boss_shot.bullet[j].y-boss_shot.bullet[i].y,boss_shot.bullet[j].x-boss_shot.bullet[i].x);
							do{
								dx=ch.x-x;
								dy=ch.y-y;
								if(dx*dx+dy*dy>32*32){
									boss_bullet_on3(1,1,5,0,1,-20,x,y,angle+PI/2,0,1,0,0,0,0,0,1);
								}
								x+=D*cos(angle);
								y+=D*sin(angle);
							}while(x>-OUT_RANGE && y>-OUT_RANGE && x<FMX+OUT_RANGE && y<FMY+OUT_RANGE);
							//反対側にも弾を発生させる
							x=boss_shot.bullet[i].x;
							y=boss_shot.bullet[i].y;
							do{
								dx=ch.x-x;
								dy=ch.y-y;
								if(dx*dx+dy*dy>32*32){
									boss_bullet_on3(1,1,5,0,1,-20,x,y,angle+PI/2,0,1,0,0,0,300,0,1);
								}
								x-=D*cos(angle);
								y-=D*sin(angle);
							}while(x>-OUT_RANGE && y>-OUT_RANGE && x<FMX+OUT_RANGE && y<FMY+OUT_RANGE);
						}
					}
				}
				if(boss_shot.bullet[i].cnt==90){
					boss_shot.bullet[i].cnt=0;
					boss_shot.bullet[i].state=3;
				}
				break;
			case 3:
				boss_shot.bullet[i].size-=1/60.0;
				if(boss_shot.bullet[i].cnt==60){
					boss_shot.bullet[i].flag=0;
				}
				break;
			}
		}
	}
}

Re: 弾幕の作成について

Posted: 2011年10月09日(日) 19:09
by クラバック
ありがとうございます。助かりました・・・!弾の配置はcos(angle),sin(angle)で指定すればいいんですね・・・成る程、幅をマクロで指定やれば、変更も容易ですし、綺麗に描けますね。有難うございました。