今回はボムの話です。

またまた例によって、登録情報格納庫を作ってやり、そこに登録し、後は自動的に計算させるという感じで行います。

前の章で「エフェクト」を行う変数を用意しましたね。

前は敵の消滅エフェクトに使用しましたが、今度は同じ格納庫にボムのエフェクトを入れてみましょう。

前にも言いましたが、このエフェクトを登録する変数には何を登録してもいいのです。

エフェクトの識別番号であるkndに決めた番号をいれてやれば、その通りに計算されるようにすれば、

同じ格納庫を使えるのです。

龍神録のボムのエフェクトには、

「ピュー・・・ドン」となるエフェクトと、(これをエフェクト番号1とする)

エフェクトラインが上下左右に移動するエフェクトと、(これをエフェクト番号2とする)

キャラクタが上にスーっと移動するエフェクトがあります。(これをエフェクト番号3とする)

ボムを登録する時、このエフェクト番号にわけて登録することで、これを実現してみましょう。

まずは下準備です、。



---- struct.h に以下を追加 ----

//エフェクト
typedef struct{
	int flag,cnt,col,knd,img,eff;
	double x,y,r,ang,spd,mvang,brt;
}effect_t;
//ボムの情報
typedef struct{
        int flag,cnt,knd;
        double x,y;
}bom_t;
//画面の明るさ情報
typedef struct{
        unsigned char brt;
}bright_set_t;
//ドン!と揺れる画面の情報
typedef struct{
        int flag,cnt,time,size;
        int x,y;
}dn_t;


---- GV.h に以下を追加 ----

GLOBAL int img_eff_bom[5];      //ボムのエフェクト画像
GLOBAL bom_t bom;               //ボム
GLOBAL bright_set_t bright_set; //描画の輝度
GLOBAL dn_t dn;                 //ドンと揺れる


---- load.cpp load関数内に以下を追加 ----


        img_eff_bom[0] = LoadGraph( "../dat/img/effect/bom0.png" );
        img_eff_bom[1] = LoadGraph( "../dat/img/effect/bom1.png" );
        img_eff_bom[2] = LoadGraph( "../dat/img/char/body.png" );
        img_eff_bom[3] = LoadGraph( "../dat/img/bullet/bom_title0.png" );
        sound_se[14]=LoadSoundMem("../dat/se/bom0.wav");
        sound_se[15]=LoadSoundMem("../dat/se/bom1.wav");


---- ini.cpp の ini 関数内に以下を追加 ----

        memset(&bom,0,sizeof(bom_t));
        memset(&bright_set,0,sizeof(bright_set_t));
        memset(&dn,0,sizeof(dn_t));

        bright_set.brt=255;


---- out.cpp のout_main関数を変更 ----

//当たり判定メイン
void out_main(){
        cbom_and_enemy();
    cshot_and_enemy();
    enemyshot_and_ch();
}


---- out.cpp の以下の任意の箇所を変更 ----


//sの敵にpower食らわす
void hit_enemy(int s,int power){
    enemy[s].hp-=power;//弾の持つパワー分HPを減らす
    enemy_death_judge(s);//敵が死ぬかどうかを決める
}

//ボムと敵の処理
void cbom_and_enemy(){
    int s;
    if(bom.flag!=1)return;
    for(s=0;s<ENEMY_MAX;s++){//敵総数
        if(enemy[s].flag>0)
            hit_enemy(s,ch.power/20);//sの敵にch.power/20ほど喰らわす
    }
}

//自機ショットと敵との処理
void cshot_and_enemy(){
    int i,s;
    for(i=0;i<CSHOT_MAX;i++){//自機ショット総数
        if(cshot[i].flag>0){
            for(s=0;s<ENEMY_MAX;s++){//敵総数
                if(enemy[s].flag>0){
                    if(out_judge_cshot(i,s)){//自機ショットと敵が当たっていれば
                        cshot[i].flag=0;//その自機ショットを消す
                        hit_enemy(s,cshot[i].power);//sの敵に.powerだけ喰らわす
                    }
                }
            }
        }
    }
}


---- graph.cpp の graph_effectの赤字部分を追加 ----

void graph_effect(int knd){
        for(int i=0;i<EFFECT_MAX;i++){
                if(effect[i].flag>0 && effect[i].knd==knd){
                        if(effect[i].eff==1)//エフェクトが光エフェクトなら
                                SetDrawBlendMode( DX_BLENDMODE_ADD, effect[i].brt) ;
                        if(effect[i].eff==2)//エフェクトがαエフェクトなら
                                SetDrawBlendMode( DX_BLENDMODE_ALPHA, effect[i].brt) ;
                        DrawRotaGraphF(effect[i].x+FIELD_X+dn.x,effect[i].y+FIELD_Y+dn.y,effect[i].r,effect[i].ang,effect[i].img,TRUE);
                        if(effect[i].eff==1 || effect[i].eff==2)
                                SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 0) ;
                }
        }
}


---- graph.cpp の graph_main を変更 ----

