さて、段々それっぽくなってきましたね。
自機ショットと当たり判定を付ければ大分骨格が完成します。
自機ショットも基本的に敵がショットを撃つのと考え方は変わりません。
弾情報を格納する入れ物をつくって、そこに種類、スピード、角度などの情報を持たせるだけでいいのです。
数値さえ設定しておけば計算部が勝手に軌道や当たり判定を計算してくれます。
では、いつものように入れ物を用意します。
---- struct.h に以下(赤字部)を追加 ---- //キャラクターショットに関する構造体 typedef struct{ int flag,power,cnt,knd;//フラグ、パワー、カウンタ、種類 double x,y,angle,spd;//座標、角度、スピード }cshot_t; //キャラクターに関する構造体 typedef struct{ int flag; //フラグ int cnt; //カウンタ int power; //パワー int point; //ポイント int score; //スコア int num; //残機数 int mutekicnt; //無敵状態とカウント int shot_mode; //ショットモード int money; //お金 int img; int slow; //スローかどうか double x,y; //座標 int shot_cnt; //ショットのカウンタ }ch_t; ---- define.h に以下を追加 ---- //自機ショットの登録最大数 #define CSHOT_MAX 200 ---- GV.h に以下を追加 ---- GLOBAL int img_cshot[2]; //自機ショット用画像 GLOBAL cshot_t cshot[CSHOT_MAX];//自機ショット登録用変数 ---- load.cpp の load()関数に以下を追加 ---- img_cshot[0]=LoadGraph("../dat/img/char/bl_00.png"); img_cshot[1]=LoadGraph("../dat/img/char/bl_01.png"); sound_se[2]=LoadSoundMem("../dat/se/cshot.wav"); ---- ini.cpp の ini関数に以下を追加 ---- memset(cshot,0,sizeof(cshot_t)*CSHOT_MAX); ch.power=500; ---- function.h に以下を追加 ---- GLOBAL void cshot_main(); ---- graph.cpp に以下を追加 ---- void graph_cshot(){ for(int i=0;i<CSHOT_MAX;i++){ if(cshot[i].flag>0){ DrawRotaGraphF(cshot[i].x+FIELD_X,cshot[i].y+FIELD_Y,1,0, img_cshot[cshot[i].knd],TRUE); } } } ---- graph.cpp の graph_main関数を変更 ---- void graph_main(){ graph_enemy(); graph_cshot(); graph_ch(); graph_bullet(); graph_board(); } ---- main.cpp のメイン関数内のswitch分の以下の部分を変更 ---- case 100://通常処理 calc_ch(); //キャラクタ計算 ch_move(); //キャラクタの移動制御 cshot_main();//自機ショットメイン enemy_main();//敵処理メイン shot_main();//ショットメイン graph_main();//描画メイン stage_count++; break;
最後に肝心な自機ショット登録部についてです。
1回に、自機パワーが200以下なら2発、それ以上なら4発撃たせてみます。
その4発の位置を以下のようにしてみます。
int cshot0pos_x[4]={-10, 10,-30, 30}; int cshot0pos_y[4]={-30,-30,-10,-10};
1発目は(-10,-30)の位置、2発目は(10,-30)の位置、3発目は(-30,-10)。。。ということです。
今回も前回までと同様、登録格納庫を用意しているので、ショットを登録する時は
int search_cshot()
で空いている番号を探して登録します。
---- cshot.cpp を変更 ---- #include "../include/GV.h" int cshot0num[2] ={2,4}; int cshot0pos_x[4]={-10, 10,-30, 30}; int cshot0pos_y[4]={-30,-30,-10,-10}; //自機ショットの登録可能番号を返す int search_cshot(){ for(int i=0;i<CSHOT_MAX;i++){ if(cshot[i].flag==0) return i; } return -1; } //通常ショット登録 void ch0_shot_pattern(){ int k; for(int i=0;i<cshot0num[ch.power<200?0:1];i++){ if((k=search_cshot())!=-1){ cshot[k].flag=1; cshot[k].cnt=0; cshot[k].angle=-PI/2; cshot[k].spd=20; cshot[k].x=ch.x+cshot0pos_x[i]; cshot[k].y=ch.y+cshot0pos_y[i]; cshot[k].power=23; cshot[k].knd=0; } } se_flag[2]=1;//発射音オン } //低速通常ショット登録 void ch1_shot_pattern(){ int k; for(int i=0;i<cshot0num[ch.power<200?0:1];i++){ if((k=search_cshot())!=-1){ cshot[k].flag=1; cshot[k].cnt=0; cshot[k].angle=-PI/2; cshot[k].spd=20; cshot[k].x=ch.x+cshot0pos_x[i]/3;//低速中なら位置を中心側へ cshot[k].y=ch.y+cshot0pos_y[i]/2; cshot[k].power=23; cshot[k].knd=0; } } se_flag[2]=1; } //ショット登録部 void enter_shot(){ //ショットボタンが押されていたら if(CheckStatePad(configpad.shot)>0){ ch.shot_cnt++; if(ch.shot_cnt%3==0){//3カウントに1回 if(CheckStatePad(configpad.slow)>0)//低速移動中なら ch1_shot_pattern(); else ch0_shot_pattern(); } } else ch.shot_cnt=0; } //ショットの移動計算 void calc_cshot(){ for(int i=0;i<CSHOT_MAX;i++){ if(cshot[i].flag==1){ int dranx=cshot[i].spd+11/2,drany=cshot[i].spd+55/2; cshot[i].x+=cos(cshot[i].angle)*cshot[i].spd; cshot[i].y+=sin(cshot[i].angle)*cshot[i].spd; cshot[i].cnt++; if(cshot[i].x<-dranx || cshot[i].x>FIELD_MAX_X+dranx || cshot[i].y<-drany || cshot[i].y>FIELD_MAX_Y+drany)//画面から外れたら cshot[i].flag=0; } } } //キャラクタショットに関する関数 void cshot_main(){ calc_cshot();//ショットの軌道計算 enter_shot();//ショット登録 }
- Remical Soft -