2015-05-25 16 views
0

我試圖讓我的Pedestrian對象移動,並且它移動,但在某個點它飛離屏幕。 Pedestrian移動List點。首先Pedestrian被添加到toDraw來畫它,並在startAndCreateTimer我通過相同的列表循環移動Vehicles也許這是因爲這條線i = (double) diff/(double) playTime;我其實不想設置播放時間怎麼不這樣做,這可能是問題還是其他問題?在這裏與Pedestrian飛走的點(從左環島的北邊開始)http://gyazo.com/23171a6106c88f1ba8ca438598ff4153JPanel圖像從屏幕飛逝

class Surface extends JPanel{ 

Track track=new Track();  
public List<Vehicle> toDraw = new ArrayList<>(); 
private Long startTime; 
private long playTime = 4000; 
private double i; 

public Surface(){ 
    startAndCreateTimer(); 
} 

@Override 
public void paintComponent(Graphics g) { 

    super.paintComponent(g);  
    //Make sure the track is painted first 
    track.paint(g); 

    for (Vehicle v : toDraw) { 
     v.paint(g); 
    } 


} 

public void repaintPanel(){ 
    this.repaint(); 
} 

private void startAndCreateTimer(){ 

    Timer timer = new Timer(100, new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       if (startTime == null) { 
        startTime = System.currentTimeMillis(); 
       } 
       long now = System.currentTimeMillis(); 
       long diff = now - startTime; 

       i = (double) diff/(double) playTime; 

       for (Vehicle v : toDraw){ 
       v.update(i); 
       } 


       repaintPanel(); 

      } 
     }); 
     timer.start(); 

    } 
} 

行人的Java

public class Pedestrian extends Vehicle { 

BufferedImage pedestrian; 
Point pedestrianPosition; 
double pedestrianRotation = 0; 
int pedestrianW, pedestrianH; 
int counter=0; 
List<LanePoint>pedestrianPath; 
boolean lockCounter=false; 

public Pedestrian(int x, int y){ 
    try { 
     pedestrian = ImageIO.read(Car.class.getResource("images/human.png")); 
    } catch (IOException e) { 
     System.out.println("Problem loading pedestrian images: " + e); 
    } 

    pedestrianPosition = new Point(x,y); 
    pedestrianW = pedestrian.getWidth(); 
    pedestrianH = pedestrian.getHeight(); 
} 

@Override 
public void paint(Graphics g) { 
    Graphics2D g2d = (Graphics2D) g.create(); 
    g2d.rotate(Math.toRadians(pedestrianRotation), pedestrianPosition.x, pedestrianPosition.y); 
    g2d.drawImage(pedestrian, pedestrianPosition.x, pedestrianPosition.y, null); 
} 


@Override 
public void setPath(List<LanePoint> path) { 
    pedestrianPath=path; 
} 

/*Update*/ 
@Override 
public void update(double i){ 


    if (counter < pedestrianPath.size()) {    
     Point startPoint = new Point(pedestrianPosition.x, pedestrianPosition.y); 
     LanePoint endPoint = new LanePoint(pedestrianPath.get(counter).x, pedestrianPath.get(counter).y,pedestrianPath.get(counter).lanePointType,pedestrianPath.get(counter).lanePointToTrafficLight,pedestrianPath.get(counter).laneTrafficLightId,pedestrianPath.get(counter).degreesRotation); 

     pedestrianPosition.x=(int)Maths.lerp(startPoint.x,endPoint.x,i);     
     pedestrianPosition.y=(int)Maths.lerp(startPoint.y,endPoint.y,i); 
     pedestrianRotation=endPoint.degreesRotation; 


     if(pedestrianPosition.equals(new Point(endPoint.x,endPoint.y))){ 
      /*PEDESTRIAN SIGN UP*/ 
      if (endPoint.lanePointType.equals(LanePoint.PointType.TRAFFICLIGHT) && endPoint.lanePointToTrafficLight.equals(LanePoint.PointToTrafficLight.INFRONTOF)){ 
       try { 
        Roundabout.client.sendBytes(new byte []{0x03,endPoint.laneTrafficLightId.byteValue(),0x01,0x00}); 
       } catch (IOException ex) { 
        ex.printStackTrace(); 
       } 
      } 
      /*PEDESTRIAN SIGN OFF*/ 
      else if (endPoint.lanePointType.equals(LanePoint.PointType.TRAFFICLIGHT) && endPoint.lanePointToTrafficLight.equals(LanePoint.PointToTrafficLight.UNDERNEATH)) {           
       if (Surface.trafficLights.get(endPoint.laneTrafficLightId).red) { 
        lockCounter = true; 
       } else { 
        try { 
         Roundabout.client.sendBytes(new byte[]{0x03, endPoint.laneTrafficLightId.byteValue(), 0x00, 0x00}); 
         lockCounter=false; 
        } catch (IOException ex) { 
         ex.printStackTrace(); 
        } 
       }     
      } 
      if (!lockCounter) { 
       counter++; //Increment counter > sets next point 
      } 
     } 
    } 
    } 
} 

