9

C++ で侵入者を殺すには、コライダーを作成する必要があることを知っています。ただし、そのゲームで侵略者を殺すものは何もありません。ヘッダーのコードは次のとおりです。

bool DoCollision(float Xbpos, float Ybpos, int BulWidth, int BulHeight, float Xipos, float Yipos, int InvWidth, int InvHeight);

これは私が初期化している関数です:

bool Game::DoCollision(float Xbpos, float Ybpos, int BulWidth, int BulHeight, float Xipos, float Yipos, int InvWidth, int InvHeight) {
if (Xbpos+BulWidth < Xipos || Xbpos > Xipos+InvWidth) return false;
if (Ybpos+BulHeight < Yipos || Ybpos > Yipos+InvHeight) return false;

return true;
}

誰かがスペース キーを押すと、次のようになります。

if (code == 57) { //Space
    myKeyInvader.MeBullet.Active = true;
    myKeyInvader.MeBullet.Xpos = myKeyInvader.Xpos + 10;
    myKeyInvader.MeBullet.Ypos = myKeyInvader.Ypos - 10;
    myKeyInvader.MeBullet.yvuel = 0.2;
    myKeyInvader.MeBullet.BulletP->CopyTo(m_Screen,myKeyInvader.Xpos,myKeyInvader.Ypos);

    if (DoCollision(Invaders[counter].MyBullet.Xbpos,Invaders[counter].MyBullet.Ybpos,Invaders[counter].MyBullet.BulWidth,
    Invaders[counter].MyBullet.BulHeight,Invaders[counter].Xipos,Invaders[counter].Yipos,Invaders[counter].InvWidth,Invaders[counter].InvHeight)) {
        //myKeyInvader.Ypos = 100;
        Invaders[counter].Active = false;
        printf("Collide!\n");
    }
}

何が問題なのか誰か知っていますか?

4

5 に答える 5

3

問題は C++ ではありません。問題は、それをどのように使用しているかです。書かれたコードでキルを得る唯一の方法は、侵入者があなたの真上にいる場合です。しかし、それでは遅すぎます。エイリアンの侵略者はすでにあなたを殺しています。

あなたがしなければならないことは、侵略者が時間の経過とともに伝播するオブジェクトであるのと同じように、それらの弾丸を時間の経過とともに伝播するオブジェクトにすることです. ユーザーがスペース キーを押すと、弾丸の新しいインスタンスがアクティブな弾丸のセットに追加されます。これらのアクティブな弾丸のそれぞれには、時間とともに変化する位置があります。各タイム ステップで、インベーダーの移動方法を規定するルールに従ってアクティブなインベーダーの状態を進め、弾丸の移動方法を規定するルールに従ってアクティブな弾丸の状態を進める必要があります。弾丸が画面の上部に到達したら削除し、エイリアンの侵略者が画面の下部に到達するとゲーム オーバーになります。

伝播、画面外の弾丸の除去、およびゲーム オーバーのチェックの後、N 個の弾丸のそれぞれと M 個のインベーダーのそれぞれとの衝突をチェックしたいと考えています。衝突が検出されたら、アクティブな弾丸のセットからその弾丸を削除し、アクティブなインベーダーのセットからエイリアン インベーダーを削除します。そしてもちろん、別のエイリアンがほこりを噛んだことをユーザーに示すために、気の利いたグラフィックが必要になるでしょう.

余談ですが、NxM の問題であるため、このチェックは CPU 使用率の最大の消耗となる可能性があります。いくつかの単純なヒューリスティックを使用して、これを高速化できます。

エイリアンの侵略者と弾丸のコレクションを自分で管理し、侵略者と弾丸がメモリ リークでプログラムを強制終了するのを防ぐために慎重にnewandを使用できます。deleteこれを行う必要はありません。C++ は、これらのコレクションを管理するための優れたツールを提供します。独自のコレクションをローリングする代わりに、C++ 標準ライブラリ コレクションの 1 つを使用します。たとえば、std::vector<AlienInvader> invaders;またはstd::list<AlienInvader> invaders、および箇条書きでも同じです。途中から削除することが多いため、ここよりも適切である可能性がありstd::listます。std::dequestd::vector

于 2012-10-19T11:06:12.077 に答える
2

発射されたアイテムが作成されたときに衝突をテストします