void graph_main(){
        if(bright_set.brt!=255)SetDrawBright(bright_set.brt,bright_set.brt,bright_set.brt);

        graph_back_main();//背景描画メイン
        graph_effect(0);//敵が死ぬエフェクト
        graph_enemy();//敵の描画
        graph_cshot();//自機ショットの描画

        if(bright_set.brt!=255)SetDrawBright(255,255,255);

        graph_ch();//自機の描画

        if(bright_set.brt!=255)SetDrawBright(bright_set.brt,bright_set.brt,bright_set.brt);
        
        graph_bullet();//弾の描画

        if(bright_set.brt!=255)SetDrawBright(255,255,255);

        graph_effect(1);//ボムのエフェクト
        graph_effect(2);//ボム線のエフェクト
        graph_effect(3);//ボムキャラのエフェクト
        graph_board();//ボードの描画
}






今回は新しく構造体に

・ボムの情報を持たせるためのbom_t

・画面の明るさを設定する為のbright_set_t

・ドン!と揺れる画面の情報dn_t

の3つを用意しました。

bright_set_tで用意する変数は常に255にしておき、暗くする必要があるときに変更します。

dn_tで用意する変数は今までどおりの使い方をして登録、計算し、画面を揺らしたい時に使います。

ボムの変数は今までどおりの使い方と同じです。

下準備が終わりました。では実際にエフェクトの計算をやってみましょう。


---- effect.cpp を変更 ----

#include "../include/GV.h"

//エフェクトの登録空き番号を探す
int search_effect(){
        for(int i=0;i<EFFECT_MAX;i++){
                if(effect[i].flag==0)
                        return i;
        }
        return -1;
}

//エフェクトを計算する
void calc_effect(){
        for(int i=0;i<EFFECT_MAX;i++){
                if(effect[i].flag>0){//エフェクトが登録されていたら
                        switch(effect[i].knd){//エフェクトの種類によって分岐
                                case 0://敵の消滅エフェクト
                                        effect[i].cnt++;
                                        effect[i].r+=0.08;//エフェクトの大きさを段々大きくする
                                        if(effect[i].cnt>10)//10カウント以上になったら
                                                effect[i].brt-=25;//明るさを少なくする
                                        if(effect[i].cnt>20)//20カウント以上になったら
                                                effect[i].flag=0;//消す
                                        break;
                                case 1://ボムのエフェクト
                                        //座標計算
                                        effect[i].x+=cos(effect[i].mvang)*effect[i].spd;
                                        effect[i].y+=sin(effect[i].mvang)*effect[i].spd;
                                        //スピード計算
                                        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;
                                                dn.flag=1;
                                                dn.cnt=0;
                                                dn.size=11;
                                                dn.time=20;
                                        }
                                        //明るさと大きさ計算
                                        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;
                                case 2://ボムエフェクト(キャラ)
                                        //座標計算
                                        effect[i].x+=cos(effect[i].mvang)*effect[i].spd;
                                        effect[i].y+=sin(effect[i].mvang)*effect[i].spd;
                                        //明るさ計算
                                        if(effect[i].cnt<51)
                                                effect[i].brt+=4;
                                        if(effect[i].cnt>130-51)
                                                effect[i].brt-=4;
                                        //カウントアップと消去計算
                                        effect[i].cnt++;
                                        if(effect[i].cnt>=130)
                                                effect[i].flag=0;
                                        break;
                                case 3://ボムのエフェクト(ライン)
                                        //座標計算
                                        effect[i].x+=cos(effect[i].mvang)*effect[i].spd;
                                        effect[i].y+=sin(effect[i].mvang)*effect[i].spd;
                                        //明るさ計算
                                        if(effect[i].cnt<51)
                                                effect[i].brt+=2;
                                        if(effect[i].cnt>130-51)
                                                effect[i].brt-=2;
                                        //カウントアップと消去計算
                                        effect[i].cnt++;
                                        if(effect[i].cnt>=130)
                                                effect[i].flag=0;
                                        break;                          
                                default:
                                        printfDx("effect設定エラー\n");
                                        break;
                        }
                }
        }
}

//消滅エフェクトの登録空き番号を探す
int search_del_effect(){
        for(int i=0;i<DEL_EFFECT_MAX;i++){
                if(del_effect[i].flag==0)
                        return i;
        }
        return -1;
}

//消滅エフェクトを登録する
void enter_del_effect(int s){
        int k=search_del_effect();
        if(k!=-1){
                del_effect[k].flag=1;//フラグを立てる
                del_effect[k].cnt=0;
                del_effect[k].col=enemy[s].back_col;//敵の背景色を消滅色に設定する
                del_effect[k].x=enemy[s].x;//敵の座標を消滅位置にセット
                del_effect[k].y=enemy[s].y;
        }
}

