広告
↓発売日:2018年09月22日↓
新品価格 |
今回は敵ショットを表示させてみます。
敵ショットの構造体から見てみましょう。
#define ENEMY_SHOT_MAX 20 struct ENEMY_SHOT{ double first_x; double first_y; double x[10]; double y[10]; double draw_x[10]; double draw_y[10]; double angle[10]; int init_flag; int move_flag; int move_type; int max_bullet; int gamecount_point[5]; double range; int enemy_num; }; struct ENEMY_SHOT enemy_shot[ENEMY_SHOT_MAX];
今までやってきた敵の構造体などとほとんど一緒ですね!
わかりやすいトコロから見てみましょう。
double first_x; double first_y; double x[10]; double y[10]; double draw_x[10]; double draw_y[10];
初期位置の座標「first_x,first_y」、計算座標「x,y」と表示する時の座標「draw_x,draw_y」ですね。
連射する弾などもあるので座標は「10」個ぐらい用意しておきます。
double angle[10];
好きな方向に飛ばしたい時に指定する角度です。
int init_flag; int move_flag; int move_type;
初期化用のフラグ、「敵ショットの入れ物」が使用中かどうかのフラグ、ショットの動き方。
int max_bullet;
こちらはプレイヤーの時にもありましたね、一度に飛ばすショットの最大弾数になります。
int gamecount_point[5]; double range;
あとは基準の「gamecount」の記録用と当たり判定の範囲ですね。
int enemy_num;
こちらは連射ショットを打っている敵がいた時、その敵はどの敵なのかを判別する為の変数なのですが、今の時点ではわかりづらいので連射ショットを実際作る時まではあまり気にしないでください。
#define ENEMY_SHOT_MAX 20 struct ENEMY_SHOT enemy_shot[ENEMY_SHOT_MAX];
そして敵ショットは敵の消滅するタイミングなどと少しずれたりするので敵の数より少し多めに用意しておきます。
敵の時と同じように、これが「敵ショットの入れ物」となりこの構造体の数が「同時に画面に表示できる敵ショットの最大数」になります。
初期化します。
void my_init_enemy_shot(){ for (int i = 0; i < ENEMY_SHOT_MAX; i++){ enemy_shot[i].first_x = 0; enemy_shot[i].first_y = 0; enemy_shot[i].init_flag = 0; enemy_shot[i].move_flag = 0; enemy_shot[i].move_type = 0; enemy_shot[i].max_bullet = 0; enemy_shot[i].range = 10; enemy_shot[i].enemy_num = 0; for(int j = 0;j < 10;j++){ enemy_shot[i].x[j] = 0; enemy_shot[i].y[j] = 0; enemy_shot[i].draw_x[j] = 0; enemy_shot[i].draw_y[j] = 0; enemy_shot[i].angle[j] = 0; } for(int j = 0;j < 5;j++){ enemy_shot[i].gamecount_point[j] = 0; } } }
当たり判定範囲の「range」は全て「10」残りは全て「0」で初期化しております。
プレイヤーショットの時は発射ボタンを押す事によって「move_flag」を起動しました。
敵の時は登場するポイントである「appear_point」に差し掛かった時に「move_flag」を起動しました。
では敵ショットはどのように「move_flag」を起動するのかと言いますと「敵自身が移動する動き」の中で敵ショットを起動します。
それを踏まえて敵ショットを表示するまでの流れを見てみましょう。
1・「敵の動き」の中で敵ショットを発射する
2・敵ショットが発射された時に現在未使用の「敵ショットの入れ物」を調べて使用中に
3・その時の「敵ショットの動き方」などを「敵ショットの入れ物」に登録
4・その「敵ショットの動き方」に応じて出現・計算・表示
5・終わったら再び「敵ショットの入れ物」を未使用に
最初の部分が違うだけでやはりほとんど変わらない流れですね。
ではまずは「敵の動き」に敵ショット発射を加えてみましょう。
前回作った単純な「敵の動き」に敵ショット起動を加えてみます。
if (gamecount < enemy[i].gamecount_point + 220){ enemy[i].y--; } if (gamecount == enemy[i].gamecount_point + 240){ my_set_enemy_shot(enemy[i].x,enemy[i].y,enemy[i].shot_type,i); } if (gamecount > enemy[i].gamecount_point + 260){ enemy[i].y++; }
「my_move_enemy()」内、上から下降、しばらくしたら再び上昇する動きの中に敵ショット起動部分を追加しました。
my_set_enemy_shot(enemy[i].x,enemy[i].y,enemy[i].shot_type,i);
引数にはその時の敵の座標「enemy[i].x,enemy[i].y」、その敵が持つショットの種類「enemy[i].shot_type」そしてさきほどの「enemy_num」にあたるその敵自身がどの「敵の入れ物」を使っているのかを示す情報を渡します。
では「my_set_enemy_shot」の中身を見てみましょう。
void my_set_enemy_shot(double x,double y,int shot_type,int enemy_num){ for(int i = 0;i < ENEMY_SHOT_MAX;i++){ if(enemy_shot[i].move_flag == 0){ enemy_shot[i].move_flag = 1; enemy_shot[i].first_x = x; enemy_shot[i].first_y = y; enemy_shot[i].move_type = shot_type; enemy_shot[i].enemy_num = enemy_num; break; } } }
未使用の「敵ショットの入れ物」を探して
for(int i = 0;i < ENEMY_SHOT_MAX;i++){ if(enemy_shot[i].move_flag == 0){ } }
さきほど引数で渡した情報をそれぞれに登録するだけですね。
enemy_shot[i].move_flag = 1; enemy_shot[i].first_x = x; enemy_shot[i].first_y = y; enemy_shot[i].move_type = shot_type; enemy_shot[i].enemy_num = enemy_num;
敵ショットが起動されたトコロで実際の動きに入っていきます。
敵ショットの動き方を計算する「my_move_enemy_shot()」です。
少し長いので分けて説明します。
まずは全ての「敵ショットの入れ物」を調べてそれが使用中かどうか調べます。
for(int i = 0;i < ENEMY_SHOT_MAX;i++){ if(enemy_shot[i].move_flag == 1){ } }
ここで使用中「enemy_shot[i].move_flag == 1」の状態のものがあった場合、その敵ショットは動いていなきゃいけないので動かします。
「switch」文で動き方を振り分けます。
switch (enemy_shot[i].move_type){ case 0: break; default: break; }
今回は「case 0」まっすぐ下に飛ぶだけのショットを作ります。
初期化部分と移動部分に分かれます。
初期化部分を見てみます。
if (enemy_shot[i].init_flag == 0){ enemy_shot[i].x[0] = enemy_shot[i].first_x; enemy_shot[i].y[0] = enemy_shot[i].first_y; enemy_shot[i].max_bullet = 1; enemy_shot[i].gamecount_point[0] = gamecount; enemy_shot[i].init_flag = 1; } else{ /*移動部分*/ }
初期化用のフラグ「enemy_shot[i].init_flag == 0」の時は初期化されていないので初期化をします。
初期座標はそのショットを放った敵の座標を移した「enemy_shot[i].first_x,enemy_shot[i].first_y」ですね。
最初は一発だけしか飛ばさないので最大弾数である「enemy_shot[i].max_bullet = 1」になります。
あとは基準となる「gamecount」を記録して初期化完了です。
では移動部分を見てみましょう。
先ほどの「else」部分ですね。
else{ if (gamecount < enemy_shot[i].gamecount_point[0] + 300){ enemy_shot[i].y[0] -= 2; } else{ enemy_shot[i].move_flag = 0; enemy_shot[i].init_flag = 0; } }
「gamecount_point[0]」を基準に「300」カウント下降して少し経過した時点で消滅します。
こちらは前回までと同じような処理なので省略させて頂きます。
敵ショットが表示されました!
ここまでの中間ソースになります。
次回は当たり判定を作ります。
広告
↓発売日:2016年02月29日↓
12歳からはじめる ゼロからのC言語 ゲームプログラミング教室 新品価格 |
↓発売日:2018年06月22日↓
新品価格 |
↓発売日:2018年03月09日↓
新品価格 |
↓発売日:2017年06月14日↓
新品価格 |
↓発売日:2018年05月21日↓
新品価格 |
↓発売日:2017年12月07日↓
新品価格 |
↓発売日:2017年02月08日↓
新・明解C言語で学ぶアルゴリズムとデータ構造 (明解シリーズ) 新品価格 |
↓発売日:2017年09月26日↓
新品価格 |