有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java钟摆模拟只执行一个周期

我正在模拟一个钟摆,但它只执行一次摆动,然后发送接近随机位置的摆锤。本质上,它不会倒退

我曾尝试使用goingForward布尔值来改变方向,但仍然不起作用

public class AnimationPane extends JPanel {
    // START CHANGEABLE VARIABLES
    private double startAngle = -60.0; // degrees
    private double mass = 1; // kilogrammes
    private int radius = 10; // m
    private double gravity = 9.80665; // m/s^2 // on earth: 9.80665
    // END CHANGEABLE VARIABLEs
    private BufferedImage ball;
    private BufferedImage rope;
    private int pointX = 180;
    private int pointY = 50;
    private double endAngle = Math.abs(startAngle); // absolute value of startAngle
    private double angle = startAngle; // current angle
    private double circum = (2 * Math.PI * radius); // m
    private double distance = 0; // m
    private double velocity = 0; // m/s
    private double totalEnergy = ((radius) - (Math.cos(Math.toRadians(angle)) * radius)) * gravity * mass + 0.00001;
    private double previousE;
    private int xPos = 0; // for program
    private int yPos = 0; // for program
    private boolean goingForward = true;
    private double height = 0;

    public AnimationPane() {
        try {
            ball = ImageIO.read(new File("rsz_black-circle-mask-to-fill-compass-outline.png"));
            Timer timer = new Timer(100, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    double angleRad = Math.toRadians(Math.abs(angle));

                    double potentialE = ((radius) - (Math.cos(angleRad) * radius)) * gravity * mass;
                    Double pE = new Double(potentialE);
                    height = (radius - (Math.cos(angleRad) * radius));
                    double kineticE = totalEnergy - pE;

                    if (kineticE <= 0 || angle >= endAngle) {

                        if (goingForward == true) {
                            goingForward = false;
                        }
                        else 
                        {
                            goingForward = true; 
                        }
                        kineticE = 0.1; 
                        angle = 60;
                    }

                    velocity = Math.sqrt(2 * kineticE / mass);
                    double ratio = distance / circum;

                    if (goingForward == true) {                           
                        distance = distance + (velocity / 10);
                        angle = startAngle + (360 * ratio);
                    }
                    else {
                        distance = distance - (velocity / 10);
                        angle = startAngle - (360 * ratio);
                    }                        

                    double angles = Math.toRadians(angle);

                    double xDouble = Math.sin(angles) * (radius * 10);
                    Double x = new Double(xDouble);
                    xPos = x.intValue() + 150;

                    double yDouble = Math.cos(angles) * (radius * 10);
                    Double y = new Double(yDouble);
                    yPos = y.intValue() + 50;

                    repaint();
                }

            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();
        } catch (IOException ex) {
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.drawLine(xPos + 20, yPos + 20, pointX, pointY);
        g.drawImage(ball, xPos, yPos, this);

    }

}

我真的很感激你能帮我把这件事做好。 谢谢!


共 (1) 个答案

  1. # 1 楼答案

    我无法调试您的代码,这很难使用,有时也很难理解(您的代码中使用了大量整数文本,这隐藏了它们的语义,我不知道您对某些语句的意图是什么)

    因此,我用小振动微分方程的解重写了它。它是有效的,你可以把它作为一个干净的基础,以你想要的方式再次实现它。请注意,正如安迪·特纳(Andy Turner)所指出的,你不必担心前进或后退的事实。你有一个方程,你解了它,它给出了球在任何时候的位置。如果你想要大角度的精确数据,我建议你去维基百科看看这个例子中的运动方程。最后一个选项,你可以用数值方法求解微分方程,尽管我个人一眼就不知道怎么做

    package stackoverflow;
    
    public class AnimationPane extends JPanel {
        private static final long   serialVersionUID    = 1L;
        private static final double GRAVITY             = 9.80665;
    
        private BufferedImage ball;
    
        private final Point fixedCordPoint;
        private final int cordLength;
        private final double startAngle;
        private double currentAngle; 
    
        private final double pulsation;
        private final Point ballPos = new Point();
        private int time = 1;
    
        public AnimationPane(Point fixedCordPoint, int cordLength, double startAngleRadians) {
            this.fixedCordPoint = new Point(fixedCordPoint);
            this.cordLength     = cordLength;
            this.pulsation      = Math.sqrt(GRAVITY / cordLength);
            this.startAngle     = startAngleRadians;
            this.currentAngle   = startAngleRadians;
            this.ball           = loadImage(new File("ball.jpg"));
        }
    
        private BufferedImage loadImage(File file) {
            try {
                return ImageIO.read(file);
            } catch (IOException e) {
                throw new RuntimeException("Could not load file : " + file, e);
            }
        }
    
        public void start() {
            Timer timer = new Timer(100, event -> {
                ballPos.x = fixedCordPoint.x + (int) Math.round(Math.sin(currentAngle) * cordLength);
                ballPos.y = fixedCordPoint.y + (int) Math.round(Math.cos(currentAngle) * cordLength);
                repaint();
                currentAngle = startAngle * Math.cos(pulsation * time);
                time++;
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawLine(ballPos.x, ballPos.y, fixedCordPoint.x, fixedCordPoint.y);
            g.drawImage(ball, ballPos.x - ball.getWidth() / 2, ballPos.y - ball.getHeight() / 2, this);
        }
    
        public static void main(String[] args) {
            JFrame frame = new JFrame();
            AnimationPane pendulumAnimationPane = new AnimationPane(new Point(160, 25), 180, - Math.PI / 10);
            frame.setContentPane(pendulumAnimationPane);
            frame.setSize(400,400);
            frame.setVisible(true);
    
            pendulumAnimationPane.start();
        }
    }