![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
お疲れ様です。
今回もお世話になります。
シューティングゲームのサンプルで勉強しています。
サンプルの乱射ショットの実行画面では弾が20発くらい
一度に乱射した状態で発射します。
自分の実行画面は1~2発、画面から後退するときに
もう1~2発発射するだけです。
自分なりにコードを足してみたりしたのですが
2くらい増えただけで乱射になりません。
まだ理解不足で出来ませんでした。
何が足りないか教えてください。
以下は乱射部分だけのコードです。
その下にENEMY::Shot()の全体のコードを載せます。
失礼します。
//乱射ショット
case 3:
//1ループ毎に1発発射
for(int i=0;i<ENEMY_SNUM;++i){
//フラグが立ってない弾を探して、座標セット
if(shot[i].flag==false){
shot[i].flag=true;
shot[i].x=x;
shot[i].y=y;
//初回だけ乱数初期化
if(num==0){
srand((unsigned int)time(NULL));
shot[i].rad=atan2(py-y,px-x)-(60*PI/180)+((rand()%120)*PI/180);
++num;
break;
}
}
}
break;
以下はENEMY::Shot()の全体のコードです。
void ENEMY::Shot()
{
//CONTROLクラスの参照
CONTROL &control = CONTROL::GetInstance();
double px,py;
//発射タイミングになったら、フラグを立てる
if(shot_time==g_count){
sflag=true;
}
//フラグを立てるときだけ
if(sflag){
//プレイヤーの一取得
control.GetPlayerPosition(&px,&py);
//敵とプレイヤーとの座標の差から逆正接を求める。
//初回だけ実行
if(scount==0)
rad=atan2(py-y,px-x);
switch(s_pattern){
//前方にショット
case 0:
//5回に一回発射。20までなので5発発射。
if(scount%5==0 && scount<=20){
for(int i=0;i<ENEMY_SNUM;++i){
//フラグが立ってない弾を探して、座標をセット
f(shot[i].flag==false){
shot[i].flag=true;
shot[i].x=x;
shot[i].y=y;
shot[i].rad=rad;
break;
}
}
}
break;
//プレイヤーに向かって直線ショット
case 1:
//6ループに一回発射。54までなので10発発射。
if(scount%6==0 && scount<=54){
for(int i=0;i<ENEMY_SNUM;++i){
//フラグが立っていない弾を探して、座標をセット
if(shot[i].flag==false){
shot[i].flag=true;
shot[i].x=x;
shot[i].y=y;
shot[i].rad=rad;
break;
}
}
}
break;
//3直線ショット
case 2:
//10ループに一回発射。1ループに3発なので5ループさせると15発発射
if(scount%10==0 && scount<=40){
for(int i=0;i<ENEMY_SNUM;++i){
//フラグが立っていない弾を探して、座標等をセット
if(shot[i].flag==false){
shot[i].flag=true;
shot[i].x=x;
shot[i].y=y;
//0の時は左より
if(num==0){
//敵とプレイヤーとの逆正接から10度引いたラジアンを代入
shot[i].rad=rad-(10*3.14/180);
//1の時はプレイヤー一直線
}else if(num==1){
//敵とプレイヤーとの逆正接を代入
shot[i].rad=rad;
//2の時は右より
}else if(num==2){
//敵とプレイヤーとの逆正接から10度足したラジアンを代入
shot[i].rad=rad+(10*PI/180);
}
++num;
//3発発射したら,numを0にしてループを抜ける。
if(num==3){
num=0;
break;
}
}
}
}
break;
//乱射ショット
case 3:
//1ループ毎に1発発射
for(int i=0;i<ENEMY_SNUM;++i){
//フラグが立ってない弾を探して、座標セット
if(shot[i].flag==false){
shot[i].flag=true;
shot[i].x=x;
shot[i].y=y;
//初回だけ乱数初期化
if(num==0){
srand((unsigned int)time(NULL));
shot[i].rad=atan2(py-y,px-x)-(60*PI/180)+((rand()%120)*PI/180);
++num;
break;
}
}
}
break;
}
//フラグが立ってる弾の数
int s=0;
//フラグが立ってる弾だけ、弾の移動を行う
for(int i=0;i<ENEMY_SNUM;++i){
if(shot[i].flag){
switch(shot[i].pattern){
//単純に下に発射
case0:
shot[i].y+=shot[i].speed;
break;
case 1:
shot[i].x+=shot[i].speed*cos(shot[i].rad);
shot[i].y+=shot[i].speed*sin(shot[i].rad);
break;
case 2:
shot[i].x+=shot[i].speed*cos(shot[i].rad);
shot[i].y+=shot[i].speed*sin(shot[i].rad);
break;
case 3:
shot[i].x+=shot[i].speed*cos(shot[i].rad);
shot[i].y+=shot[i].speed*sin(shot[i].rad);
break;
}
//弾が画面をはみ出たらフラグを戻す。
if(ShotOutCheck(i)){
shot[i].flag=false;
continue;
}
++s;
}
}
//sがゼロということは発射中の弾がない。
//かつdeadflagがTRUEということはこの敵のクラスは消滅させてよい
if(s==0 && deadflag){
//敵クラス消滅フラグをTRUEにする
endflag=true;
}
++scount;
}
}
No.2ベストアンサー
- 回答日時:
細かく全体を見てはいません。
//初回だけ乱数初期化
if(num==0){
srand((unsigned int)time(NULL));
shot[i].rad=atan2(py-y,px-x)-(60*PI/180)+((rand()%120)*PI/180);
++num;
break;
}
提示された部分で、rand が使われているのはここだけです。
これだと、 「num==0 のとき、必ず srand してからrand」となります。
・numがどうなっているのか、コードからはわかりません。
最初の1回だけ角度がランダムに決定され、それ以降はnum!=0となり、shot[i].radが過去に設定されたもののまま、ということは無いですか?
・乱数の発生原理を理解しましょう。
randは「疑似乱数」と呼ばれるもので、「乱数のように見えるけど、実際には一定の法則に従った数列」です。
srand (seed,種と呼ばれます)は、その初期値を決めるものです。種が同じなら、発生する乱数列も同じになります。
例えば srand(10) 後、 rand()を繰り返したら 5,3,7,2 .... と乱数が求められたとします。
この場合、srand(10)とすれば、その後のrand()は、必ず 5,3,7,2 .... となります。
通常は、最初にsrandして、後はrandを繰り返す、という使い方をします。
srandは、プログラム実行時に初期値が設定されます。そのため、プログラム実行の度に同じ乱数列が発生します。
# いわゆる「電源パターン」です。
それを防ぐテクニックに一つが、「現在時刻を元に種を作る」です。
srand((unsigned int)time(NULL));
はそのためのものです。
ですが、これには「同じ時刻だと同じ乱数になる」という欠点があります。
time()は1秒単位です。よって、現在のプログラムだと、1秒間に撃たれた「乱射弾」は、全部同じ方向へ飛びます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 一眼レフカメラ 【Canon Power Shot SX70 HS】のレンズカバーを無くしてしまいまし 4 2022/11/23 20:15
- 一眼レフカメラ 【Canon Power Shot SX70 HS】のレンズフードを無くしてしまいま 1 2022/11/23 20:08
- 英語 shoot、shot どちらも名詞で「発砲」的な意味がありますけど 違いはなんですかね? 3 2022/12/18 00:46
- C言語・C++・C# C++ と、 1 2022/11/07 23:45
- 英語 screen shotの直訳をお教えください 5 2023/02/23 08:53
- 画像編集・動画編集・音楽編集 open shotで説明ビデオ(無音動画とテキストテロップ形式)を作りたいのですが、このソフトは複数 1 2023/04/01 22:24
- 鳥類 この野鳥の名前を教えて下さい。 3 2023/05/15 10:58
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- Visual Basic(VBA) 【Excel VBA】自動メール送信の機能追加 5 2022/09/29 12:53
- 英語 英文の添削をしてほしいです。 2 2022/07/12 12:07
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
getcの改行判定
-
for文の中にswitch文はいれられ...
-
配列を使って魔方陣
-
#if 1 #elseの意味について
-
c言語プログラミングで1から100...
-
c言語のwhile文を使った計算で...
-
C言語初心者です。次の問題で質...
-
VHDLで、case文とwhen文のどち...
-
構文エラー";"が型の前にあり...
-
C言語 プログラム
-
全角文字の判定
-
計算結果がlong型以上になる場...
-
配列を関数に渡す方法
-
File Edit Options Buffers Too...
-
行列をべき乗させるプログラム
-
C言語で分からないことがあり...
-
十進BASICのプログラムについて
-
for文
-
C言語
-
プログラミング関係で
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
構文エラー";"が型の前にあり...
-
for文の中にswitch文はいれられ...
-
#if 1 #elseの意味について
-
プログラミングで二番目に大き...
-
getcの改行判定
-
C言語プログラムが理解できなくて…
-
C言語 数字以外を入力させない...
-
配列を関数に渡す方法
-
配列を使って魔方陣
-
初心者です。for文、if文を使っ...
-
c言語for文
-
c言語で平均をだす
-
while文について、c言語...
-
scanf関数を用いての加減乗除%...
-
行列をべき乗させるプログラム
-
c言語プログラミングで1から100...
-
C言語階乗の総和を求める
-
scanfが実行されません
-
階乗のプログラム!!
-
C言語の二分法のプログラムにつ...
おすすめ情報