ボス弾幕について

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

ボス弾幕について

#1

投稿記事 by yrao » 16年前

おはようございます。
プログラミングの館のプロジェクトを使ってゲーム作りを勉強しています。

作りたいボス段幕が二つあるのですが、実装方法が分かりません。
どなたかアドバイス頂ければ幸いです。

~一つ目~

①自機の場所に沿うように弾を配置する。
弾は配置されたまま消えない。(東方だと、地霊殿2面のパルスィの「グリーンアイドモンスター」のような感じです。)
※いきなり自機の場所に弾が置かれるとまずいので、画面左上又は右上から配置を始たいと思っています。
②一定時間配置したら、配置されている弾を自機の方へ向かわせる。


①②を繰り返す。



~二つ目~

発射された弾(弾A)が画面外に出たら、
ゲーム画面とゲームボードの境界 と 弾Aの軌道 との交点から弾(弾B)を発射する。
(説明下手ですね;
弾が画面外に出た地点から弾を吹き出させる
ということです。)
※弾Bが画面外に出ても、弾Bは発射されない。

弾Aをどのように発射するかは具体的には決めていないのですが、とりあえず自機狙い(1way)で実装してみようと思っています。
弾Bは、ボスに向かうように発射で、発射角度、発射速度に一定のばらつきがあるものです。




よろしくお願いします。

エル

Re:ボス弾幕について

#2

投稿記事 by エル » 16年前

自分も初心者なんですが、弾Aの処理に画面に消えたに弾Bの処理が行われる用にしたらダメなんですかね?
弾Bの座標を弾Aと一緒にしてあげたら可能だと思うのですが。
余計な事でしたらすみません。

nayo

Re:ボス弾幕について

#3

投稿記事 by nayo » 16年前

一つ目はたしか龍神録のボスにはアシストが用意されていたので
ボスのアシストを利用して毎フレーム自機方向を計算し、移動させてあげて
何フレームかに一回アシスト座標からx,y座標それぞれ±乱数値の位置に弾を配置し、
アシストのカウントが一定カウントになったら全弾と自機の角度を求め、速度を与えて移動させれば良いと思います
無かったらすみません

二つ目については新しく弾Bを発射するのではなく弾Aが画面外に来たらボスへの方向を求めて
その方向±乱数角度方向、最低速度+乱数速度を与えて、もし違う弾にしたいのならば画像も変え、
一度画面外に出たというフラグを用意するか、画像が変わっていたならば画面外に出てもこの処理を行わない、
とすればできそうな気がします

…分かり辛いですね

TRUTH

Re:ボス弾幕について

#4

投稿記事 by TRUTH » 16年前

こんにちはー。

1つ目はnayo様と同じアイデアです。


2つ目は新しい弾を登録する方です。
弾Aが消えそうになった瞬間(画面から出た時)、弾AのXY座標とangleを取得し
それを元に弾Bを作ります。初期座標はXY座標、angleを微調整して放ちます。
最後に弾Aのフラグを消してしまえば、実装できるのではないかと思います。
弾Aと弾Bの区別は状態ので区別できると思います。

yrao

Re:ボス弾幕について

#5

投稿記事 by yrao » 16年前

アドバイスして下さった方々、ありがとうございます。



一つ目の方から作り始めているのですが、
・アシストに毎フレーム自機の座標を所得させる処理
・一定時間経った後、弾にスピードを与え自機に向かって飛ばす処理

が上手く出来ずに悩んでいます。
どのような処理を書けばよいのでしょうか。

nayo

Re:ボス弾幕について

#6

投稿記事 by nayo » 16年前

・アシストに毎フレーム自機の座標を取得させるにてついて
自機狙いの弾は作ったことがありますか?
atan2関数を使って弾の座標と自機の座標から角度を求めていたはずです
それを応用して毎フレーム利用するだけです

・一定時間経った後、弾にスピードを与え自機に向かって飛ばす処理について
弾幕を処理している関数内で
if( アシストのカウントがある値なら ){
	for( 弾の総数分ループ ){
		if( もし弾が出現しているなら ){
			弾の速度を与える、自機方向への角度を求める、その他必要な処理
		}
	}
}
上記のような感じできないでしょうか

yrao

Re:ボス弾幕について

#7

投稿記事 by yrao » 16年前

おかげさまでアシストに自機を追いかけさせる事ができました。
ありがとうございます。
 
現在、以下のようにプログラムを書いているのですが、
一定時間経った後に、全弾自機に向かって飛んでくるというのがうまくできず、弾が動かない状態です。
どこが問題なのでしょうか。
 
(弾幕発射とアシストの制御は、龍神録プログラミングの支館様にかかれていたものを参考にしています。)


void boss_shot_bulletH014(){
int i, t = boss_shot.cnt;


if( t%700 == 0 ){//アシスト作成.700カウントで1セット
assist_way(boss.x, boss.y, 1, PI/2, 0, 5, 0, 0, 0, 0);
} //↑真下にアシストを放出

if(t%700 == 500)//500カウントでアシストを消す
delete_boss_assist(1); //sate=1のアシストがあれば削除

for(i=0;i<BOSS_ASSIST_MAX;i++){
if(boss_shot.assist.flag>0){
int sate = boss_shot.assist.state;
double x = boss_shot.assist.x;
double y = boss_shot.assist.y;

switch(sate){
case 0:
if( t%700 >= 20 && t%700 < 80 ){//20カウント~80カウントはアシストを止める
boss_shot.assist.spd = 0;
boss_shot.assist.state = 1;
}
break;
case 1:
if( t%700 >= 80 && t%700 <= 500 && t%3 == 0 )//80カウント~500カウントまで
boss_shot.assist.spd = 1.4; //アシストは自機追尾する
boss_shot.assist.angle = bossatan4(i,ch.x,ch.y);
bullet_way(x+rang(40), y+rang(40), 1, 0, 0, 0.0, 10, 3+rang(3), 0, 0);//アシストの軌跡に弾配置
break;
case 2 ://(この部分がうまくいきません)
if( t%700 > 550 )//550カウントしたら全弾を自機に飛ばす
boss_shot.bullet.spd = 5.0;
boss_shot.bullet.angle = atan2(boss_shot.bullet[i].y-ch.y,boss_shot.bullet[i].x-ch.x);


default :
break;
}
}
}
}

