そこの13章の敵の弾が自機を狙う処理でつまづきました。
3日程試行錯誤して、1から打ち直したりしたのですがどうにも改善しないのでここで質問させていただきました。
ここに載せる事は上のHPの管理人様には許可を得ています。
Microsoft VisualC++ 2010 Express で作成しています Dxライブラリ使用です。
C++は少しかじった程度で、しかも勉強してからだいぶ期間空いてしまったので理解してない点が多いです。
長いですが宜しくお願いします。
まず↓が敵クラスの発射関数です。
発射フラグが立った時にプレイヤーの座標を取得し、1度だけプレイヤーへの角度を求めています。
ですがショットパターンが1及び2の時、プレイヤーの初期座標が常に入りっぱなしで、動いた後次の敵が来ても、敵の弾がプレイヤーを狙ってくれないのです。
void CEnemy::Shot()
{
//CONTROLクラスの参照
CONTROL &control = CONTROL::GetInstance();
double dbPx = 0, dbPy = 0;
//発射タイミングになったらフラグを立てる
if( this->n_Shottime == g_Count ){
this->fShot = TRUE;
}
//フラグが立っている時だけ
if( this->fShot ){
if( !this->fDead){
//プレイヤーの座標取得
control.GetPlayerPos( &dbPx, &dbPy );
//敵とプレイヤーの位置から逆正接を求める
//初回だけ実行
if( this->nScount == 0 )this->dbRad = atan2( (dbPy - this->db_eY), (dbPx - this->db_eX) );
//ショットパターンを参照して発射方法を分ける
switch( this->byS_pat ){
//前方にショット
case 0:
//5ループに1回発射 20までなので5発発射
if( this->nScount%5 == 0 && this->nScount <= 20 ){
for( int i = 0; i < E_SHOT_MAX; i++ ){
//フラグが立ってない弾を探して座標等をセット
if( this->E_shot[i].fShot == FALSE ){
this->E_shot[i].fShot = TRUE; //発射中フラグ
this->E_shot[i].dbX = this->db_eX; //X座標
this->E_shot[i].dbY = this->db_eY; //Y座標
this->E_shot[i].dbRad = this->dbRad;//発射角度
break;
}
}
}
break;
//プレイヤーに向かって直線ショット
case 1:
//6ループに1回発射、54までなので10発発射
if( this->nScount % 6 == 0 && this->nScount <= 54 ){
//フラグが立ってない弾を探して座標などをセット
for( int i = 0; i < E_SHOT_MAX; ++i ){
if( !this->E_shot[i].fShot ){
this->E_shot[i].fShot = TRUE;
this->E_shot[i].dbX = this->db_eX;
this->E_shot[i].dbY = this->db_eY;
this->E_shot[i].dbRad = this->dbRad;
break;
}
}
}
break;
//3方向ショット
case 2:
//10ループに1回発射、1ループに3発なので5ループさせると15発発射
if( this->nScount % 10 == 0 && this->nScount <= 40 ){
for( int i = 0; i < E_SHOT_MAX; ++i ){
//フラグが立っていない弾を探して、座標等をセット
if( !this->E_shot[i].fShot ){
this->E_shot[i].fShot = TRUE;
this->E_shot[i].dbX = this->db_eX;
this->E_shot[i].dbY = this->db_eY;
//3方向発射の処理。発射中弾数カウント用変数を参照して
//0の時は左より
if( this->nBulletNum == 0 ){
//敵とプレイヤーとの逆正接から10度引いたラジアンを代入
this->E_shot[i].dbRad = this->dbRad - ( 10 * 3.14 / 180 );
//1の時はプレイヤー一直線
}else if( this->nBulletNum == 1 ){
//敵とプレイヤーの逆正接を代入
this->E_shot[i].dbRad = this->dbRad;
//2の時は右より
}else if( this->nBulletNum == 2 ){
//敵とプレイヤーとの逆正接から10度足したラジアンを代入
this->E_shot[i].dbRad = this->dbRad + ( 10 * PI / 180 );
}
//弾数カウントを足す
this->nBulletNum++;
//3発発射したらカウントを0にしてループを抜ける
if( this->nBulletNum == 3 ){
this->nBulletNum = 0;
break;
}
}
}
}
break;
//乱射ショット
case 3:
//5ループに1回発射、70までなので15発発射
if( this->nScount % 5 == 0 && this->nScount <= 70 ){
for( int i = 0; i < E_SHOT_MAX; ++i ){
//フラグが立ってない弾を探して、座標等をセット
if( !this->E_shot[i].fShot ){
this->E_shot[i].fShot = TRUE;
this->E_shot[i].dbX = this->db_eX;
this->E_shot[i].dbY = this->db_eY;
//初回だけ乱数初期化
if( this->nBulletNum == 0 ){
srand( (unsigned int)time( NULL ) );
}
this->E_shot[i].dbRad = atan2( dbPy - this->db_eY, dbPx - this->db_eX ) - ( 60 * PI / 180 ) + ( (rand() % 120) * PI / 180 );
this->nBulletNum++;
break;
}
}
}
break;
}
}
//フラグが立ってる弾の数
int fBullet = 0;
//フラグが立っている弾の数だけ移動を行う
for( int i = 0; i < E_SHOT_MAX; ++i ){
if( this->E_shot[i].fShot ){
switch( this->E_shot[i].byS_pat ){
//単純に下に発射
case 0 :
this->E_shot[i].dbY += this->E_shot[i].byB_Speed;
break;
case 1:
this->E_shot[i].dbX += this->E_shot[i].byB_Speed * cos( this->E_shot[i].dbRad );
this->E_shot[i].dbY += this->E_shot[i].byB_Speed * sin( this->E_shot[i].dbRad );
break;
case 2:
this->E_shot[i].dbX += this->E_shot[i].byB_Speed * cos( this->E_shot[i].dbRad );
this->E_shot[i].dbY += this->E_shot[i].byB_Speed * sin( this->E_shot[i].dbRad );
break;
case 3:
this->E_shot[i].dbX += this->E_shot[i].byB_Speed * cos( this->E_shot[i].dbRad );
this->E_shot[i].dbY += this->E_shot[i].byB_Speed * sin( this->E_shot[i].dbRad );
break;
}
//弾が画面外へ行ったらフラグを戻す
if( this->BulletOutCheck(i) ){
this->E_shot[i].fShot = FALSE;
continue;
}
++fBullet;
}
}
//fBulletが0という事は発射中の弾がない
//かつdeadflagがTRUEということはこの敵クラスを消滅させても良い
if( fBullet == 0 && this->fDead ){
this->fEnd = TRUE;
}
++this->nScount;
}
DrawFormatString( 30, 200, 0xffff, "X:%d", (int)dbPx );
DrawFormatString( 30, 220, 0xffff, "Y:%d", (int)dbPy );
}
void CONTROL::All()
{
//描画領域の指定
SetDrawArea( MARGIN, MARGIN, (MARGIN+BGWIDTH), (MARGIN+BGHEIGHT) );
bground->All(); //背景クラスのAll関数実行
player->All(); //プレイヤークラスのAll関数実行
//敵の総数分敵クラスを作成
for( int i = 0; i < ENEMY_MAX; ++i ){
if( enemy[i] != NULL ){
if( enemy[i]->All() ){
delete enemy[i]; //敵クラス消滅フラグがTRUEなら解放する
enemy[i] = NULL;
}
}
}
++g_Count; //ゲームループカウント
}
敵クラスで座標取得関数を呼び出すためにcontorlクラスにプレイヤー座標取得関数を作っています