Java图像沿列表中的点移动并使用线性插值

时间:2015-03-10 10:31:54

标签: java

我试图让图片沿路径行进。该路径的点存储在ArrayList中。现在图像每两秒跳到下一个点,所以我必须使用线性插值来使运动平滑。但是如何在update()方法中使用线性插值?我在网上搜索过这个问题,但是在更新方法中找不到关于线性插值的更多信息,结合带有点的ArrayList。

更新方法

public void update(){

    repaint();
    if(counter < Lane.firstLane.size()){

        startPoint = new Point(carPosition.x, carPosition.y);
        endPoint = new Point(Lane.firstLane.get(counter).x, Lane.firstLane.get(counter).y);
        pointOnTimeLine = new Point(startPoint);
        Timer timer = new Timer(40, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (startTime == null) {
                    startTime = System.currentTimeMillis();
                }
                long now = System.currentTimeMillis();
                long diff = now - startTime;
                if (diff >= playTime) {
                    diff = playTime;
                    ((Timer) e.getSource()).stop();
                }
                double i = (double) diff / (double) playTime;
                pointInTime = i;

                //pointOnTimeLine.x = (int) (startPoint.x + ((endPoint.x - startPoint.x) * i));
                //pointOnTimeLine.y = (int) (startPoint.y + ((endPoint.y - startPoint.y) * i));

                //carPosition.setLocation(pointOnTimeLine);
                carPosition.x=(int) lerp(startPoint.x,endPoint.x,i);                       
                carPosition.y=(int)lerp(startPoint.y,endPoint.y,i);

                System.out.println("Car position: x"+carPosition.x+": y"+carPosition.y );
                //System.out.println("Point"+pointOnTimeLine);

                repaint();
                counter++;
            }
        });
        timer.start();

     }
    else{
        //System.out.println("Destination reached");
    }


   //carPosition.x+=1;
   //repaint();    


}


double lerp(double a, double b, double t) {
    return a + (b - a) * t;
}

移动汽车的线程

public void moveCar() {
    Runnable helloRunnable = new Runnable() {
        public void run() {

           car.update();
           repaint();


        }
    };

    ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
    executor.scheduleAtFixedRate(helloRunnable, 0, 40, TimeUnit.MILLISECONDS);
}

Lane.cs

public class Lane {

     public static List<Point> firstLane = new ArrayList<>(Arrays.asList(new Point(10,135),new Point(124,190),new Point(363,190),new Point(469,210)));

}

编辑:我根据MadProgrammers的建议对我的代码进行了更改。动画现在可以在这里播放动画电影http://gyazo.com/e6a28b87cb905c0ff5eb023d68955321。我的OP用我当前的代码更新。下一步是转弯部分,但我认为有一种更加优雅的方式来调用汽车更新方法并在moveCar中重绘()。我已经将此线程中的时间指定为与计时器(40ms)中相同的长度。有没有更好的方法来调用car.update()并在moveCar()中重新绘制?

1 个答案:

答案 0 :(得分:3)

让我们打破这个......

基本上,您希望在一段时间内(A)从一个点(B)移动到另一个点(t)。在给定时间点AB之间的给定点是两者之间差异的百分比(其中t被归一化为0到1之间的分数)

Timeline

因此,如果A10B20t为2秒,则1秒p应为{ {1}} 15)其中((B - A) * i) + Ai的标准化时差(2秒的50%= 1秒)

因此,给定任何时间点,您可以计算两点之间的差异并计算它应该处于的位置。

如果您想知道为什么我将时间标准化,请考虑一下,如果您将0.5更改为4秒,则计算不会更改,我们只需要计算标准化时间点({ {1}})并在计算中运行,以便为我们提供所需的结果。

因此,您需要知道从点t到点1 / 4 = 0.25需要多长时间。然后你需要一些机制,可以定期检查已经过的时间量,并计算两点之间的对象的当前位置。为此,您可以使用Swing A定期打勾(例如40毫秒)直到2秒钟。

Move from A to B

B

好的,“但这对我有什么帮助?”我听你问。嗯,实际情况是,这是在多个点之间移动的基础。

在你的代码中,你有4个关键点,时间均匀分布,对象必须移动,这意味着每个点沿着时间线大约相差33%。

当您计算沿时间线的当前位置时,您需要找到它之间的两个点(0-33是第一个和第二个点,34-66是第二个和第三个点,67&gt;是然后计算这些点之间物体的位置。

这有点复杂,因为你需要考虑两点之间的时间量作为所有时间的一小部分,但由于点之间的时间距离大多是均匀的,所以它不应该发挥重要作用。

这已展示herehere,因此您必须原谅我不再重新发布代码。

现在,为了我的钱,我还​​花了一些时间来了解动画库,如Timing Framework和/或Trident和/或Universal Tween Engine