Maths.java

public class Maths { 

    //Lineat interpolation 
    public static double lerp(double a, double b, double t) { 
     return a + (b - a) * t; 
    } 

} 
+0

什麼當'diff'> ='startTime'時會發生? – MadProgrammer

+1

考慮提供一個[runnable示例](https://stackoverflow.com/help/mcve),它演示你的問題。這不是代碼轉儲,而是您正在做的事情的一個例子,它突出了您遇到的問題。這會導致更少的混淆和更好的響應 – MadProgrammer

+0

@MadProgrammer當'diff> = startTime'時沒有任何反應,我認爲圖像因爲playTime而飛走了,只要程序運行時間不超過4000毫秒,怎麼做,或者這可能不會導致我的問題? – Sybren

回答

2

所以,基本上你是計算對象的基於已過去的時間量點之間的位置。這很好。

所以在t = 0,對象將在起始點,在t = 0.5,它將在開始和結束點之間的一半,在t = 1.0它將在終點。

t > 1.0會發生什麼情況?對象應該在哪裏? - 提示,它應該是無處因爲它應該已被刪除或重置...

Thisthis是「時間線」的基礎動畫的基本的例子,這意味着,在一段時間內,物體的位置(沿時間線)

所以,爲了計算沿着一條線的位置,你需要三件事:你開始的點,你想要結束的點和持續時間(在0-1之間)

使用這些,您可以根據時間量計算這兩點之間的線上的點。

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Line2D; 
import java.awt.geom.Point2D; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public static class TestPane extends JPanel { 

     protected static final double PLAY_TIME = 4000.0; 

     private Point2D startAt = new Point(0, 0); 
     private Point2D endAt = new Point(200, 200); 
     private Point2D current = startAt; 
     private Long startTime; 

     public TestPane() { 
      Timer timer = new Timer(40, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        if (startTime == null) { 
         startTime = System.currentTimeMillis(); 
        } 
        long time = System.currentTimeMillis() - startTime; 
        double percent = (double) time/PLAY_TIME; 
        if (percent > 1.0) { 
         percent = 1.0; 
         ((Timer) e.getSource()).stop(); 
        } 

        current = calculateProgress(startAt, endAt, percent); 
        repaint(); 
       } 
      }); 
      timer.start(); 
     } 

     protected Point2D calculateProgress(Point2D startPoint, Point2D targetPoint, double progress) { 

      Point2D point = new Point2D.Double(); 

      if (startPoint != null && targetPoint != null) { 

       point.setLocation(
           calculateProgress(startPoint.getX(), targetPoint.getY(), progress), 
           calculateProgress(startPoint.getX(), targetPoint.getY(), progress)); 

      } 

      return point; 

     } 

     protected double calculateProgress(double startValue, double endValue, double fraction) { 

      return startValue + ((endValue - startValue) * fraction); 

     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      g2d.setColor(Color.GREEN); 
      g2d.draw(new Line2D.Double(startAt, endAt)); 
      g2d.setColor(Color.RED); 
      g2d.fill(new Ellipse2D.Double(current.getX() - 5, current.getY() - 5, 10, 10)); 
      g2d.dispose(); 
     } 

    } 

} 