Tatu

Re:ボス弾幕について

#8

投稿記事 by Tatu » 16年前

書いてあるコードのうまくいっていない部分は
まず、if(t%700 > 550)ではboss_shot.bullet.angleが
1フレームごとに更新されてしまうのでif(t%700==550)に変更する。

boss_shot.bullet.angle=atan2(boss_shot.bullet.y-ch.y,boss_shot.bullet.x-ch.x)
atan2(y,x)はx軸正の方向とベクトル(x,y)の方向がなす角度を返すので、
これでは角度が自機から弾への方向になってしまい、弾が自機から遠ざかるように動いてしまう。
そのため、引数をch.y-boss_shot.bullet.y,ch.x-boss_shot.bullet.xに変更すればよい。
boss_shot.bullet.angle=bossatan3(i,ch.x,ch.y);とかいてもよい。



あと、弾幕のコードを書いてみました。
一つ目はアシストに自機を追尾させながら弾を置き、
配置された弾は置かれて一定時間後に自機の方向に飛んでくる弾幕で、
二つ目はパルシィの「丑の刻参り」のような弾幕です。

//弾発射用関数
void boss_bullet_on(int way,int knd,int col,double x,double y,double b_angle,double d_angle,double spd,int state,int till,int eff=0,int sflag=1){
    int i,k;
    for(i=0;i<way;i++){
        if((k=search_boss_shot())!=-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].flag    = 1;
            boss_shot.bullet[k].cnt     = 0;
            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;//スピード
            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_bulletT062(){
    int i,t=boss_shot.cnt;
    //アシストを出す
    if(t==0){
        boss_shot.assist[0].flag  = 1;
        boss_shot.assist[0].cnt   = 0;
        boss_shot.assist[0].knd   = 0;
        boss_shot.assist[0].col   = 0;
        boss_shot.assist[0].x     = 0;
        boss_shot.assist[0].y     = 0;
        boss_shot.assist[0].angle = 0;
        boss_shot.assist[0].spd   = 2.5;
        boss_shot.assist[0].state = 0;
        boss_shot.assist[0].till  = 0;
        boss_shot.assist[0].eff   = 0;
        se_flag[0]=1;
    }
    //アシストは常に自機を追いながら弾を配置する
    boss_shot.assist[0].angle=atan2(ch.y-boss_shot.assist[0].y,ch.x-boss_shot.assist[0].x);
    if(t%5==0){
        boss_bullet_on(1,1,1,boss_shot.assist[0].x+rang(64),boss_shot.assist[0].y+rang(64),0,0,0,1,0);
        boss_bullet_on(1,7,0,boss_shot.assist[0].x+rang(64),boss_shot.assist[0].y+rang(64),0,0,0,1,0);
    }
    for(i=0;i<BOSS_BULLET_MAX;i++){
        //配置された弾は一定時間後に自機の方向に動き出す
        if(boss_shot.bullet.flag==1 && boss_shot.bullet.state==1){
            if(boss_shot.bullet.cnt==300){
                boss_shot.bullet[i].angle=bossatan3(i,ch.x,ch.y);
            }
            if(boss_shot.bullet[i].cnt>=300 && boss_shot.bullet[i].cnt<360){
                boss_shot.bullet[i].spd+=0.05;
            }
            if(boss_shot.bullet[i].cnt==360) boss_shot.bullet[i].state=0;
        }
    }
}

void boss_shot_bulletT063(){
    int i,t=boss_shot.cnt%150;
    if(boss_shot.cnt==0) input_phy_pos(FMX/2,FMY/2,30);
    //角度を記憶させる
    if(t==30) boss_shot.base_angle[0]=bossatan2();
    if(t>=30 && t<150 && t%8==0){
        for(i=0;i<6;i++){
            boss_bullet_on(1,8,4,boss.x,boss.y,boss_shot.base_angle[0]+i*PI2/6+rang(PI/24),0,2,1,0);
        }
    }
    for(i=0;i<BOSS_BULLET_MAX;i++){
        if(boss_shot.bullet[i].flag>0 && boss_shot.bullet[i].state==1){
            boss_shot.bullet[i].spd+=0.02;
            //画面枠についたら新しく弾を発射し、消去する
            if(boss_shot.bullet[i].x<0 || boss_shot.bullet[i].x>FMX || boss_shot.bullet[i].y<0 || boss_shot.bullet[i].y>FMY){
                boss_bullet_on(1,1,2,boss_shot.bullet[i].x,boss_shot.bullet[i].y,bossatan3(i,boss.x,boss.y)+rang(PI/4),0,1,0,0,1,0);
                boss_shot.bullet[i].flag=0;
            }
        }
    }
}

yrao

Re:ボス弾幕について

#9

投稿記事 by yrao » 16年前

Tatuさんありがとうございます。
作っていただいたソースコードを参考にして、もう一度作り直してみたところ、無事実装することができました。
二つ目の弾幕のほうもありがとうございます。助かります。
 
 
アドバイスをしていただいた方々、本当にありがとうございましたm(_ _)m
 

閉鎖

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