プロが教えるわが家の防犯対策術!

CとDXライブラリでSTGを作っているのですが、あたり判定がわかりません。前、斜め右上、斜め右下の3方向に飛ぶ弾の処理を行いたいのですが、どうすればいいのでしょうか?
画面に出力することはできたのですが、ななめに飛ぶ弾だけ判定できずに困っています。
―――――――――ソースの一部―――――――――――
//拡散する弾
void JitamaMove2(){
//弾の発射
int key = GetJoypadInputState(DX_INPUT_KEY_PAD1);
if( (key & PAD_INPUT_A) && (trigger == 0) ) {
for( int i = 0; i < 3; i++ ){
if (jitama[i].life == 0){
jitama[i].life = 1;
jitama[i].x = jikidata.x+24;
jitama[i].y = jikidata.y+8;
jitama[i].y1 = jikidata.y+8;
jitama[i].y2 = jikidata.y+8;

float dy = jikidata.y;
float d = sqrt(dy*dy);
jitama[i].yobi = dy/d*idouryou[4]*10;

break;
}
}
trigger = 20;
}
if(trigger>0) trigger = trigger - 1;

//弾の移動
for(int i=0; i<3; i=i+1){
if(jitama[i].life > 0){
jitama[i].x = jitama[i].x + idouryou[10];
DrawGraph(jitama[i].x, jitama[i].y,*(jitama[i].ghandle), TRUE);

float idouy = (float)jitama[i].yobi / 10;
jitama[i].y2 = jitama[i].y2 - idouy;
DrawGraph(jitama[i].x, jitama[i].y2 - 10, *(jitama[i].ghandle), TRUE);//斜め下に対する弾の描写
jitama[i].y1 = jitama[i].y1 + idouy;
DrawGraph(jitama[i].x, jitama[i].y1 + 10, *(jitama[i].ghandle), TRUE);//斜め上に対する弾の描写
//画面外に出たときの処理
if(jitama[i].x>640) jitama[i].life = 0;
}
}
}

/*当たり判定を計算する関数*/
int IsAtari(CharaData *a, CharaData *b){
int retval = 0;
int ax1 = a->x + (a->image_w - a->bounds_w)/2;
int ay1 = a->y + (a->image_h - a->bounds_h)/2;
int ax2 = a->x + (a->image_w + a->bounds_w)/2;
int ay2 = a->y + (a->image_h + a->bounds_h)/2;

int bx1 = b->x + (b->image_w - b->bounds_w)/2;
int by1 = b->y + (b->image_h - b->bounds_h)/2;
int bx2 = b->x + (b->image_w + b->bounds_w)/2;
int by2 = b->y + (b->image_h + b->bounds_h)/2;

if( (ax1<bx2) && (bx1<ax2) && (ay1<by2) && (by1<ay2) ){
switch (a->amode){
case A_NORMAL://キャラ消滅
a->life = 0;
break;
case A_HARD://耐久力-1
a->life = a->life -1;
break;
}
switch (b->amode){
case A_NORMAL://キャラ消滅
b->life = 0;
break;
case A_HARD://耐久力-1
b->life = b->life -1;
if(b->life > 0) SetHanten(b->x, b->y, b->image_w, b->image_h);
break;
}
if(b->life == 0) SetBakuen(b->x, b->y);
retval = 1;
}

return(retval);

}


//当たり判定の処理
int AtariHantei(){
for(int i=0; i<50; i=i+1){
if(tekidata[i].life > 0 && tekidata[i].amode != A_GHOST){//A_GHOS・・・判定なし
//自機と敵の判定
if(IsAtari(&jikidata, &tekidata[i])==1) return(1);
//弾と敵の判定
for(int j=0; j<3; j=j+1){
if(jitama[j].life > 0 && jitama[j].amode != A_GHOST){
IsAtari(&jitama[j], &tekidata[i]);
}
}
}
}

for( int i = 0; i < 50; i++ ){
if(tekitama[i].life > 0){
if(IsAtari(&jikidata, &tekitama[i]) == 1) return(1);
}
}
return(0);
}

