ブレイクアウトのためのより洗練されたボールパドル衝突アルゴリズム?


7

私が取り組んでいる簡単なブレイクアウトゲームがあります。衝突コードはしっかりしています。物事はあるべきように跳ね返り、物事を通過したり他のファンキーさを行ったりしませんが、反射は少し単純化しています。その結果、ボールがループにスタックしてしまい、ループを壊すことなく最後のブロックを打てない状態になりやすい。

現在、パドル衝突コードはY速度を反映しており、パドルのどちら側に当たるかに応じてX速度を反映しています。

        // Check for paddle collisions
        if ((m_ball.rect()).intersects(m_paddle.rect())) {
            double ballCenter = m_ball.rect().getX() + (m_ball.rect().getWidth()/2);
            double paddleCenter = m_paddle.rect().getX() + (m_paddle.rect().getWidth()/2);

            m_ball.setSpeedY(m_ball.speedY() * -1);

            if (ballCenter > paddleCenter) {
                m_ball.setSpeedX(Math.abs(m_ball.speedX()));
            } else {
                m_ball.setSpeedX(-Math.abs(m_ball.speedX()));
            }
        }

アルゴリズムをより「興味深い」ものにして、ボールが同じ四角形でバウンドし続けないようにコントロールを強化する方法はありますか?

回答:


12

スライドスケールを使用して、パドル上の位置に応じてX速度を変更します。

X速度を最大に変更するには、定数を設定します。ボールがパドルの右端に当たった場合は、この定数をX速度に追加します。パドルの左端に当たった場合は、X速度からこの定数を差し引きます。パドルの真ん中に当たった場合は、X速度に影響を与えないでください。

その間のどこでも、スライドスケールを使用して、X速度に加算または減算する量を決定します。


4

ブレイクアウトゲームの多くは「スピン」を導入します。パドルが動いている場合、パドルが動いている方向のボールのX方向に影響します。


2

ジョナサン、

私はエリックが示唆するように行いますが、XとYの速度コンポーネントが連動していることを確認するように注意します。そうしないと、ボールの全体的な速度がパドルとの衝突から単純に変化します。これは非現実的な物理です。

私は最初からボールの全体的な速度を計算しますので、.speedX()および.speedY()(ピタゴラスの定理を使用して)、その後、パドルに対するボールの位置から新しいX速度を計算し、新しいX速度の関数に依存してY速度を設定元の全体速度。これにより、ボールは(無限の可能な角度で)方向を変えるだけで、常に同じ全体速度を維持します。

具体的には、次のようにします。

if ((m_ball.rect()).intersects(m_paddle.rect())) {
    double ballWidth = m_ball.rect().getWidth();
    double ballCenterX = m_ball.rect().getX() + ballWidth/2;
    double paddleWidth = m_paddle.rect().getWidth();
    double paddleCenterX = m_paddle.rect().getX() + paddleWidth/2;
    double speedX = m_ball.speedX();
    double speedY = m_ball.speedY();

    // Applying the Pythagorean theorem, calculate the ball's overall
    // speed from its X and Y components.  This will always be a
    // positive value.
    double speedXY = Math.sqrt(speedX*speedX + speedY*speedY);

    // Calculate the position of the ball relative to the center of
    // the paddle, and express this as a number between -1 and +1.
    // (Note: collisions at the ends of the paddle may exceed this
    // range, but that is fine.)
    double posX = (ballCenterX - paddleCenterX) / (paddleWidth/2);

    // Define an empirical value (tweak as needed) for controlling
    // the amount of influence the ball's position against the paddle
    // has on the X speed.  This number must be between 0 and 1.
    final double influenceX = 0.75;

    // Let the new X speed be proportional to the ball position on
    // the paddle.  Also make it relative to the original speed and
    // limit it by the influence factor defined above.
    speedX = speedXY * posX * influenceX;
    m_ball.setSpeedX(speedX);

    // Finally, based on the new X speed, calculate the new Y speed
    // such that the new overall speed is the same as the old.  This
    // is another application of the Pythagorean theorem.  The new
    // Y speed will always be nonzero as long as the X speed is less
    // than the original overall speed.
    speedY = Math.sqrt(speedXY*speedXY - speedX*speedX) *
             (speedY > 0? -1 : 1);
    m_ball.setSpeedY(speedY);
}

注:時間が経過すると、丸め誤差により全体の速度が元の値からゆっくりとドリフトします。望ましい全体的な速度は、m_ball(ここでは毎回計算するのではなく)メンバーデータとして追加したいものかもしれませんし、他のゲームプレイ要素に従って加速したり減速したりしたいものかもしれません。


1
誰かが負けるまでゆっくりとボールをスピードアップすることは一般的なゲームメカニックです。そうでなければ、あなたは永遠に遊ぶことができます。
エリックロバートソン

それは良い点です!
トッドリーマン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.