2015-12-30 2 views
0

У меня есть модель планеты (внизу) и краска Солнца в центре экрана. Затем я рисую планеты, используя новый поток. Планеты движутся слишком быстро, а не означает, что это движение по кругу. Я попытался изменить время сна и скорость планеты и не имеет значения - планеты движутся слишком быстро. Velocity> 3 - слишком быстрая скорость.Как замедлить движение планеты по своей орбите?

Мне нужен результат: Планеты двигаются медленно, и я могу управлять скоростью планеты с ее скоростью (1, 3, 5, 10). Угол (положение планеты) меняется 1 раз в секунду на небольшом количестве (1, 3, 5 градусов - скорость)

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

Самое главное - не запускать анимацию изнутри paintComponent. Метод paintcomponent будет повторяться снова и снова, что означает, что вы будете создавать все больше и больше потоков анимации без необходимости, когда только один - это то, что требуется. Что еще хуже, у вас нет полного контроля над тем, когда или даже если вызывается paintComponent. Поэтому вместо этого запустите поток анимации один раз и, вероятно, в конструкторе вашего класса.

+0

Хорошо. Как я могу рисовать это без paintComponent? Я попытался сделать это без paintComponent - я вижу пустой черный экран. StartAnimation() Я перешел к конструктору. –

+0

@JAgeev: вам все равно нужно использовать paintComponent, чтобы сделать ваш рисунок для вас, но это все, что он должен делать. Он не должен иметь никакого кода, который запускает потоки или таймеры, и у него не должно быть никакого кода, который изменяет состояние объекта, только это изменяет внешний вид компонента. –

1

Рассмотрим следующие моменты

  1. Ваш метод startAnimation() должен вызываться только один раз, а не в paintComponent() метод, который будет создать экземпляр нового потока на каждом repaint()
  2. Помимо, соблюдающих angle двойной тип, как это позволит вам сделать сколь угодно малые приращения и сокращения.

  3. Thead.sleep() интервал должен быть единым сроком службы.

  4. Поддержание DAMPING_COFFICIENT умножить на velocity при расчете новых 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; 
    } 
} 

Rest классов

import java.awt.Color; 
import java.awt.Container; 
import java.awt.Graphics; 
import java.awt.Toolkit; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 

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 static final double DAMPING_COFFICIENT = 0.01; 
    private static final int FRAMES_PER_SECOND = 60; 
    private static final long FRAME_DURATION = (1000/FRAMES_PER_SECOND); 

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

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

    public void startAnimation() { 
     runner = new Thread() { 
      public void run() { 
       try { 
        while (!Thread.interrupted()) { 
         repaint(); 
         for (Planet p : planets) { 
          double angle = (p.getAngle() + p.getVelocity() * DAMPING_COFFICIENT); 

          //System.out.println(p.getName() + " : " + angle); 

          if (angle >= 360) 
           angle = 0; 
          p.setAngle(angle); 
         } 
         Thread.sleep(FRAME_DURATION); 
        } 
       } catch (Exception e) { 

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

.

+0

Красиво сделано, 1+ –

Смежные вопросы