4

2 つのオブジェクト間で発生する可能性のあるすべての衝突を処理するための適切な方法を作成しようとしています。通常、一方が移動して他方にぶつかり、「跳ね返る」必要があります。

これまでに行ったこと (ボードがあり、レンガでボールをバウンドさせる典型的なゲームを作成しています) は、長方形が交差するかどうかを確認し、交差する場合は Y 速度を反転させることです。

これは非常に醜い一時的な解決策であり、長期的には機能しません。これはゲームでは非常に一般的な処理であるため、将来のプロジェクトでもこれを行うための優れた方法を見つけたいと思っています. リンクや役立つ情報は大歓迎です。

以下は、私の衝突処理関数が現在どのように見えるかです。

protected void collision()
    {
        #region Boundaries
        if (bal.position.X + bal.velocity.X >= viewportRect.Width ||
            bal.position.X + bal.velocity.X <= 0)
        {
            bal.velocity.X *= -1;
        }
        if (bal.position.Y + bal.velocity.Y <= 0)
        {
            bal.velocity.Y *= -1;
        }
        #endregion
        bal.rect = new Rectangle((int)bal.position.X+(int)bal.velocity.X-bal.sprite.Width/2, (int)bal.position.Y-bal.sprite.Height/2+(int)bal.velocity.Y, bal.sprite.Width, bal.sprite.Height);
        player.rect = new Rectangle((int)player.position.X-player.sprite.Width/2, (int)player.position.Y-player.sprite.Height/2, player.sprite.Width, player.sprite.Height);

        if (bal.rect.Intersects(player.rect))
        {
            bal.position.Y = player.position.Y - player.sprite.Height / 2 - bal.sprite.Height / 2;
            if (player.position.X != player.prevPos.X)
            {
                bal.velocity.X -= (player.prevPos.X - player.position.X) / 2;
            }

            bal.velocity.Y *= -1;
        }
        foreach (Brick b in brickArray.list)
        {
            b.rect.X = Convert.ToInt32(b.position.X-b.sprite.Width/2);
            b.rect.Y = Convert.ToInt32(b.position.Y-b.sprite.Height/2);
            if (bal.rect.Intersects(b.rect))
            {
                b.recieveHit();
                bal.velocity.Y *= -1;
            }
        }
        brickArray.removeDead();
    }
4

1 に答える 1

1

役立つ可能性のあるいくつかの提案を次に示します。

Playerまず第一に、Bal(それが何であるかわからない)などのすべてのオブジェクトとBrick、やや似たインターフェースを持っています-それらはすべてsprite(オブジェクトのサイズを定義する)、rect(オブジェクトの境界ボックス)、position(現在の位置)、velocity(現在の位置)を持っています速度)。これは、この機能をカプセル化する共通の基本クラスを作成できることを示唆しています。

また、現在のとrectに基づいて常に再計算していることにも注意してください。これは、実際には再計算を隠すプロパティであるべきであることを示唆しています (これは常に同じです!)positionspriterect

したがって、次のような共通の基本クラスを定義することから始めることができます (.NET 標準のコーディング スタイルに従い、プロパティとCamelCase名前を使用します)。

class GameObject {
  Point Position { get; set; } 
  Vector Velocity { get; set; }
  Sprite Sprite { get; set; }
  Rectangle Rect { 
    get { 
      // Ecnapsulated calculation of the bounding rectangle
      return new Rectangle
        ( (int)Position.X + (int)Velocity.X - Sprite.Width/2, 
          (int)Position.Y + (int)Velocity.Y - Sprite.Height/2, 
          Sprite.Width, Sprite.Height);   
    }
}    

この型をすべてのゲーム オブジェクトの基本クラスとして使用する場合は、次のように記述できるはずです。

protected void Collision() {      
    #region Boundaries        
    if (bal.Position.X + bal.Velocity.X >= viewportRect.Width ||        
        bal.Position.X + bal.Velocity.X <= 0)        
        bal.Velocity.X *= -1;        
    if (bal.Position.Y + bal.Velocity.Y <= 0)        
        bal.Velocity.Y *= -1;        
    #endregion

    if (bal.Rect.Intersects(player.Rect)) {      
        bal.Position.Y = player.Position.Y - player.Sprite.Height/2 
                       - bal.Sprite.Height/2;      
        if (player.Position.X != player.PrevPos.X)      
            bal.Velocity.X -= (player.PrevPos.X - player.Position.X) / 2;      
        bal.Velocity.Y *= -1;      
    }      
    foreach (Brick b in brickArray.list) {      
        if (bal.Rect.Intersects(b.Rect)) {      
            b.RecieveHit();      
            bal.Velocity.Y *= -1;      
        }      
    }      
    brickArray.RemoveDead();      
}      

また、関数を 2 つに分割することも良い考えのように思えます。1 つはブロックをチェックbalplayer、もう 1 つはブロックをチェックします。

于 2010-04-02T23:18:18.937 に答える