お久しぶりです。いつも親切なお答えを下さりありがとうございます。
前々からきになっていたのですが、東方の封獣ぬえの弾幕はどうつくるのか?がきになりました。
特に、弾幕キメラと鵺的スネークショーの二つの作り方を教えてください。
弾幕キメラは、レーザーが弾に、弾がレーザーになるという弾幕はどうつくればいいのか、
鵺的スネークショーは、あのつながった緑色のレーザー(?)はどう作ればいいのか教えてください。
あのレーザーはこの掲示板で、ほかの方が質問されているトピックをみたとき、
弾をつなげて作っていると書いてありましたが、
詳しく教えてください。
もしつなげたとしてもなぜあのようなつなぎ目が見えない、レーザーになるのでしょうか?
またレーザーに使う一つ一つの弾の画像はどう書けばいいでしょうか?
それと、じっくり見ると先のほうが割と白く後ろのほうは緑色になっていました。
どうすればいいでしょうか?
質問ばかりで申し訳ないですがどうかお願いします。
ぬえの弾幕のつくりかた
Re:ぬえの弾幕のつくりかた
弾幕キメラのような弾幕の関数を作ってみました。
レーザーと弾の切り替えの代わりに
弾の種類boss_shot.bullet.kndを変更しています。
/*
弾発射関数
way個のknd番目の種類のcol番目の色の弾を座標(x,y)からb_angleの方向を中心に発射角度をそれぞれd_angleだけずらし、
(ただし、偶数弾などb_angleの方向に撃ちたくないときはb_angleの値をd_angle/2.0だけ大きくする)
angle方向に速度をspd,vxの値をvx,vyの値をvyに(vx,vyはそのままでは機能しない),
状態をstateにしてとばす。この弾はtillまで画面外に出ても消えず、
effが1ならば加算ブレンドして描画され、sflagが1ならば発射音がなる。
*/
void boss_bullet_on(int way,int knd,int col,int cnt,double x,double y,double b_angle,double d_angle,double spd,double vx,double vy,int state,int till,int eff=0,int sflag=1){
int i=0,k;
for(i=0;i<way;i++){
if((k=search_boss_shot())!=-1){
boss_shot.bullet[k].flag = 1;
boss_shot.bullet[k].knd = knd;//弾の種類
if(knd==7) boss_shot.bullet[k].kaiten=1;
else boss_shot.bullet[k].kaiten=0;
boss_shot.bullet[k].col = col;//弾の色
boss_shot.bullet[k].cnt = cnt;
boss_shot.bullet[k].x = x;//座標
boss_shot.bullet[k].y = y;
boss_shot.bullet[k].angle = b_angle+d_angle*(i - way/2);//角度:bが基準、dが間隔
boss_shot.bullet[k].spd = spd;//angle方向のスピード
boss_shot.bullet[k].vx = vx;//x方向の速度
boss_shot.bullet[k].vy = vy;//y方向の速度
boss_shot.bullet[k].state = state;//弾の状態
boss_shot.bullet[k].till = till;//弾が画面外に出ても消えない時間
boss_shot.bullet[k].eff = eff;
if(sflag==1)se_flag[0]=1;
}
}
}
void boss_shot_bulletT131(){
int i,t=boss_shot.cnt%180;
double x,y,r,angle,angle2;
if(boss_shot.cnt==0){
boss.x=FMX/2;
boss.y=FMY/2-40;
}
if(t==0){
boss_shot.base_angle[0]=bossatan2();
}
if(t<60){
if((boss_shot.cnt/180)%2==0){
if(t%12==0){
boss_bullet_on(16,8,1,0,boss.x,boss.y,boss_shot.base_angle[0],PI2/16,2,0,0,1,1200,1,1);
}
else if(t%12==6){
boss_bullet_on(16,8,1,0,boss.x,boss.y,boss_shot.base_angle[0],PI2/16,2,0,0,2,1200,1,1);
}
}
else{
if(t%12==0){
boss_bullet_on(16,8,1,0,boss.x,boss.y,boss_shot.base_angle[0]+PI2/32,PI2/16,2,0,0,1,1200,1,1);
}
else if(t%12==6){
boss_bullet_on(16,8,1,0,boss.x,boss.y,boss_shot.base_angle[0]+PI2/32,PI2/16,2,0,0,2,1200,1,1);
}
}
}
if(t==60){
for(i=0;i<BOSS_BULLET_MAX;i++){
if(boss_shot.bullet.flag == 1 && (boss_shot.bullet.state == 1 || boss_shot.bullet.state == 2) ){
boss_shot.bullet.knd=1;
boss_shot.bullet.spd=0;
}
}
}
if(t>=60){
for(i=0;i<BOSS_BULLET_MAX;i++){
if(boss_shot.bullet.flag ==1){
switch(boss_shot.bullet.state){
case 1:
x=boss_shot.bullet.x-boss.x;
y=boss_shot.bullet.y-boss.y;
r=sqrt(x*x+y*y);
angle=boss_shot.bullet[i].angle;
if(t<120){
angle2=PI/19200*(t-60);
}
else
angle2=PI/19200*(180-t);
boss_shot.bullet[i].angle=angle-angle2;
boss_shot.bullet[i].x=boss.x+r*cos(boss_shot.bullet[i].angle);
boss_shot.bullet[i].y=boss.y+r*sin(boss_shot.bullet[i].angle);
break;
case 2:
x=boss_shot.bullet[i].x-boss.x;
y=boss_shot.bullet[i].y-boss.y;
r=sqrt(x*x+y*y);
angle=boss_shot.bullet[i].angle;
if(t<120){
angle2=PI/19200*(t-60);
}
else
angle2=PI/19200*(180-t);
boss_shot.bullet[i].angle=angle+angle2;
boss_shot.bullet[i].x=boss.x+r*cos(boss_shot.bullet[i].angle);
boss_shot.bullet[i].y=boss.y+r*sin(boss_shot.bullet[i].angle);
break;
}
}
}
}
if(t==179){
for(i=0;i<BOSS_BULLET_MAX;i++){
if(boss_shot.bullet[i].flag == 1 && (boss_shot.bullet[i].state == 1 || boss_shot.bullet[i].state == 2)){
boss_shot.bullet[i].knd=8;
boss_shot.bullet[i].spd=2;
}
}
}
}
レーザーと弾の切り替えの代わりに
弾の種類boss_shot.bullet.kndを変更しています。
/*
弾発射関数
way個のknd番目の種類のcol番目の色の弾を座標(x,y)からb_angleの方向を中心に発射角度をそれぞれd_angleだけずらし、
(ただし、偶数弾などb_angleの方向に撃ちたくないときはb_angleの値をd_angle/2.0だけ大きくする)
angle方向に速度をspd,vxの値をvx,vyの値をvyに(vx,vyはそのままでは機能しない),
状態をstateにしてとばす。この弾はtillまで画面外に出ても消えず、
effが1ならば加算ブレンドして描画され、sflagが1ならば発射音がなる。
*/
void boss_bullet_on(int way,int knd,int col,int cnt,double x,double y,double b_angle,double d_angle,double spd,double vx,double vy,int state,int till,int eff=0,int sflag=1){
int i=0,k;
for(i=0;i<way;i++){
if((k=search_boss_shot())!=-1){
boss_shot.bullet[k].flag = 1;
boss_shot.bullet[k].knd = knd;//弾の種類
if(knd==7) boss_shot.bullet[k].kaiten=1;
else boss_shot.bullet[k].kaiten=0;
boss_shot.bullet[k].col = col;//弾の色
boss_shot.bullet[k].cnt = cnt;
boss_shot.bullet[k].x = x;//座標
boss_shot.bullet[k].y = y;
boss_shot.bullet[k].angle = b_angle+d_angle*(i - way/2);//角度:bが基準、dが間隔
boss_shot.bullet[k].spd = spd;//angle方向のスピード
boss_shot.bullet[k].vx = vx;//x方向の速度
boss_shot.bullet[k].vy = vy;//y方向の速度
boss_shot.bullet[k].state = state;//弾の状態
boss_shot.bullet[k].till = till;//弾が画面外に出ても消えない時間
boss_shot.bullet[k].eff = eff;
if(sflag==1)se_flag[0]=1;
}
}
}
void boss_shot_bulletT131(){
int i,t=boss_shot.cnt%180;
double x,y,r,angle,angle2;
if(boss_shot.cnt==0){
boss.x=FMX/2;
boss.y=FMY/2-40;
}
if(t==0){
boss_shot.base_angle[0]=bossatan2();
}
if(t<60){
if((boss_shot.cnt/180)%2==0){
if(t%12==0){
boss_bullet_on(16,8,1,0,boss.x,boss.y,boss_shot.base_angle[0],PI2/16,2,0,0,1,1200,1,1);
}
else if(t%12==6){
boss_bullet_on(16,8,1,0,boss.x,boss.y,boss_shot.base_angle[0],PI2/16,2,0,0,2,1200,1,1);
}
}
else{
if(t%12==0){
boss_bullet_on(16,8,1,0,boss.x,boss.y,boss_shot.base_angle[0]+PI2/32,PI2/16,2,0,0,1,1200,1,1);
}
else if(t%12==6){
boss_bullet_on(16,8,1,0,boss.x,boss.y,boss_shot.base_angle[0]+PI2/32,PI2/16,2,0,0,2,1200,1,1);
}
}
}
if(t==60){
for(i=0;i<BOSS_BULLET_MAX;i++){
if(boss_shot.bullet.flag == 1 && (boss_shot.bullet.state == 1 || boss_shot.bullet.state == 2) ){
boss_shot.bullet.knd=1;
boss_shot.bullet.spd=0;
}
}
}
if(t>=60){
for(i=0;i<BOSS_BULLET_MAX;i++){
if(boss_shot.bullet.flag ==1){
switch(boss_shot.bullet.state){
case 1:
x=boss_shot.bullet.x-boss.x;
y=boss_shot.bullet.y-boss.y;
r=sqrt(x*x+y*y);
angle=boss_shot.bullet[i].angle;
if(t<120){
angle2=PI/19200*(t-60);
}
else
angle2=PI/19200*(180-t);
boss_shot.bullet[i].angle=angle-angle2;
boss_shot.bullet[i].x=boss.x+r*cos(boss_shot.bullet[i].angle);
boss_shot.bullet[i].y=boss.y+r*sin(boss_shot.bullet[i].angle);
break;
case 2:
x=boss_shot.bullet[i].x-boss.x;
y=boss_shot.bullet[i].y-boss.y;
r=sqrt(x*x+y*y);
angle=boss_shot.bullet[i].angle;
if(t<120){
angle2=PI/19200*(t-60);
}
else
angle2=PI/19200*(180-t);
boss_shot.bullet[i].angle=angle+angle2;
boss_shot.bullet[i].x=boss.x+r*cos(boss_shot.bullet[i].angle);
boss_shot.bullet[i].y=boss.y+r*sin(boss_shot.bullet[i].angle);
break;
}
}
}
}
if(t==179){
for(i=0;i<BOSS_BULLET_MAX;i++){
if(boss_shot.bullet[i].flag == 1 && (boss_shot.bullet[i].state == 1 || boss_shot.bullet[i].state == 2)){
boss_shot.bullet[i].knd=8;
boss_shot.bullet[i].spd=2;
}
}
}
}
Re:ぬえの弾幕のつくりかた
鵺的スネークショーのような弾幕関数です。
boss_shot.bullet.effが1の弾を
重ねることで先端を白くしました。
void boss_shot_bulletT133(){
int i,t=boss_shot.cnt%180;
if(t==0){
boss_shot.base_angle[0]=bossatan2()+rang(PI/256);
}
if(t<30 && t%3==0){
if((boss_shot.cnt/180)%2==0){
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0],PI2/32,2,0,0,1,0,1,1);
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0]+PI2/64,PI2/32,2,0,0,2,0,1,1);
if(t<15){
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0],PI2/32,2,0,0,1,0,1,1);
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0]+PI2/64,PI2/32,2,0,0,2,0,1,1);
}
}
else{
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0],PI2/32,2,0,0,3,0,1,1);
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0]+PI2/64,PI2/32,2,0,0,4,0,1,1);
if(t<15){
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0],PI2/32,2,0,0,3,0,1,1);
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0]+PI2/64,PI2/32,2,0,0,4,0,1,1);
}
}
}
for(i=0;i<BOSS_BULLET_MAX;i++){
if(boss_shot.bullet.flag == 1){
switch(boss_shot.bullet.state){
case 1:
boss_shot.bullet.x-=sin(boss_shot.bullet.angle)*PI/3*cos(PI2/48*boss_shot.bullet.cnt);
boss_shot.bullet.y+=cos(boss_shot.bullet.angle)*PI/3*cos(PI2/48*boss_shot.bullet.cnt);
break;
case 2:
if(boss_shot.bullet.cnt>=96 && boss_shot.bullet[i].cnt<192){
boss_shot.bullet[i].angle+=PI2/96;
}
else{
boss_shot.bullet[i].x-=sin(boss_shot.bullet[i].angle)*PI/3*cos(PI2/48*boss_shot.bullet[i].cnt);
boss_shot.bullet[i].y+=cos(boss_shot.bullet[i].angle)*PI/3*cos(PI2/48*boss_shot.bullet[i].cnt);
}
break;
case 3:
boss_shot.bullet[i].x+=sin(boss_shot.bullet[i].angle)*PI/3*cos(PI2/48*boss_shot.bullet[i].cnt);
boss_shot.bullet[i].y-=cos(boss_shot.bullet[i].angle)*PI/3*cos(PI2/48*boss_shot.bullet[i].cnt);
break;
case 4:
if(boss_shot.bullet[i].cnt>=96 && boss_shot.bullet[i].cnt<192){
boss_shot.bullet[i].angle-=PI2/96;
}
else{
boss_shot.bullet[i].x+=sin(boss_shot.bullet[i].angle)*PI/3*cos(PI2/48*boss_shot.bullet[i].cnt);
boss_shot.bullet[i].y-=cos(boss_shot.bullet[i].angle)*PI/3*cos(PI2/48*boss_shot.bullet[i].cnt);
}
break;
}
}
}
}
boss_shot.bullet.effが1の弾を
重ねることで先端を白くしました。
void boss_shot_bulletT133(){
int i,t=boss_shot.cnt%180;
if(t==0){
boss_shot.base_angle[0]=bossatan2()+rang(PI/256);
}
if(t<30 && t%3==0){
if((boss_shot.cnt/180)%2==0){
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0],PI2/32,2,0,0,1,0,1,1);
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0]+PI2/64,PI2/32,2,0,0,2,0,1,1);
if(t<15){
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0],PI2/32,2,0,0,1,0,1,1);
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0]+PI2/64,PI2/32,2,0,0,2,0,1,1);
}
}
else{
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0],PI2/32,2,0,0,3,0,1,1);
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0]+PI2/64,PI2/32,2,0,0,4,0,1,1);
if(t<15){
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0],PI2/32,2,0,0,3,0,1,1);
boss_bullet_on(32,10,3,0,boss.x,boss.y,boss_shot.base_angle[0]+PI2/64,PI2/32,2,0,0,4,0,1,1);
}
}
}
for(i=0;i<BOSS_BULLET_MAX;i++){
if(boss_shot.bullet.flag == 1){
switch(boss_shot.bullet.state){
case 1:
boss_shot.bullet.x-=sin(boss_shot.bullet.angle)*PI/3*cos(PI2/48*boss_shot.bullet.cnt);
boss_shot.bullet.y+=cos(boss_shot.bullet.angle)*PI/3*cos(PI2/48*boss_shot.bullet.cnt);
break;
case 2:
if(boss_shot.bullet.cnt>=96 && boss_shot.bullet[i].cnt<192){
boss_shot.bullet[i].angle+=PI2/96;
}
else{
boss_shot.bullet[i].x-=sin(boss_shot.bullet[i].angle)*PI/3*cos(PI2/48*boss_shot.bullet[i].cnt);
boss_shot.bullet[i].y+=cos(boss_shot.bullet[i].angle)*PI/3*cos(PI2/48*boss_shot.bullet[i].cnt);
}
break;
case 3:
boss_shot.bullet[i].x+=sin(boss_shot.bullet[i].angle)*PI/3*cos(PI2/48*boss_shot.bullet[i].cnt);
boss_shot.bullet[i].y-=cos(boss_shot.bullet[i].angle)*PI/3*cos(PI2/48*boss_shot.bullet[i].cnt);
break;
case 4:
if(boss_shot.bullet[i].cnt>=96 && boss_shot.bullet[i].cnt<192){
boss_shot.bullet[i].angle-=PI2/96;
}
else{
boss_shot.bullet[i].x+=sin(boss_shot.bullet[i].angle)*PI/3*cos(PI2/48*boss_shot.bullet[i].cnt);
boss_shot.bullet[i].y-=cos(boss_shot.bullet[i].angle)*PI/3*cos(PI2/48*boss_shot.bullet[i].cnt);
}
break;
}
}
}
}
Re:ぬえの弾幕のつくりかた
ありがとうございます。
わかりましたが、
スネークショーの弾を東方のように弾と弾との間がみえず、とてもきれいに、
するにはどうすればいいでしょうか?
追加、
>スネークショーの弾を東方のように弾と弾との間がみえず、とてもきれいに、
>するにはどうすればいいでしょうか?
えっとわかりやすくいうと、弾の画像はどうすればいいでしょうか・・・という質問です。
ブレンドモードを使えば、きれいにできますか?それは知っていたのですが、
先端だけエフェクトフラグというのは思いつきませんでした・・・
ご丁寧にありがとうございます。

わかりましたが、
スネークショーの弾を東方のように弾と弾との間がみえず、とてもきれいに、
するにはどうすればいいでしょうか?
追加、
>スネークショーの弾を東方のように弾と弾との間がみえず、とてもきれいに、
>するにはどうすればいいでしょうか?
えっとわかりやすくいうと、弾の画像はどうすればいいでしょうか・・・という質問です。
ブレンドモードを使えば、きれいにできますか?それは知っていたのですが、
先端だけエフェクトフラグというのは思いつきませんでした・・・
ご丁寧にありがとうございます。