//消滅エフェクトを計算・エフェクトを登録する
void calc_del_effect(){
        int k;
        for(int i=0;i<DEL_EFFECT_MAX;i++){
                if(del_effect[i].flag>0){
                        if(del_effect[i].cnt%2==0){// 1/30秒ずつセット
                                if((k=search_effect())!=-1){//空き番号検索
                                        memset(&effect[k],0,sizeof(effect_t));//初期化
                                        effect[k].flag=1;//フラグを立てる
                                        effect[k].brt=255;//輝度を最大値に
                                        effect[k].ang=rang(PI);//角度をランダムに
                                        effect[k].col=del_effect[i].col;//色をセット
                                        effect[k].eff=1;//1は光エフェクト。光エフェクトにセットする
                                        effect[k].img=img_del_effect[effect[k].col];//消滅する画像をセット
                                        effect[k].knd=0;//エフェクトの種類は0番(消滅エフェクトは0とする)
                                        effect[k].x=del_effect[i].x;//座標をセット
                                        effect[k].y=del_effect[i].y;
                                        effect[k].spd=0;
                                }
                        }
                        if(del_effect[i].cnt>8){
                                del_effect[i].flag=0;
                        }
                        del_effect[i].cnt++;
                }
        }
}

//ボムを登録
void enter_bom(){
        int k;
        bom.flag=1;
        bom.cnt=0;
        bom.knd=0;
        ch.mutekicnt=1;//無敵に
        se_flag[14]=1;//キュイーン音
        //縦線
        if((k=search_effect())!=-1){
                effect[k].flag=1;
                effect[k].cnt=0;
                effect[k].knd=3;//ボムの線のエフェクト
                effect[k].brt=0;//α値
                effect[k].ang=PI/2;//画像の向き
                effect[k].mvang=-PI/2;//エフェクトが進む方向
                effect[k].spd=1;//スピード
                effect[k].r=1;//大きさ
                effect[k].eff=2;//αブレンド
                effect[k].img=img_eff_bom[3];
                effect[k].x=70;//座標
                effect[k].y=300;
        }
        //横線
        if((k=search_effect())!=-1){
                effect[k].flag=1;
                effect[k].cnt=0;
                effect[k].knd=3;//ボムの線のエフェクト
                effect[k].brt=0;
                effect[k].ang=0;
                effect[k].mvang=0;
                effect[k].spd=1;
                effect[k].r=1;
                effect[k].eff=2;
                effect[k].img=img_eff_bom[3];
                effect[k].x=100;
                effect[k].y=350;
        }
        //キャラ
        if((k=search_effect())!=-1){
                effect[k].flag=1;
                effect[k].cnt=0;
                effect[k].knd=2;//ボムのキャラ・線のエフェクト
                effect[k].brt=0;
                effect[k].ang=0;
                effect[k].mvang=-PI/2;
                effect[k].spd=0.7;
                effect[k].r=1;
                effect[k].eff=2;
                effect[k].img=img_eff_bom[2];
                effect[k].x=260;
                effect[k].y=300;
        }
}

//ボム計算
void bom_calc(){
        int n,k,shot_angle[4]={0,PI,PI/2,PI*1.5};//4発エフェクトが飛ぶ角度
        if(ch.flag==0 && bom.flag==0){//キャラが通常状態で、ボムがオフなら
                if(CheckStatePad(configpad.bom)==1){//ボムボタンが押されたら
                        enter_bom();
                }
        }
        if(bom.flag==1){//ボムが登録されていたら
                if(bom.cnt%10==0){//1/6秒に1回
                        n=(bom.cnt/10);
                        if(n<4 && (k=search_effect())!=-1){
                                effect[k].flag=1;
                                effect[k].cnt=0;
                                effect[k].knd=1;//エフェクト番号1:ボムのエフェクト
                                effect[k].brt=0;
                                effect[k].ang=rang(PI);//画像の向きはランダム
                                effect[k].mvang=shot_angle[n]-PI/4;//飛ぶ方向
                                effect[k].spd=13+rang(2);//スピード
                                effect[k].r=0.5;//大きさ
                                effect[k].eff=2;//αブレンド
                                effect[k].img=img_eff_bom[(bom.cnt/10)/3];//画像
                                effect[k].x=ch.x;//座標
                                effect[k].y=ch.y;
                        }
                }
                bom.cnt++;
                if(bom.cnt<40)
                        bright_set.brt=255-bom.cnt*5;//画面の明るさ設定(暗く)
                if(bom.cnt>90)
                        bright_set.brt=255-40*5+(bom.cnt-90)*5;//画面の明るさ設定(明るく)
                if(bom.cnt>130){
                        bom.flag=0;
                        bright_set.brt=255;
                }
        }
}

//ドガーンとゆれる画面の処理
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;
                }
        }
}

void effect_main(){
        dn_calc();//ドガーンとゆれる画面の処理
        calc_del_effect();//消滅エフェクトの計算
        calc_effect();//エフェクトの計算
        bom_calc();//ボム計算
}



enter_bomでボムを登録します。登録されたボムは130カウントの間計算され、

エフェクトの登録や、画面の明るさの変更などを行います。

calc_effect()関数では、エフェクトの計算を行っており、今回増えたエフェクト番号1,2,3の処理が追加されています。



実行結果



- Remical Soft -