使用Java图形处理技术沿弧形路径移动形状

3
请原谅我的幼稚,这是我第一次使用Java处理图形动画。我正在尝试制作一段星形动画,它沿着某种弧线(在二维空间中模拟轨道)移动。借助计时器和“轨道”操作来实现动画效果。
简单来说,我在JPanel中的不同位置绘制了几颗星星。星星的y坐标值取决于该星距离“下降”的x轴有多远,且“下降”的初始位置为300(即JPanel的中心)。靠近“下降”点的星星y坐标变化较小。当星星达到或超过面板右侧(或超出视野范围)时,将其重置到左侧以其原始y坐标位置(比较糟糕)。我之所以选择这样做,是因为星星位置随机分布。如果所有星星的dy相同,那么它们都会沿着自己的弧线移动。
然而,当我运行此代码时,在第三遍之后,所有星星的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]);
    }
}

}


欢迎来到SO!为了更快地获得更好的帮助,请发布一个SSCCE - Andrew Thompson
2个回答

3

java.awt.geom.FlatteningPathIterator是一个Java类,用于将曲线路径转换为由直线段组成的路径。具体使用方法可参考该链接

您可以传入圆弧(或其他形状),并使用点来定位星星。您可以从这里获取星形图案。


非常有用,尽管链接现在只能通过Archive.org访问。 - mhvelplund

2

WarpImage 是来自 Sun/Oracle Java2D demo 的一个示例,java2d/demos/Images/WarpImage.java,它展示了如何使用 PathIterator 来跟踪 CubicCurve2D 的动画效果。你可以参考一下这个示例来获取一些指导。


@stanislavl 感谢你们两位,使用PathIterator解决了我的问题。之前我并不知道这些特性的使用方法。 - user1203349

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接