A 回答 (1件)

★弾をどう管理しているのでしょうか?


>画面に出力することはできたのですが、ななめに飛ぶ弾だけ判定できずに困っています。
 ↑
 弾の座標が判定したい座標と違うから上手く判定できていないように思います。
 弾の当たり判定は何時呼び出しますか?
 普通は弾が移動した後で判定しますが…。
 ※自機、自機弾、敵機、敵機弾の移動タイミングは同じですか?
・ソースを見ましたが良く分かりません。
 当たり判定は次の4パターンあります。
 (1)『自機の移動』と『敵機/敵機弾』の当たり判定
 (2)『敵機の移動』と『自機/自機弾』の当たり判定
 (3)『自機弾の移動』と『敵機』の当たり判定
 (4)『敵機弾の移動』と『自機』の当たり判定
 これを上手に判定するには自機、自機弾、敵機、敵機弾を1つのオブジェクトとして
 管理します。そうすれば当たり判定を1つの共通な関数に出来て便利なのですが。
 ソースを見た感じ違う構造のようですね。
 斜めだけ判定できないということはY座標がずれているのかも。
 当たり判定の関数を整理した方が良いでしょう。
 まず次の関数を用意します。
 (1)自機本体との衝突チェック⇒int JikiCheck(x,y,w,h)
 (2)自機弾丸との衝突チェック⇒int JikiShotCheck(x,y,w,h)
 (3)敵機本体との衝突チェック⇒int EnemyCheck(x,y,w,h)
 (4)敵機弾丸との衝突チェック⇒int EnemyShotCheck(x,y,w,h)
 これらの関数は与えられた引数(x,y,w,h)より衝突すれば 1 を返す仕様です。
 この4つの関数を用意したら自機などが移動した時の当たり判定を作ります。
 (1)『自機の移動』と『敵機/敵機弾』の当たり判定⇒void JikiCrash()
 (2)『敵機の移動』と『自機/自機弾』の当たり判定⇒void JikiShotCrash()
 (3)『自機弾の移動』と『敵機』の当たり判定⇒void EnemyCrash()
 (4)『敵機弾の移動』と『自機』の当たり判定⇒void EnemyShotCrash()
 この4つは上記の Check 関数を呼び出して当たり判定します。
 例えば(1)なら次のようになります。

サンプル:
// 『自機の移動』と『敵機/敵機弾』の当たり判定
void JikiCrash( void )
{
 // 自機と敵機の判定
 for ( int i = 0 ; i < 50 ; i++ ){
  if ( TekiData[i].life > 0 ){
   int x = TekiData[i].x;
   int y = TekiData[i].y;
   int w = TekiData[i].image_w;
   int h = TekiData[i].image_h;
   
   if ( EnemyCheck(x,y,w,h) ){
    // 衝突処理
   }
  }
 }
 // 自機と敵機弾の判定
 for ( int i = 0 ; i < 50 ; i++ ){
  if ( TekiTama[i].life > 0 ){
   int x = TekiTama[i].x;
   int y = TekiTama[i].y;
   int w = TekiTama[i].image_w;
   int h = TekiTama[i].image_h;
   
   if ( EnemyShotCheck(x,y,w,h) ){
    // 衝突処理
   }
  }
 }
}
このように関数を整理して作り上げればバグも入りにくくなります。
本当なら自機、自機弾、敵機、敵機弾の座標だけを共通に管理する方法を考え
作り直せば当たり判定もスッキリ出来ます。時間があれば全ソースを見直して
シューティング・ゲームの設計をやり直すべきです。本当はね。
もう随分と作りこんでいるのでバグを見つけるのが大変です。
IsAtari関数が多分原因ではないかと推測します。
頑張って下さい。
    • good
    • 1

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!