因此,使用current = calculateProgress(startAt, endAt, percent);

NiceMove

你可以看到點移動平均的起點和終點之間。

如果我們改變它的東西更像你彷彿在做,current = calculateProgress(current, endAt, percent);

BadMove

你可以看到,它加速了線,終於緩出,這是不是你真想......

與時間線理論更新

讓我們想象一下,你有一個時間線,其中有長度並且沿着這條時間線,您有5個事件(或關鍵幀)(e1 - e5),每個事件發生在彼此之後。

e1開始在0e51

Time Line

結束正如你可以看到以不規則的間隔,發生的事件和運行的時間長度不同。

  • T1的時間線
  • T2的時間線
  • T3的時間線的12.5%運行的25%運行的25%運行
  • T3爲時間37.5%運行line

因此,根據t,您需要確定哪些事件已被執行。所以當t0.12時,我們正在運行大約一半通過t1(在e1 & e2之間)。

然後你需要(沿時間軸0-0.25)計算本地時間/關鍵幀之間的差異

localTime = 1.0 - ((t - e1)/(e2 - e1)) 
      = 1.0 - ((0.12 - 0)/(0.25 - 0)) 
      = 1.0 - (0.12/0.25) 
      = 1.0 - 0.48 
      = 0.52 

哪裏t是沿着時間線的時候,e1是第一個事件的時間(0)和e2是第二事件(0.25),這使我們沿着t1的持續時間(在這個例子中)

這是那麼對於給定的時間片的線性內插的值的時間。

Runnable的例子...

我看看你的代碼,但還有很多工作需要做才能得到這個工作。

基本上,您需要知道路徑的長度以及每個段的路徑數量(以百分比表示)。有了這個,我們可以創建一個「關鍵幀」的「時間線」,它決定了對象基於已經過去的時間量和「應該」行進的時間量。

所以,我做的第一件事是創建一個Path類(一種模仿你的List S的,但有一些額外的方法)

public class Path implements Iterable<Point> { 

    private List<Point> points; 
    private double totalLength = 0; 

    public Path(Point... points) { 
     this.points = new ArrayList<>(Arrays.asList(points)); 
     for (int index = 0; index < size() - 1; index++) { 
      Point a = get(index); 
      Point b = get(index + 1); 
      double length = lengthBetween(a, b); 
      totalLength += length; 
     } 
    } 

    public double getTotalLength() { 
     return totalLength; 
    } 

    public int size() { 
     return points.size(); 
    } 

    public Point get(int index) { 
     return points.get(index); 
    } 

    public double lengthBetween(Point a, Point b) { 

     return Math.sqrt(
         (a.getX() - b.getX()) * (a.getX() - b.getX()) 
         + (a.getY() - b.getY()) * (a.getY() - b.getY())); 

    } 

    @Override 
    public Iterator<Point> iterator() { 
     return points.iterator(); 
    } 

} 

大多數情況下,這提供了路徑的totalLength。我們用這個來計算每段多少佔用後

我再從this以前的回答借用TimeLine類現在

public class Timeline { 

    private Map<Double, KeyFrame> mapEvents; 

    public Timeline() { 
     mapEvents = new TreeMap<>(); 
    } 

    public void add(double progress, Point p) { 
     mapEvents.put(progress, new KeyFrame(progress, p)); 
    } 

