1

この質問に対する他の回答があることを指摘する前に、この質問または同様の質問に対する他の回答のすべてではないにしても、ほとんどを見てきましたが、必要な解決策が見つかりませんでした。

基本的に私ができるようにしたいのは、円/ボールが長方形と衝突したときです。この衝突が長方形のどちら側で発生したかを判断したいのです。これを見つけて、もう少し現実的な物理学を強制できるようにしたいと思います。たとえば、ボールが長方形の上部に当たった場合、逆に Y 速度のみです...両方ではありません。

ボールと長方形の X と Y の位置、さらには両方のバウンディング ボックスの位置を比較してみました...ボールのボックスの下部が長方形の上部と交差しているかどうかをテストします... 'if ボールを使用して.boundingBox.Bottom >= 四角形.boundingBox.Top'.

私が達成しようとしていることを示すために、これに写真を添付し​​ました...詳細ではないため、少し混乱する場合に備えて...vのように見える赤いものは、ボールが片側から入った場合のパスです、インパクト時の動きを反対方向に移動させたいのですが、これは、ボールの速度のどのコンポーネントを変更する必要があるかについて、長方形の側面に依存します...

参考までに、ベクトルの正規化も調べました...これまで使用したことがないので、これを使用して解決できれば許してください...

読んでくれてありがとう

急いで編集します。代わりに別の画像を使用しました...図に示されている物理学は、ボールが他のボールと衝突したときにボールがどのように動作するかであるため、これはまだ達成しようとしている動作を示しています側面... 画像へのリンク: http://codeincomplete.com/posts/2011/6/12/collision_detection_in_breakout/bounce2.v283.png

4

1 に答える 1

6

このコードは必要以上に包括的であり、ニーズに合わせてリファクタリングできますが、完全な答えであり、移動する円とともに境界四角形を移動することで柔軟に使用できます。

これは、コードが何をしているかを視覚的に示すためのグラフィックです。赤い円は黒い四角形と交差しています。反対側の角を通る 2 本の架空の線を視覚化します。円が 2 つの線のそれぞれのどちら側にあるかがわかれば、衝突したエッジを推測できます。

ここに画像の説明を入力

最初にクラス スコープのプライベート メンバーを宣言する

Rectangle CollisionBoxRect;
Rectangle circleRect;
Dictionary<string, Vector2> corners;

円を移動してその位置と交差する可能性のあるボックスの位置を設定した後の更新では、円の境界四角形がブロックの境界四角形に関係しているかどうかを確認する基本的なチェックが行われます。その場合、円が衝突した長方形のどちら側に応じて、適切な衝突法線を使用してボールの速度を変更します。

if (CollisionBoxRect.Intersects(circleRect))
{
     ballVelocity = Vector2.Reflect(ballVelocity, GetCollisionNormal(CollisionBoxRect));
}

次のメソッドは、適切な側 (実際には法線) の取得をサポートしています。これらのメソッドのいくつかは、(get corners メソッドのように) 変更されない場合、初期化フェーズで 1 回実行できます。

private Vector2 GetCollisionNormal(Rectangle boxBeingIntersected)
{
    getCorners(boxBeingIntersected);
    bool isAboveAC = isOnUpperSideOfLine(corners["bottomRight"], corners["topLeft"], getBallCenter());
    bool isAboveDB = isOnUpperSideOfLine( corners["topRight"], corners["bottomLeft"], getBallCenter());

    if (isAboveAC)
    {
        if (isAboveDB)
        {
            //top edge has intersected
            return -Vector2.UnitY;
        }
        else
        {
            //right edge intersected
            return Vector2.UnitX;
        }
    }
    else
    {
        if (isAboveDB)
        {
            //left edge has intersected
            return -Vector2.UnitX;
        }
        else
        {
            //bottom edge intersected
            return Vector2.UnitY;
        }
    }
}

public bool isOnUpperSideOfLine(Vector2 corner1, Vector2 oppositeCorner, Vector2 ballCenter)
{
    return ((oppositeCorner.X - corner1.X) * (ballCenter.Y - corner1.Y) - (oppositeCorner.Y - corner1.Y) * (ballCenter.X - corner1.X)) > 0;
}

private Vector2 getBallCenter()
{
    return new Vector2(circleRect.Location.X + circleRect.Width / 2, circleRect.Location.Y + circleRect.Height / 2);
}

private void getCorners(Rectangle boxToGetFrom)
{
    corners.Clear();
    Vector2 tl = new Vector2(boxToGetFrom.X, boxToGetFrom.Y);
    Vector2 tr = new Vector2(boxToGetFrom.X + boxToGetFrom.Width, boxToGetFrom.Y);
    Vector2 br = new Vector2(boxToGetFrom.X + boxToGetFrom.Width, boxToGetFrom.Y + boxToGetFrom.Height);
    Vector2 bl = new Vector2(boxToGetFrom.X, boxToGetFrom.Y + boxToGetFrom.Height);
    corners.Add("topLeft", tl);
    corners.Add("topRight", tr);
    corners.Add("bottomRight", br);
    corners.Add("bottomLeft", bl);
}
于 2013-10-05T20:12:15.560 に答える