画好的形状停止后一直在振动

Painted shape keeps vibrating after stopping

我试图通过创建一个从侧面弹跳并减速的球来重现一些物理现象。球在 x 方向上停止移动,但它在 y 方向上保持上下振动,就像只有 1 个像素一样。它还在底部边框上方执行此操作。

还有,我的代码readable/good是实践吗?

Bouncy.java

package Bouncy;

import javax.swing.*;

public class Bouncy {

    private static void createAndShowGui() {
        JFrame frame = new JFrame("Bouncy Balls");
        Board board = new Board();
        frame.getContentPane().add(board);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLocation(2000, 50);
        board.requestFocusInWindow();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

}

Board.java

package Bouncy;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Board extends JPanel implements ActionListener {

    public static final int BOARDWIDTH = 800;
    public static final int BOARDHEIGHT = 800;

    private Ball ball;

    public Board() {

        Dimension preferedDimension = new Dimension(BOARDWIDTH, BOARDHEIGHT);
        setPreferredSize(preferedDimension);
        ball = new Ball(15, 0);
        Timer animationTimer = new Timer(17, this);
        animationTimer.start();
    }

    public void actionPerformed(ActionEvent e) {
        ball.applyPhysics();
        repaint();
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHints(rh);

        ball.display(g2d);

        g2d.dispose();
    }
}

Ball.java

package Bouncy;

import java.awt.*;

public class Ball {

    private int xPos;
    private int yPos;
    private double dx;
    private double dy;
    private int ballWidth;
    private int ballHeight;

    public Ball() {
        this(0, 0);
    }

    public Ball(int dx, int dy) {
        ballWidth = 50;
        ballHeight = ballWidth;
        xPos = 0;
        yPos = 0;
        this.dx = dx;
        this.dy = dy;
    }

    public void applyPhysics() {
        bounceX();
        applyXFriction();
        bounceY();
    }

    public void bounceX() {
        if (xPos > Board.BOARDWIDTH - ballWidth) {
            xPos = Board.BOARDWIDTH - ballWidth;
            dx = -dx;
        } else if (xPos < 0) {
            xPos = 0;
            dx = -dx;
        } else {
            xPos += dx;
        }
    }

    public void applyXFriction() {
        final double xFriction = .95;

        if (yPos == Board.BOARDHEIGHT - ballHeight) {
            dx *= xFriction;
            if (Math.abs(dx) < .5) {
                dx = 0;
            }
        }
    }

    public void bounceY() {
        final int gravity = 12;
        final double energyLoss = .75;
        final double dt = .2;

        if (yPos > Board.BOARDHEIGHT - ballHeight){
            yPos = Board.BOARDHEIGHT - ballHeight;
            dy = -dy * energyLoss;
        } else if (yPos < 0) {
            yPos = 0;
            dy *= -energyLoss;
        } else {
            dy += gravity * dt;
            yPos += dy * dt + .5 * gravity * dt * dt;
        }
    }

    public void display(Graphics2D g2d) {
        g2d.fillOval(xPos, yPos, ballWidth, ballHeight);
    }
}

在应用摩擦方法中,将 dx 设置为 0,同时将 dy 设置为 0。这将阻止球沿 X 轴和 Y 轴移动

if (Math.abs(dx) < .5)
{
       dx = 0;
       dy = 0;
}

这将停止球的振动:

if (Math.abs(dy * dt + .5 * gravity * dt * dt) < 1.5 && yPos == Board.BOARDHEIGHT - ballHeight) 
{
    dy = 0;
    yPos = Board.BOARDHEIGHT - ballHeight;
}