



![]()
45 章
前回まではボスの弾幕は終わりが無く、何度も弾幕を次へ繰り返していくとポインタエラーになっていました。
今回はちゃんと終わりを作り、中ボス、ラスボスを作りましょう。
中ボスラスボスといっても、同じ敵ですが、龍神録や東方は中間に1度出てきて、やられて引っ込んだあと、
ラストで本格的にもう一度出現します。それを実装してみましょう。
boss構造体にdanmaku_num[2]を追加します。
中ボスでいくつ弾幕を出し、ラスボスでいくつ弾幕を出すかセットするための変数です。
次の弾幕へさしかかるとき、現在の弾幕数がこの数字と一致したら倒すということにします。
また今回は、画面をドン!と揺らすdn処理を一つのファイルに纏めましたので、そちらもあわせてご覧下さい。
dnの登録にはenter_dnを使用します。
---- struct.h の以下の部分を変更 ----
//ボスの情報
typedef struct{
//フラグ、カウンタ、種類、待機時間、状態、弾幕終了までのカウンタ、後ろの羽衣、表示フラグ
int flag,cnt,knd,wtime,state,endtime,hagoromo,graph_flag;
//HP,最大HP
int hp,hp_max;
//出現カウンタ数、各弾幕のHP、背景の種類、中ボス-ラスボスの弾幕数(45)
int appear_count[2],set_hp[DANMAKU_MAX],back_knd[DANMAKU_MAX],danmaku_num[2];
//座標
double x,y,dx,dy,ang,spd;
//物理移動のための変数
phy_t phy;
}boss_t;
---- function.h に以下を追加 ----
//dn.cpp
GLOBAL void enter_dn(int size,int time);
---- define.h の以下を変更
#define BOSS_POS_Y (FMY/4)
---- func.hの以下を変更 ----
void (*boss_shot_bullet[DANMAKU_MAX])() =
{
boss_shot_bulletH000,
boss_shot_bulletH001,
boss_shot_bulletH000,
boss_shot_bulletH009,
boss_shot_bulletH000,
};
---- ini.cpp の 以下を変更 ----
int back_knd[DANMAKU_MAX]={//背景の種類
0,1,0,1,//0は通常 1はスペル用
};
//ゲームの初期化
void ini(){
stage_count=1;
memset(&ch,0,sizeof(ch_t));
memset(enemy,0,sizeof(enemy_t)*ENEMY_MAX);
memset(lazer,0,sizeof(lazer_t)*LAZER_MAX);
memset(enemy_order,0,sizeof(enemy_order_t)*ENEMY_ORDER_MAX);
memset(shot,0,sizeof(shot_t)*SHOT_MAX);
memset(cshot,0,sizeof(cshot_t)*CSHOT_MAX);
memset(effect,0,sizeof(effect_t)*EFFECT_MAX);
memset(del_effect,0,sizeof(del_effect_t)*DEL_EFFECT_MAX);
memset(&bom,0,sizeof(bom_t));
memset(&bright_set,0,sizeof(bright_set_t));
memset(&dn,0,sizeof(dn_t));
memset(&boss,0,sizeof(boss_t));
memset(child,0,sizeof(child_t)*CHILD_MAX);
memset(&stage_title,0,sizeof(stage_title_t));
memset(item,0,sizeof(item_t)*ITEM_MAX);
ch.x=FMX/2;
ch.y=FMY*3/4;
ch.power=0;//初期パワー(41)
ch.num=5;//初期残機数(41)
stage_title.appear_cnt=stage_title_count[stage];
/*弾幕それぞれの設定。後々きちんと設定しましょう。*/
boss.appear_count[0]=800;//中ボスが出現する時刻(42)
boss.appear_count[1]=1100;//最後ボスが出現する時刻(44)
boss.danmaku_num[0]=1;//中ボスが何個目までの弾幕を出すか
boss.danmaku_num[1]=3;//最後に出るボスが何個目までの弾幕を出すか
for(int i=0;i<DANMAKU_MAX;i++){//弾幕それぞれのHP
boss.set_hp[i]=1000;
boss.hp_max=1000;
}
for(int i=0;i<DANMAKU_MAX;i++)//弾幕それぞれの背景の種類
boss.back_knd[i]=back_knd[i];
/*ここまで*/
bright_set.brt=255;//初期輝度は最大
}
---- effect.cpp の先頭に 以下を追加 ----
extern void dn_calc();
---- effect.cpp の calc_effect()の以下を変更 ----
case 1://ボムのエフェクト
//スピード計算
if(effect[i].cnt<60)
effect[i].spd-=(0.2+effect[i].cnt*effect[i].cnt/3000.0);
if(effect[i].cnt==60){
effect[i].spd=0;
se_flag[15]=1;
enter_dn(11,20);//(45)
}
//明るさと大きさ計算
effect[i].r+=0.015;
if(effect[i].cnt<51)
effect[i].brt+=5;
if(effect[i].cnt>=60){
effect[i].r+=0.04;
effect[i].brt-=255/30.0;
}
//カウントアップと消去計算
effect[i].cnt++;
if(effect[i].cnt>=90)
effect[i].flag=0;
break;
---- dn.cpp を新たに追加し、以下を追加 ----
#include "../include/GV.h"
void enter_dn(int size, int time){
dn.flag=1;
dn.cnt=0;
dn.time=time;
dn.size=size;
}
//ドガーンとゆれる画面の処理
void dn_calc(){
if(dn.flag==1){
dn.x=(int)rang(dn.size);
dn.y=(int)rang(dn.size);
dn.cnt++;
if(dn.cnt>dn.time){//指定された時間がたつと終わる
dn.flag=0;
dn.x=0;
dn.y=0;
}
}
}
ボスが今どの種類の弾幕をうっているかはboss.kndに入っています。
これがini関数で格納したboss.danmaku_numと同じだったらボスを消します。
消す時はドガーンを言う音とエフェクトをつけてやりましょう。
boss.danmaku_num[0]は中ボスまで、[1]はラスボスまでです。
番号は0から始まりますから、中ボスでfunc.hの
void (*boss_shot_bullet[DANMAKU_MAX])()
に指定した2つ目までを中ボスで表示したいのなら1番まで中ボスで表示したいので1を指定します。
---- boss_shot.cpp の以下を変更 ----
//ボスをセット
void enter_boss(int num){
if(num==0){//中ボス開始時の時は
memset(enemy,0,sizeof(enemy_t)*ENEMY_MAX);//雑魚敵を消す
memset(shot,0,sizeof(shot_t)*SHOT_MAX);//弾幕を消す
boss.x=FMX/2;//ボスの初期座標
boss.y=-30;
if(stage_count==boss.appear_count[0])//最初なら
boss.knd=-1;//弾幕の種類
}
boss.phy.flag=1;
boss.flag=1;
boss.hagoromo=0;//扇を広げるかどうかのフラグ
boss.endtime=99*60;//残り時間
boss.state=1;//待機中状態に
boss.cnt=0;
boss.graph_flag=0;//描画フラグを戻す
boss.knd++;
boss.wtime=0;//待機時間を初期化
input_phy(60);//60カウントかけて物理的計算で定位置に戻す
}
//ボスの弾幕メイン
void boss_shot_main(){
if((stage_count==boss.appear_count[0] || stage_count==boss.appear_count[1])
&& boss.flag==0){//開始時間なら
enter_boss(0);//開始
}
if(boss.flag==0)//ボスが登録されて無ければ戻る
return;
calc_boss();
if(boss.phy.flag==1)//物理演算移動オンなら
calc_phy();//物理計算を
if(boss.state==2 && (boss.hp<=0 || boss.endtime<=0)){//弾幕中で体力が無くなったら
se_flag[1]=1;//敵のピチュリ音
se_flag[11]=1;
input_phy(30);//30カウントで定位置に戻す
memset(&boss_shot,0,sizeof(boss_shot_t));//ボスの弾幕情報を初期化
memset(&lazer,0,sizeof(lazer_t)*LAZER_MAX);//ボスのレーザー情報を初期化
flash.flag=0;//フラッシュを消す
if(boss.knd==boss.danmaku_num[0] || boss.knd==boss.danmaku_num[1]){//弾幕をだしきったら
boss.flag=0;//消す
enter_dn(10,40);//(45)ドガーン処理
se_flag[9]=1;//ボスが死んだ音
return ;
}
else
enter_boss(1);//次の弾幕を登録
}
if(boss.state==1){//弾幕間の待機時間
waitandenter();
}
if(boss.state==2){//弾幕中なら
boss_shot_bullet[boss.knd]();//弾幕関数へ
boss_shot_calc();//弾幕計算
}
boss.cnt++;
}
実行結果
- Remical Soft -