    public Point getPointAt(double progress) { 

     if (progress < 0) { 
      progress = 0; 
     } else if (progress > 1) { 
      progress = 1; 
     } 

     KeyFrame[] keyFrames = getKeyFramesBetween(progress); 

     double max = keyFrames[1].progress - keyFrames[0].progress; 
     double value = progress - keyFrames[0].progress; 
     double weight = value/max; 

     return blend(keyFrames[0].getPoint(), keyFrames[1].getPoint(), 1f - weight); 

    } 

    public KeyFrame[] getKeyFramesBetween(double progress) { 

     KeyFrame[] frames = new KeyFrame[2]; 
     int startAt = 0; 
     Double[] keyFrames = mapEvents.keySet().toArray(new Double[mapEvents.size()]); 
     while (startAt < keyFrames.length && keyFrames[startAt] <= progress) { 
      startAt++; 
     } 

     if (startAt >= keyFrames.length) { 
      startAt = keyFrames.length - 1; 
     } 

     frames[0] = mapEvents.get(keyFrames[startAt - 1]); 
     frames[1] = mapEvents.get(keyFrames[startAt]); 

     return frames; 

    } 

    protected Point blend(Point start, Point end, double ratio) { 
     Point blend = new Point(); 

     double ir = (float) 1.0 - ratio; 

     blend.x = (int) (start.x * ratio + end.x * ir); 
     blend.y = (int) (start.y * ratio + end.y * ir); 

     return blend; 
    } 

    public class KeyFrame { 

     private double progress; 
     private Point point; 

     public KeyFrame(double progress, Point point) { 
      this.progress = progress; 
      this.point = point; 
     } 

     public double getProgress() { 
      return progress; 
     } 

     public Point getPoint() { 
      return point; 
     } 

    } 

} 

,因爲他們的立場,他們是不兼容的,我們需要每個段並計算段長度作爲路徑總長度的百分比,併爲時間線上的指定點創建關鍵幀...

double totalLength = path.getTotalLength(); 
timeLine = new Timeline(); 
timeLine.add(0, path.get(0)); 
// Point on time line... 
double potl = 0; 
for (int index = 1; index < path.size(); index++) { 
    Point a = path.get(index - 1); 
    Point b = path.get(index); 
    double length = path.lengthBetween(a, b); 
    double normalised = length/totalLength; 
    // Normalised gives as the percentage of this segment, we need to 
    // translate that to a point on the time line, so we just add 
    // it to the "point on time line" value to move to the next point :) 
    potl += normalised; 
    timeLine.add(potl, b); 
} 

我故意這樣做,以顯示你將需要做的工作。

極品,我創建了一個Ticker,它只是運行一個Swing Timer和報告tick s到Animation小號

public enum Ticker { 

    INSTANCE; 

    private Timer timer; 
    private List<Animation> animations; 

    private Ticker() { 
     animations = new ArrayList<>(25); 
     timer = new Timer(5, new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       // Prevent possible mutatation issues... 
       Animation[] anims = animations.toArray(new Animation[animations.size()]); 
       for (Animation animation : anims) { 
        animation.tick(); 
       } 
      } 
     }); 
    } 

    public void add(Animation animation) { 
     animations.add(animation); 
    } 

    public void remove(Animation animation) { 
     animations.remove(animation); 
    } 

    public void start() { 
     timer.start(); 
    } 

    public void stop() { 
     timer.stop(); 
    } 

} 

public interface Animation { 

    public void tick(); 

} 

這集中了「時鐘」,是允許Animation s到確定他們想要做什麼每個tick。這應該是更大的可擴展性,然後創造幾十個Timer s

好吧,這是所有的樂趣和遊戲,但它是如何一起工作?那麼,這是一個完整的可運行示例。

它採用自己的一條路徑,並創建一個TimeLine,併爲其移動一個對象。

