如何放慢行星在轨道上的运动?

时间:2015-12-30 18:45:58

标签: java multithreading swing animation graphics

我有一个行星模型(下图)并在屏幕中央绘制太阳。然后我用一个新线程绘制行星。行星移动太快并不意味着它是一个圆圈上的移动。我试图改变线程的睡眠时间和行星的速度并不重要 - 行星移动得太快。速度> 3 - 速度太快。

我需要结果:行星移动缓慢,我可以用她的速度(1,3,5,10)来管理行星的速度。角度(行星的位置)在少量(1,3,5度 - 速度)下以秒为单位改变1次

public class Planet
{
    private String name;
    private int id;
    private double radius = 1.0;
    private double radiusOrbit = 5.0;
    private double velocity = 1;
    private Color color;
    private int angle = 0;
    private String parent;

    public Planet(String name, int id, double rad, double radOrbit, double velocity, Color color)
    {
        this.name = name;
        this.id = id;
        this.radius = rad;
        this.radiusOrbit = radOrbit;
        this.velocity = velocity;
        this.color = color;
   }
...getters and setters
}

主类

public class ShowCosmos2 {
    public static void main(String[] args)
    {
        JFrame frame = new PlanetsFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

class PlanetsFrame extends JFrame
{

    private int width = Toolkit.getDefaultToolkit().getScreenSize().width;
    private int height = Toolkit.getDefaultToolkit().getScreenSize().height;
    public PlanetsFrame()
    {
        setSize(width, height);
        setTitle("Planets");

        setContentPane(new PlanetsCanvas(width, height));
        Container contentPane = getContentPane();
        contentPane.setBackground(Color.BLACK);
    }
}

class PlanetsCanvas extends JPanel
{
    private int width, height;
    private int centerX = 0;
    private int centerY = 0;
    private Thread runner;
    private boolean running = false;
    Planet[] planets = {
        new Planet("Venera", 1, 5.0, 50.0, 1, Color.GREEN),
        new Planet("Mercury", 1, 3.0, 75.0, 1.5, Color.ORANGE),
        new Planet("Earth", 1, 6.0, 100.0, 2, Color.BLUE),
        new Planet("Jupiter", 1, 12.0, 150.0, 1, Color.RED)
    };
    public PlanetsCanvas(int w, int h)
    {
        width = w;
        height = h;
        centerX = (int)(w/2);
        centerY = (int)(h/2);
    }

    protected void drawFrame(Graphics g)
    {
        //Sun
            g.setColor(Color.YELLOW);
            g.fillOval(width/2 - 25, height/2 - 25, 50, 50);
            for (int i = 0; i < planets.length; i++)
            {
                Planet p = planets[i];
                g.setColor(p.getColor());
                int newX = (int)(centerX + Math.cos(p.getAngle())*p.getRadiusOrbit());
                int newY = (int)(centerY - Math.sin(p.getAngle())*p.getRadiusOrbit());
                g.fillOval((int)(newX-p.getRadius()),
                        (int)(newY-p.getRadius()), 
                        (int)p.getRadius()*2, (int)p.getRadius()*2);
                //int angle = (int)(p.getAngle() + p.getVelocity());
                //if (angle >= 360) angle = 0;
                //p.setAngle(angle);
            }
    }

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        drawFrame(g);
        startAnimation();
    }

    public void startAnimation() {
        runner = new Thread() {
            public void run() {
                try {
                    while (!Thread.interrupted()) {
                        repaint();
                        for(int i=0; i<planets.length; i++)
                        {
                            Planet p = planets[i];
                            int angle = (int)(p.getAngle() + p.getVelocity());
                            if (angle >= 360) angle = 0;
                            p.setAngle(angle);
                        }
                        Thread.sleep(500);
                    }
                } catch (Exception e) {

                }
            }
        };
        runner.start();
        running = true;
    }
}

2 个答案:

答案 0 :(得分:2)

最重要的是 - 不要在paintComponent中启动动画。 paintcomponent方法将一直被反复调用,这意味着当只有一个被调用时,你将不必要地创建越来越多的动画线程。更糟糕的是,您无法完全控制何时或甚至调用paintComponent。因此,可以在类的构造函数中启动一次动画线程。

答案 1 :(得分:1)

考虑以下几点

  1. 您的WebView { id: responseWebPage objectName: "responseWebPage" accessibility.name: "responseWebPage" url: "local:///assets/initialcontent.html" onUrlChanged: { console.debug("URL is changed. New URL is " + responseWebPage.url); } } 方法应仅调用一次,而不是startAnimation()方法,它将在每个paintComponent()上实例化一个新主题
  2. 除此之外,请将repaint()保持为双重类型,因为这样可以对其进行任意小的增量和减量。

  3. angle间隔应为单帧时间。

  4. 在计算新Thead.sleep()以减慢或加速时,保持DAMPING_COFFICIENT乘以velocity
  5. 这是修改后的慢速代码。

    angle

    其他课程

    import java.awt.Color;
    
    public class Planet {
        private String name;
        private int id;
        private double radius = 1.0;
        private double radiusOrbit = 5.0;
        private double velocity = 1;
        private Color color;
        private double angle = 0;
        private String parent;
    
        public Planet(String name, int id, double rad, double radOrbit,
                double velocity, Color color) {
            this.name = name;
            this.id = id;
            this.radius = rad;
            this.radiusOrbit = radOrbit;
            this.velocity = velocity;
            this.color = color;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public double getRadius() {
            return radius;
        }
    
        public void setRadius(double radius) {
            this.radius = radius;
        }
    
        public double getRadiusOrbit() {
            return radiusOrbit;
        }
    
        public void setRadiusOrbit(double radiusOrbit) {
            this.radiusOrbit = radiusOrbit;
        }
    
        public double getVelocity() {
            return velocity;
        }
    
        public void setVelocity(double velocity) {
            this.velocity = velocity;
        }
    
        public Color getColor() {
            return color;
        }
    
        public void setColor(Color color) {
            this.color = color;
        }
    
        public String getParent() {
            return parent;
        }
    
        public void setParent(String parent) {
            this.parent = parent;
        }
    
        public double getAngle() {
            return angle;
        }
    
        public void setAngle(double angle) {
            this.angle = angle;
        }
    }