Перемещение фигур по дуге с помощью java-графики

Простите мою наивность, я здесь впервые и впервые имею дело с анимацией графики в java. Я пытаюсь выполнить анимацию звездных форм, которые движутся по своего рода дуге (пытаясь смоделировать орбиту в 2D). Орбитальное действие используется с таймером для анимации звезд.

Проще говоря, я нарисовал несколько звезд в разных позициях на jpanel. Перевод положения звезд по оси y зависит от того, насколько далеко эта звезда отстоит от оси заката x, которая инициализирована значением 300 (центр jpanel). Чем ближе звезда к точке заката, тем меньше изменится ее положение по оси y. Когда звезда достигает или пересекает правую сторону панели (или выходит из поля зрения), сбрасывается на левую сторону в исходное положение по оси Y (уродливо, я знаю). Я решил сделать это так, потому что звезды расположены случайным образом. Я не могу, чтобы все звезды начинались с одной и той же точки, иначе все звезды двигались бы по своей собственной дуге.

Однако, когда я запускаю это, после третьего прохода позиции x всех звезд становятся меньше (в отрицательных диапазонах и вне поля зрения). Любые предложения по лучшему способу выполнения первоначальной задачи приветствуются. Спасибо.

private Action orbit = new AbstractAction() {

    int declineAxis = 300; //if a stars top left x is greater than this, move downwards
    double distFromDecline;
    AffineTransform at = new AffineTransform();

    @Override
    public void actionPerformed(ActionEvent ae) {
        for (int i = 0; i < 12; i++) {
            distFromDecline = Math.abs(declineAxis - stars.getStar(i).getBounds().getCenterX());
            if (distFromDecline <= 50) {
                if (stars.getStar(i).getBounds().getX() < declineAxis) {
                    at.translate(5, -2);
                } else {
                    at.translate(5, 2);
                }
            } else if (distFromDecline <= 100 && distFromDecline > 50) {
                if (stars.getStar(i).getBounds().getX() < declineAxis) {
                    at.translate(5, -3);
                } else {
                    at.translate(5, 3);
                }
            } else if (distFromDecline <= 200 && distFromDecline > 100) {
                if (stars.getStar(i).getBounds().getX() < declineAxis) {
                    at.translate(5, -4);
                } else {
                    at.translate(5, 4);
                }
            } else if (distFromDecline >200) {
                if (stars.getStar(i).getBounds().getX() < declineAxis) {
                    at.translate(5, -5);
                } else {
                    at.translate(5, 5);
                }
            }
            stars.move(at, i);
        }
    }
};
public class Stars {

private int[] yOrigins;
private Path2D[] stars;
private Random rand = new Random();

public Stars(int n) {
    stars = new Path2D[n];
    yOrigins = new int[n];
    int dx = 700 / n;
    int x = 0;
    for (int i = 0; i < n; i++) {
        int y = rand.nextInt(401);
        generateStar(i, x, y);
        yOrigins[i] = y;
        x += dx;
    }
}

private void generateStar(int i, int x, int y) {
    stars[i] = new Path2D.Double();
    Path2D.Double cur = (Path2D.Double) stars[i];
    cur.moveTo(x, y);
    cur.lineTo(cur.getCurrentPoint().getX() + 6, y - 2);
    cur.lineTo(cur.getCurrentPoint().getX() + 2, cur.getCurrentPoint().getY() - 6);
    cur.lineTo(cur.getCurrentPoint().getX() + 2, cur.getCurrentPoint().getY() + 6);
    cur.lineTo(cur.getCurrentPoint().getX() + 6, cur.getCurrentPoint().getY() + 2);
    cur.lineTo(cur.getCurrentPoint().getX() - 6, cur.getCurrentPoint().getY() + 2);
    cur.lineTo(cur.getCurrentPoint().getX() - 2, cur.getCurrentPoint().getY() + 6);
    cur.lineTo(cur.getCurrentPoint().getX() - 2, cur.getCurrentPoint().getY() - 6);
    cur.closePath();
}

public void paintStars(Graphics2D g) {
    //super.paintComponent(g);
    g.setColor(new Color(246, 246, 255));
    for (int i = 0; i < stars.length; i++) {
        g.fill(stars[i]);
    }
}

public Shape getStar(int i) {
    return stars[i];
}

void move(AffineTransform at, int i) {
    stars[i] = (Path2D) stars[i].createTransformedShape(at);
    System.out.println(i+": " + stars[i].getBounds());
    if(stars[i].getBounds().getX()>700){
        at.translate(-(stars[i].getBounds().x+stars[i].getBounds().getWidth()), yOrigins[i]);
        stars[i] = (Path2D) at.createTransformedShape(stars[i]);
    }
}

}


person user1203349    schedule 11.02.2012    source источник
comment
Добро пожаловать в СО! Чтобы быстрее получить помощь, опубликуйте SSCCE.   -  person Andrew Thompson    schedule 11.02.2012


Ответы (2)


java.awt.geom.FlatteningPathIterator http://docs.oracle.com/javase/6/docs/api/java/awt/geom/FlatteningPathIterator.html

Вы передаете свою дугу (или любую другую фигуру) и используете точки для позиционирования звезды.

Вы можете использовать звездочки здесь http://java-sl.com/shapes.html

person StanislavL    schedule 11.02.2012
comment
Очень полезно, хотя ссылка доступна только через Archive.org сейчас. - person mhvelplund; 10.07.2014

WarpImage из демонстрации Sun/Oracle Java2D, java2d/demos/Images/WarpImage.java, является привлекательным примером анимации, которая следует за CubicCurve2D с использованием PathIterator. Вы можете увидеть, предлагает ли он какое-либо руководство.

person trashgod    schedule 11.02.2012
comment
@stanislavl Спасибо обоим, использование PathIterator решило мою проблему. не знал об использовании этой функции раньше. - person user1203349; 13.02.2012