2

跳ねるボールのアプリケーションがあり、ボールが重ならないように拡張する必要があります。

ボールが別のボールと重なると、現実と同じように離れていくはずです。

ここに画像の説明を入力

MoveBall指定されたメソッドを拡張する必要があります:

        private void MoveBall()
    {
        prevX = x;
        prevY = y;
        x += xVelocity;
        y += yVelocity;

        // Is there too closed ball?

        foreach (Ball ball in parentForm.balls)
        {
            distance = Math.Sqrt(Math.Pow((double)(ball.prevX - prevX), 2) + 
                                 Math.Pow((double)(ball.prevY- prevY), 2));
            overlap = ((radius + ball.radius) - distance);// +ball.radius;

            if (ball.id != this.id && 
                ball.id != lastID &&
                overlap > 0)
            {
                lastID = this.id;
                if (xVelocity > 0) // roading right 
                {
                    xVelocity = -xVelocity;
                    x -= xVelocity - ball.xVelocity;
                }
                else if (xVelocity <= 0) // roading left 
                {
                    xVelocity = -xVelocity;
                    x += xVelocity + ball.xVelocity;
                }
                if (yVelocity > 0)
                { // going up
                    yVelocity = -yVelocity;
                    y -= yVelocity - ball.yVelocity;
                }
                else if (yVelocity <= 0) // down
                {
                    yVelocity = -yVelocity;
                    y += yVelocity + ball.yVelocity;
                }

            }
        }

        // ***********************************************
        // ***************** END MY CODE *****************
        if (x > parentForm.Width - 10 - (radius) || x < 0)
        {
            if (x < 0) x = 0;
            if (x > parentForm.Width - 10) x = parentForm.Width - 10 - radius;
            xVelocity = -xVelocity;
        }
        if (y > parentForm.Height - 40 - (radius) || y < 0)
        {
            if (y < 0) y = 0;
            if (y > parentForm.Height - 40) y = parentForm.Height - 40 - (radius);
            yVelocity = -yVelocity;
        }

    }

x、y、xVelocity、yVelocity、radius、prevX、prevY は int として宣言されます。

オーバーラップ、距離を 2 倍にします。

2枚重ねると引っかかる。なんで?

残念ながら、多くのモジュールがあるため、すべてのソース コードをアップロードすることはできません。Visual C# Express 2010 を使用しています。

4

2 に答える 2

2

明確に質問されていないので、「なぜボールがくっついているのか」という質問を想定します。

ソースコードに表示されているループは1つだけですが、それだけでは不十分です;-)考えられるすべての衝突をチェックするには、n *(n-1)/2の可能な衝突をチェックする必要があります。これは通常、2つのループで行われます。同じ衝突を2回処理しないように、注意深く対策を講じる必要があります。

ボールが動かなくなる理由は、同じ衝突を複数回処理するためです。たとえば、2つのボールが正確に水平に衝突します。左側のボールの速度は5、x位置は100です。もう1つのボールの位置は110、速度は-6です。衝突が発生したとき:

  1. xは105に設定されます。
  2. 衝突が検出されました:xは104に設定され、速度は-5に設定されています。
  3. もう一方のボールは同じ衝突を処理します。
  4. 彼は速度に応じて104の位置に移動します。
  5. 衝突処理:彼の速度は6になり、位置は105になります。

ボールはそれぞれ100と110でした。速度は互いに離れる方向を向いていますが、次の手順での衝突処理により、速度が再び反転します。そのため、位置は互いに接近しており、速度はフレームごとに符号が変化しています。ボールは「互いにくっついている」ように見えます。

答えがあなたの問題を理解するのに役立つことを願っています。弾性衝突(各衝突を1回だけ処理する)のより良い実装については、ここを参照してください:ボールからボールへの衝突-検出と処理

于 2013-01-13T21:10:13.483 に答える
0

衝突検出アルゴリズムを初めて試みたときに同様の問題に出くわしたので、ここで問題と思われるものについて説明します。

おそらく、ボールが十分に速く移動するため、コードによって衝突が検出される前に、ボールはすでに部分的に「内側」にある可能性があります。衝突検出が来てそれに気づくと、本来のことを行います。つまり、発生した衝突の詳細に従って、オブジェクトの計画された軌道を変更します。問題は、これらのオブジェクトは、衝突検出がキャッチする前に一種の「マージ」されたため、衝突検出が再び起動されて互いにトラップされるため、スタックを解除できないことです。

これが問題の原因である場合、上記のコードは十分に小さい速度ベクトルで機能する可能性があります。もちろん、それは本当の解決策ではありませんが、もしそれが非常に小さな速度でうまくいくなら、おそらく私の仮説を裏付けるものであり、あなたはどのように進めるかについて何らかのアイデアを持っています.

于 2013-01-13T20:43:48.320 に答える