敵が突然消えるだけでは何だか寂しいので、消滅エフェクトを作ってみましょう。

それでは、エフェクト用のファイルを一つ追加します。

ソリューションエクスプローラーで、プロジェクトの項目を右クリックして新しい項目の追加から、

mydat フォルダの source に「effect.cpp」を追加して下さい。

そこに以下のようにコピペして下さい。


---- 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://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;
                                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;
                                }
                        }
                        if(del_effect[i].cnt>8){//カウンタが8より大きくなったら終了
                                del_effect[i].flag=0;
                        }
                        del_effect[i].cnt++;
                }
        }
}

void effect_main(){
        calc_del_effect();//消滅エフェクトの計算
        calc_effect();//エフェクトの計算
}


enter_del_effectに消滅エフェクトを登録すれば、後は全自動でエフェクトを計算してくれる便利な機能です。

この関数には引数sに敵の識別番号を渡します。すると、s番の敵が消滅したエフェクトを登録してくれます。

今回も新たに情報の格納庫を用意しました。

消滅エフェクトを登録する為の del_effect

エフェクトを登録する為の effect

の2つです。 何故消滅エフェクトとエフェクトの2つあるのかと疑問に思う人もいるかもしれません。

消滅エフェクトは実際にエフェクトを行うわけではなく、どういうタイミングでエフェクトを登録するか、

何のエフェクトをどこに登録するかなどを管理する役をします。

つまり実際のエフェクトはeffectが計算、描画するのです。

このeffect変数は汎用的な物で消滅エフェクト以外にも様々な物が登録出来ます。

エフェクトにはこれから様々な物が登場しますが、ほとんどこれで賄います。

色んなエフェクトが必要になるたびに、色んな変数を用意するのは大変なのでこうすると効率的なのです。

なので、今は、「消滅エフェクト変数の上に、エフェクト変数が乗っかってる。消滅エフェクト変数だけじゃエフェクトにはならない

消滅エフェクト変数はエフェクトを管理する役をする」と覚えておいて下さい。

enter_del_effect関数で登録された情報は

calc_del_effect()関数で計算されます。

注釈を見てもらったら解ると思いますが、登録されている消滅エフェクトを探し、あれば

1/30秒に1回エフェクトを登録します。そして、エフェクトの登録番号を探し、そこに情報をセットします。

先ほども言ったように、エフェクト変数は何にでも使えるので、何のエフェクトであるかの種類を示す

kndに0を入れました。今後消滅エフェクトは0番のエフェクトだとします。



out_mainで自機ショット総数と敵総数を総当りで判定させます。

ではこれに伴っていつものように以下変更します。



---- out.cpp 以下の部分を変更 ----

extern void enter_del_effect(int);

void enemy_death_judge(int s){
        int i;
        se_flag[8]=1;//敵に当たった音
        if(enemy[s].hp<0){//敵のHPが0未満になったら
                enemy[s].flag=0;//敵を消滅させる
                se_flag[1]=1;//敵のピチュり音
                enter_del_effect(s);


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

//エフェクト登録最大数
#define EFFECT_MAX 100
//消滅エフェクト登録最大数
#define DEL_EFFECT_MAX 30


---- struct.h の以下を変更 ----

//敵に関する構造体
typedef struct{
        int flag,cnt,pattern,muki,knd,hp,hp_max,item_n[6],img,back_col;
        //フラグ、カウンタ、移動パターン、向き、敵の種類、HP最大値、落とすアイテム、背景色
        double x,y,vx,vy,sp,ang;
        //座標、速度x成分、速度y成分、スピード、角度
        int bltime,blknd,blknd2,col,state,wtime,wait;
        //弾幕開始時間、弾幕の種類、弾の種類、色、状態、待機時間、停滞時間
}enemy_t;


---- enemy.cppのenemy_enter関数の登録部の中に以下を追加 ----

enemy[i].back_col=GetRand(4);


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

//effect.cpp
GLOBAL void effect_main();


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

GLOBAL int img_del_effect[5];

GLOBAL del_effect_t del_effect[DEL_EFFECT_MAX];//消滅エフェクト
GLOBAL effect_t effect[EFFECT_MAX];//エフェクト


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

memset(effect,0,sizeof(effect_t)*EFFECT_MAX);
memset(del_effect,0,sizeof(del_effect_t)*DEL_EFFECT_MAX);


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

LoadDivGraph( "../dat/img/enemy/hit_effect.png" , 5 , 5 , 1 , 140 , 140 , img_del_effect ) ;


---- main.cpp のmain関数の以下を変更 ----

            case 100://通常処理
                calc_ch();   //キャラクタ計算
                ch_move();   //キャラクタの移動制御
                cshot_main();//自機ショットメイン
                enemy_main();//敵処理メイン
                shot_main(); //ショットメイン
                out_main();  //当たり計算
                effect_main();//エフェクトメイン
                graph_main();//描画メイン
                stage_count++;
                break;


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

//エフェクト
typedef struct{
        int flag,cnt,col,knd,img,eff,brt;
        double x,y,r,ang;
}effect_t;

//消滅エフェクト
typedef struct{
        int flag,cnt,col;
        double x,y;
}del_effect_t;


---- graph.cpp 以下を追加 ----

void graph_effect(){
    for(int i=0;i<EFFECT_MAX;i++){
        if(effect[i].flag>0){
            if(effect[i].eff==1)//エフェクトが光エフェクトなら
                SetDrawBlendMode( DX_BLENDMODE_ADD, effect[i].brt) ;

            DrawRotaGraphF(effect[i].x+FIELD_X,effect[i].y+FIELD_Y,effect[i].r,effect[i].ang,effect[i].img,TRUE);

            if(effect[i].eff==1)
                SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 0) ;
        }
    }
}

void graph_main(){
        graph_effect();
        graph_enemy();
        graph_cshot();
        graph_ch();
        graph_bullet();
        graph_board();
}




実行結果


- Remical Soft -