ページ 11

当たり判定の処理を教えてください。

Posted: 2011年5月02日(月) 23:53
by こーら
シューティングゲームをつくっています。
自機、敵機、弾を表示させ、移動させるところまで完成したのですが、当たり判定の処理で手間取っています。
コードを載せますね・

コード:

#include "MainLoop.h"

//=============================================================
//                  グローバル変数
//=============================================================
static Plane    ziki;            //自機
static Plane    teki[ TEKI ];    //敵機
static Shot     myShot[ SHOT ];  //自弾
static Anything Any;             //その他

//=============================================================
//                  メインループ
//=============================================================
void MainLoop( void )
{
  //画像読み込み
  LoadImage();
  //初期化
  Init();

  //裏画面
  SetDrawScreen( DX_SCREEN_BACK );

  //ループ開始
  while( 1 )
  {
    Any.Flame++;

    //すべて消す
    ClsDrawScreen();

    /*****************************/

    ZikiMove();   //自機移動
    MyShot  ();   //自弾移動
    TekiMove();   //敵機移動

    /*****************************/

    //終了条件[ESC]
    if( CheckHitKey( KEY_INPUT_ESCAPE ) == 1 ) break;

    //裏画面の処理を表にコピー
    ScreenFlip();

    //windowsの処理
    if( ProcessMessage() < 0 ) break;
  }
}

//=============================================================
//                  画像読み込み
//=============================================================
void LoadImage( void )
{
  ~~~~~~~略~~~~~~~~~
}

//=============================================================
//                  変数初期化
//=============================================================
void Init( void )
{
 ~~~~~~~略~~~~~~~~~
}

//=============================================================
//                  自機移動
//=============================================================
void ZikiMove( void )
{
  ~~~~~~~略~~~~~~~~~
}

//=============================================================
//                  自弾移動
//=============================================================
void MyShot( void )
{
  int hit = 0;
  int i;

  //SPACEが押されたら
  if( CheckHitKey( KEY_INPUT_SPACE ) == 1 ){
    //space押フラグが0のとき
    if( Any.Press == 0 ){
      //弾情報取得ループ
      for( i = 0; i < SHOT; i++ ){
        //弾が存在していなければ
        if( myShot[ i ].F == 0 ){
          myShot[ i ].X = ziki.X + ( ziki.W - myShot[ i ].W ) / 2;
          myShot[ i ].Y = ziki.Y - myShot[ i ].H;
          myShot[ i ].F = 1;
          break;
        }
      }
    }
    //space押フラグを1に
    Any.Press = 1;
  } else {
    //space押フラグを0に
    Any.Press = 0;
  }

  //弾表示ループ
  for( i = 0; i < SHOT; i++ ){
    //弾存在フラグが1のとき
    if( myShot[ i ].F == 1 ){
      //移動
      myShot[ i ].Y -= 4;
      //壁にあたったら消す
      if( myShot[ i ].Y < 0 ) myShot[ i ].F = 0;
      //弾表示
      DrawGraph( myShot[ i ].X, myShot[ i ].Y, myShot[ i ].Graph, TRUE );
    }
  }
}

//=============================================================
//                  敵機移動
//=============================================================
void TekiMove( void )
{
  int i, j, hit = 0;

  if( Any.Flame % 50 == 0 ){
    for( i = 0; i < TEKI; i++ ){
      if( teki[ i ].F == 0 ){
        teki[ i ].X = GetRand( winX - teki[ i ].W );
        teki[ i ].Y = 0;
        teki[ i ].F = 1;
        break;
      }
    }
  }

  for( i = 0; i < TEKI; i++ ){
    if( teki[ i ].F = 1 ){
      teki[ i ].Y += 3;
      DrawGraph( teki[ i ].X, teki[ i ].Y, teki[ i ].Graph, TRUE );
      if( teki[ i ].Y > winY ) teki[ i ].F = 0;
    }
  }

 //当たり判定?
  for( i = 0; i < TEKI; i++ ){
    if( teki[ i ].F == 1 ){
      for( j = 0; j < SHOT; j++ ){
        if( myShot[ j ].F == 1 ){
          hit = HitCheck( teki[i].X, teki[i].Y, teki[i].W, teki[i].H,
                          myShot[j].X, myShot[j].Y, myShot[j].W, myShot[j].H );
          if( hit == 1 ){
            teki[ i ].F = 0;
            myShot[ j ].F = 0;
          }
        }
      }
    }
  }
}

//=============================================================
//                  当たり判定
//=============================================================
int HitCheck( int tx, int ty, int tw, int th,
              int sx, int sy, int sw, int sh )
{
  if( ((sx > tx && sx < tx + tw) || (tx > sx && tx < sx + sw)) &&
      ((sy > ty && sy < ty + th) || (ty > sy && ty < sy + sh)) ){
    return 1;
  } else {
    return 0;
  }
これで実行すると、弾は敵機に当たると消えるのですが、敵機は消えません。
HitCheck関数に引数として敵機座標、弾座標を渡さないといけないのですが、
敵機と弾の処理は別関数で行っていて、渡し方がわかりません。
当たりのチェックはあってると思うのですが・・・

このコードの改良点やここはこうしないとダメというのを教えてください。
自分なりに納得するまで調べ、このコードの失敗を調べようと思います。

乱文失礼しました。
必要ならすべてのコードを載せます。返信お願いします。

Re: 当たり判定の処理を教えてください。

Posted: 2011年5月03日(火) 00:10
by h2so5
HitCheckに構造体を渡せば、もっとすっきりしたコードになると思います。

Re: 当たり判定の処理を教えてください。

Posted: 2011年5月03日(火) 00:17
by a5ua
138行目の
if( teki[ i ].F = 1 ){
は、
if( teki[ i ].F == 1 ){
の間違いですね。

なお、C言語では、0以外の値が真、0が偽と判定されるので、フラグのON,OFFを判定するときは、
if (flag) {// flagがONのとき
}
とか
if (!flag) { // flagがOFFのとき
}
のようにするとよいでしょう。(上記のようなミスもなくなりますし)

今回のコードでは、
if (HitCheck(~)) {
}
のようにも書けますね。

Re: 当たり判定の処理を教えてください。

Posted: 2011年5月03日(火) 00:36
by こーら
おおおおお!
出来ました!本当にありがとうございます!

if(flag) ~
なんて書き方できるんですね!これならミスは少なくなりそうです。
こういう書き方をもっと調べてみたいですね・・
よかったら記事として書いてほしい・・((

本当にありがとうございました!