Một thuật toán va chạm bóng chèo tinh vi hơn cho Breakout?


7

Tôi có một trò chơi đột phá đơn giản mà tôi đang làm việc. Mã va chạm là rắn; mọi thứ nảy lên như họ nên và không vượt qua mọi thứ hoặc làm những điều buồn cười khác, nhưng sự phản ánh là một chút đơn giản. Kết quả là, thật dễ dàng để đi vào trạng thái mà quả bóng bị mắc kẹt trong một vòng lặp sao cho các khối cuối cùng không thể bị đánh mà không chết để phá vỡ vòng lặp.

Hiện tại, mã va chạm mái chèo phản ánh tốc độ Y và phản ánh tốc độ X tùy thuộc vào phía nào của mái chèo mà nó chạm:

        // 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()));
            }
        }

Có cách nào tôi có thể làm cho thuật toán trở nên "thú vị" hơn không, và thắt chặt kiểm soát để quả bóng không bị kẹt khi nảy trong cùng một hình vuông?

Câu trả lời:


12

Sử dụng thang trượt để sửa đổi tốc độ X tùy thuộc vào vị trí trên mái chèo.

Đặt một số loại hằng số để thay đổi tốc độ X tối đa. Nếu quả bóng chạm vào phía bên phải của mái chèo, hãy thêm hằng số này vào tốc độ X. Nếu nó chạm vào phía bên trái của mái chèo, hãy trừ hằng số này khỏi tốc độ X. Nếu nó chạm vào giữa mái chèo, không ảnh hưởng đến tốc độ X.

Bất cứ nơi nào ở giữa, sử dụng thang trượt để xác định số lượng cần thêm hoặc trừ vào tốc độ X.


4

Rất nhiều game break out sẽ giới thiệu "spin". Nếu mái chèo di chuyển, nó sẽ ảnh hưởng đến hướng X của quả bóng theo hướng mái chèo đang di chuyển.


2

Jonathan,

Tôi sẽ làm như Erick gợi ý, nhưng tôi sẽ cẩn thận để đảm bảo các thành phần tốc độ X và Y được lồng vào nhau, nếu không tốc độ chung của quả bóng sẽ thay đổi đơn giản từ một va chạm với mái chèo, đó là vật lý phi thực tế.

Vì vậy, trước tiên tôi sẽ tính tốc độ tổng thể của quả bóng từ .speedX().speedY()(sử dụng định lý Pythagore), sau đó tính tốc độ X mới từ vị trí của quả bóng so với mái chèo, sau đó đặt tốc độ Y phụ thuộc vào chức năng của tốc độ X mới và tốc độ tổng thể ban đầu, để bóng chỉ thay đổi hướng (trong vô số góc có thể) nhưng luôn duy trì cùng tốc độ chung.

Nói một cách cụ thể hơn, tôi sẽ làm như thế nà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);
}

Lưu ý: Khi thời gian trôi qua, lỗi làm tròn sẽ khiến tốc độ chung trôi chậm so với giá trị ban đầu. Tốc độ tổng thể mong muốn có thể là thứ bạn muốn thêm dưới dạng dữ liệu thành viên m_ball(thay vì tính toán mỗi lần ở đây) hoặc có thể là thứ bạn muốn cho phép tăng tốc và làm chậm theo các yếu tố chơi trò chơi khác.


1
Đó là một cơ chế trò chơi phổ biến để từ từ tăng tốc độ cho đến khi ai đó thua cuộc. Nếu không bạn có thể chơi mãi mãi.
Erick Robertson

Đó là một điểm hay!
Todd Lehman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.