フレームごとに既存の各アイテムのメイン ループで衝突のテストを行うべきではありませんか?

于 2012-10-19T09:58:40.200 に答える
1

心配しないでください。C++ には侵入者を殺すために必要なものがすべて揃っています :)))

非常に小さなコードに基づいてアドバイスを与えるのは簡単ではありませんが、ここで唯一の論理的なエラーは、スペースが押されたときにのみ衝突をテストしているようです。おそらく外側のループでテストする必要があります:

if (code == 57) { //Space
    myKeyInvader.MeBullet.Active = true;
    myKeyInvader.MeBullet.Xpos = myKeyInvader.Xpos + 10;
    myKeyInvader.MeBullet.Ypos = myKeyInvader.Ypos - 10;
    myKeyInvader.MeBullet.yvuel = 0.2;
    myKeyInvader.MeBullet.BulletP->CopyTo(m_Screen,myKeyInvader.Xpos,myKeyInvader.Ypos);
}

論理的な観点からは、Space キーを押すと弾丸が発射されます。弾丸の開始位置が設定され、Y 軸上の速度も設定されます (上に移動します)。

衝突をチェックするコードは、このifブロックの外にある必要があります。実際、このコード ブロックは、まだスペースを押している場合 (つまり、発火している場合) にのみ実行されます。「まだ発砲している」場合にのみ衝突をチェックする必要がありますか? 弾丸を発射し、それが侵略者を破壊するのを待ち始めたという事実は、この弾丸が侵略者に到達し、実際に侵略者を破壊できるという事実と何らかの形で干渉しますか? もちろん違います!

if (DoCollision(Invaders[counter].MyBullet.Xbpos,Invaders[counter].MyBullet.Ybpos,Invaders[counter].MyBullet.BulWidth,
    Invaders[counter].MyBullet.BulHeight,Invaders[counter].Xipos,Invaders[counter].Yipos,Invaders[counter].InvWidth,Invaders[counter].InvHeight)) {
    //myKeyInvader.Ypos = 100;
    Invaders[counter].Active = false;
    printf("Collide!\n");
}

外側のループで衝突をチェックする必要があります。これには、おそらくキー押下のチェックも含まれます。このようにして、画面を見て待っているだけでも、プログラムは条件をテストし続け、それが満たされると、衝突イベントに関連付けられたコードが実行されます (つまり、侵入者は「非アクティブ化」されます)。

于 2012-10-19T10:27:12.097 に答える
0

コードは問題ないように見えますが、衝突チェッカーの周りに 2 つのループが必要です。1 つはすべての侵入者 (1 人だけでなく) をチェックするためのもので、もう 1 つは弾丸が銃を離れた瞬間だけでなく、弾道に沿ったすべての弾丸の位置をチェックするためのものです。

弾丸を移動し、まだ画面内にあるかどうかを返す補助関数があると仮定します。

bool BulletIsInScreen();

次に、ループを記述できます。

if (code == 57) { // Space
  while (BulletIsInScreen()) {
    for (size_t i = 0; i < counter; ++i) { // counter is the number of invaders,
                                           // according to your comment to your own answer
      myKeyInvader.MeBullet.Active = true;
      myKeyInvader.MeBullet.Xpos = myKeyInvader.Xpos + 10;
      myKeyInvader.MeBullet.Ypos = myKeyInvader.Ypos - 10;
      myKeyInvader.MeBullet.yvuel = 0.2;
      myKeyInvader.MeBullet.BulletP->CopyTo(m_Screen,myKeyInvader.Xpos,myKeyInvader.Ypos);

      if (DoCollision(Invaders[i].MyBullet.Xbpos, Invaders[i].MyBullet.Ybpos,
                      Invaders[i].MyBullet.BulWidth, Invaders[i].MyBullet.BulHeight,
                      Invaders[i].Xipos, Invaders[i].Yipos,
                      Invaders[i].InvWidth, Invaders[i].InvHeight)) {
        //myKeyInvader.Ypos = 100;
        Invaders[i].Active = false;
        printf("Collide!\n");
      }
    }
  }
}

これで期待どおりに動作するはずです。

于 2012-10-19T11:10:37.277 に答える
0

あなたは//Space、それが何であるか、または57ではなく32(ASCIIの場合)であるべきだと言いますか?プログラムは if==57 ブロックに流れますか?

于 2012-10-19T09:50:13.220 に答える