こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

C++での乱射ショットについて教えてください。

お疲れ様です。
今回もお世話になります。
シューティングゲームのサンプルで勉強しています。
サンプルの乱射ショットの実行画面では弾が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;
}
}

投稿日時 - 2014-04-21 05:09:56

QNo.8562839

すぐに回答ほしいです

質問者が選んだベストアンサー

細かく全体を見てはいません。

//初回だけ乱数初期化
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秒間に撃たれた「乱射弾」は、全部同じ方向へ飛びます。

投稿日時 - 2014-04-21 08:02:30

お礼

お疲れ様です。
いろいろ復習になった部分もあったのでよかったです。
解決出来ました。
ありがとうございます。
失礼します。

投稿日時 - 2014-04-22 03:13:02

ANo.2

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

他のショットはサンプルのように上手くできているのでしょうか?
shot[i].flagやshot[i].radの値をデバッガで確認してみるとか。
乱数の初期化が出来ていないせいで全ての弾が重なってるなんてことはないですよね。

投稿日時 - 2014-04-21 07:02:30

お礼

お疲れ様です。
言葉をヒントに試していたら解決出来ました。
ありがとうございます。
失礼します。

投稿日時 - 2014-04-22 03:06:52

あなたにオススメの質問