FollowMeHome

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Path2D; 
import java.text.NumberFormat; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Iterator; 
import java.util.List; 
import java.util.Map; 
import java.util.TreeMap; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       Path path = new Path(
           new Point(440, 40), 
           new Point(440, 120), 
           new Point(465, 90), 
           new Point(600, 180), 
           new Point(940, 165), 
           new Point(940, 145), 
           new Point(1045, 105), 
           new Point(1080, 120), 
           new Point(1170, 120), 
           new Point(1200, 120), 
           new Point(1360, 123), 
           new Point(1365, 135), 
           new Point(1450, 170), 
           new Point(1457, 160), 
           new Point(1557, 160)); 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane(path)); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 

       Ticker.INSTANCE.start(); 
      } 
     }); 
    } 

    public enum Ticker { 

     INSTANCE; 

     private Timer timer; 
     private List<Animation> animations; 

     private Ticker() { 
      animations = new ArrayList<>(25); 
      timer = new Timer(5, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        // Prevent possible mutatation issues... 
        Animation[] anims = animations.toArray(new Animation[animations.size()]); 
        for (Animation animation : anims) { 
         animation.tick(); 
        } 
       } 
      }); 
     } 

     public void add(Animation animation) { 
      animations.add(animation); 
     } 

     public void remove(Animation animation) { 
      animations.remove(animation); 
     } 

     public void start() { 
      timer.start(); 
     } 

     public void stop() { 
      timer.stop(); 
     } 

    } 

    public interface Animation { 

     public void tick(); 

    } 

    public static final double PLAY_TIME = 4000d; 

    public class TestPane extends JPanel implements Animation { 

     private Path path; 
     private Path2D pathShape; 
     private Timeline timeLine; 

     private Long startTime; 
     private Point currentPoint; 

     public TestPane(Path path) { 
      this.path = path; 

      // Build the "path" shape, we can render this, but more importantally 
      // it allows use to determine the preferred size of the panel :P 
      pathShape = new Path2D.Double(); 
      pathShape.moveTo(path.get(0).x, path.get(0).y); 
      for (int index = 1; index < path.size(); index++) { 
       Point p = path.get(index); 
       pathShape.lineTo(p.x, p.y); 
      } 

      // Build the time line. Each segemnt (the line between any two points) 
      // makes up a percentage of the time travelled, we need to calculate 
      // the amount of time that it would take to travel that segement as 
      // a percentage of the overall length of the path...this 
      // allows us to even out the time... 
      double totalLength = path.getTotalLength(); 
      timeLine = new Timeline(); 
      timeLine.add(0, path.get(0)); 
      // Point on time line... 
      double potl = 0; 
      for (int index = 1; index < path.size(); index++) { 
       Point a = path.get(index - 1); 
       Point b = path.get(index); 
       double length = path.lengthBetween(a, b); 
       double normalised = length/totalLength; 
       // Normalised gives as the percentage of this segment, we need to 
       // translate that to a point on the time line, so we just add 
       // it to the "point on time line" value to move to the next point :) 
       potl += normalised; 

       timeLine.add(potl, b); 
      } 

      currentPoint = path.get(0); 

      Ticker.INSTANCE.add(this); 

     } 

     @Override 
     public Dimension getPreferredSize() { 
      Dimension size = pathShape.getBounds().getSize(); 
      size.width += pathShape.getBounds().x; 
      size.height += pathShape.getBounds().y; 
      return size; 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      g2d.setColor(Color.GREEN); 
      g2d.draw(pathShape); 

      g2d.setColor(Color.RED); 
      g2d.fill(new Ellipse2D.Double(currentPoint.x - 5, currentPoint.y - 5, 10, 10)); 
      g2d.dispose(); 
     } 

     @Override 
     public void tick() { 
      if (startTime == null) { 
       startTime = System.currentTimeMillis(); 
      } 

      long diff = System.currentTimeMillis() - startTime; 
      double t = (double)diff/PLAY_TIME; 
      if (t > 1.0) { 
       t = 1.0d; 
       // Don't call me any more, I'm already home 
       Ticker.INSTANCE.remove(this); 
      } 

      currentPoint = timeLine.getPointAt(t); 
      repaint(); 

     } 

    } 

    public class Path implements Iterable<Point> { 

     private List<Point> points; 
     private double totalLength = 0; 

     public Path(Point... points) { 
      this.points = new ArrayList<>(Arrays.asList(points)); 
      for (int index = 0; index < size() - 1; index++) { 
       Point a = get(index); 
       Point b = get(index + 1); 
       double length = lengthBetween(a, b); 
       totalLength += length; 
      } 
     } 

     public double getTotalLength() { 
      return totalLength; 
     } 

     public int size() { 
      return points.size(); 
     } 

     public Point get(int index) { 
      return points.get(index); 
     } 

     public double lengthBetween(Point a, Point b) { 

      return Math.sqrt(
          (a.getX() - b.getX()) * (a.getX() - b.getX()) 
          + (a.getY() - b.getY()) * (a.getY() - b.getY())); 

     } 

     @Override 
     public Iterator<Point> iterator() { 
      return points.iterator(); 
     } 

    } 

    public class Timeline { 

     private Map<Double, KeyFrame> mapEvents; 

     public Timeline() { 
      mapEvents = new TreeMap<>(); 
     } 

     public void add(double progress, Point p) { 
      mapEvents.put(progress, new KeyFrame(progress, p)); 
     } 

     public Point getPointAt(double progress) { 

      if (progress < 0) { 
       progress = 0; 
      } else if (progress > 1) { 
       progress = 1; 
      } 

      KeyFrame[] keyFrames = getKeyFramesBetween(progress); 

      double max = keyFrames[1].progress - keyFrames[0].progress; 
      double value = progress - keyFrames[0].progress; 
      double weight = value/max; 

      return blend(keyFrames[0].getPoint(), keyFrames[1].getPoint(), 1f - weight); 

     } 

     public KeyFrame[] getKeyFramesBetween(double progress) { 

      KeyFrame[] frames = new KeyFrame[2]; 
      int startAt = 0; 
      Double[] keyFrames = mapEvents.keySet().toArray(new Double[mapEvents.size()]); 
      while (startAt < keyFrames.length && keyFrames[startAt] <= progress) { 
       startAt++; 
      } 

      if (startAt >= keyFrames.length) { 
       startAt = keyFrames.length - 1; 
      } 

      frames[0] = mapEvents.get(keyFrames[startAt - 1]); 
      frames[1] = mapEvents.get(keyFrames[startAt]); 

      return frames; 

     } 

     protected Point blend(Point start, Point end, double ratio) { 
      Point blend = new Point(); 

      double ir = (float) 1.0 - ratio; 

      blend.x = (int) (start.x * ratio + end.x * ir); 
      blend.y = (int) (start.y * ratio + end.y * ir); 

      return blend; 
     } 

     public class KeyFrame { 

      private double progress; 
      private Point point; 

      public KeyFrame(double progress, Point point) { 
       this.progress = progress; 
       this.point = point; 
      } 

      public double getProgress() { 
       return progress; 
      } 

      public Point getPoint() { 
       return point; 
      } 

     } 

    } 
} 

現在,如果我這樣做,我想無論是在Path或爲static實用方法,即採取了Path並自動返回TimeLine創建方法)

+0

我沒有訪問面板類中的開始和結束位置,我正在處理一系列要點和要繪製和移動的圖像列表,如何執行此操作? – Sybren

+0

請看看聊天。 – Sybren

+0

@Sybren我看了一下你的代碼,但經過大約一個小時的試圖弄清楚我可能如何「修復」它,我認爲最好簡單地採用你所擁有的概念,併合並「TimeLine」作爲一個例子。查看更新 – MadProgrammer