2013-03-10 71 views
1

我想讓我的應用程序繪製移動圖像比當前繪製它們更平滑一些。我不知道該怎麼做。消除Java繪製動畫

這是我的主要遊戲線程的樣子:

@Override 
public void run(){ 
    int delay = 500; //milliseconds 
    ActionListener taskPerformer = new ActionListener(){ 
     @Override 
     public void actionPerformed(ActionEvent evt){ 
      Car car = new Car(); 
      int speed = (int)(3 + Math.floor(Math.random() * (6 - 3))); 
      car.setSpeed(speed); 
      MainLoop.this.gameObjects.vehicles.add(car.create("/Media/Graphics/blueCar.png", width - 20, 78)); 
      car.driveTo(0, 78); 
     } 
    }; 
    new Timer(delay, taskPerformer).start(); 
    try{ 
     while(true){ 
      this.repaint(); 
      for(GameObject go : this.gameObjects.vehicles){ 
       // loops through objects to move them 
       Vehicle vh = (Vehicle) go; 
       this.moveVehicle(vh); 
       if(vh.getX() <= vh.getDestX()){ 
        vh.markForDeletion(true); 
       } 
      } 
      this.gameObjects.destroyVehicles(); 
      Thread.sleep(1); 
     } 
    }catch(Exception e){ 
     e.printStackTrace(); 
    } 
} 

這是計算的項目下一個x/y位置

protected void moveVehicle(Vehicle vh){ 
    int cx = vh.getX(); 
    int dx = vh.getDestX(); 
    int cy = vh.getY(); 
    int dy = vh.getDestY(); 
    // move along x axis 
    // getMaxSpeed() = Number between 3 and 6 
    if(cx > dx && vh.movingX() == -1){ 
     vh.setX(cx - vh.getMaxSpeed()); 
    }else if(cx < dx && vh.movingX() == 1){ 
     vh.setX(cx + vh.getMaxSpeed()); 
    }else{ 
     vh.setX(dx); 
    } 

    // move along y axis 
    // getMaxSpeed() = Number between 3 and 6 
    if(cy > dy && vh.movingY() == -1){ 
     vh.setY(cy - vh.getMaxSpeed()); 
    }else if(cy < dy && vh.movingY() == 1){ 
     vh.setY(cy + vh.getMaxSpeed()); 
    }else{ 
     vh.setY(dy); 
    } 
} 

這是我的繪製方法的方法:

@Override 
public void paintComponent(Graphics graphics){ 
    super.paintComponent(graphics); 
    Graphics2D g = (Graphics2D) graphics; 

    for(GameObject go : gameObjects.vehicles){ 
     g.drawImage(go.getSprite(), go.getX(), go.getY(), this); 
    } 
} 

這可能比需要更多的信息,但我想知道,我應該怎麼做才能讓項目MOV e從left -> righttop -> bottom儘可能順利,沒有太多的性能損失?

編輯:要求SSCCE:

package sscce; 

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.ArrayList; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 

public class Sscce extends JPanel implements Runnable{ 

    ArrayList<Square> squares = new ArrayList<>(); 

    public Sscce(){ 
     JFrame frame = new JFrame(); 
     frame.setSize(500, 500); 
     frame.setLocationRelativeTo(null); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
     frame.add(this); 
     Thread t = new Thread(this); 
     t.start(); 
    } 

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

    @Override 
    public void run(){ 
     int delay = 500; //milliseconds 
     ActionListener taskPerformer = new ActionListener(){ 
      @Override 
      public void actionPerformed(ActionEvent evt){ 
       Square squ = new Square(); 
       Sscce.this.squares.add(squ); 
       squ.moveTo(0); 
      } 
     }; 
     new Timer(delay, taskPerformer).start(); 
     while(true){ 
      try{ 
       for(Square s : this.squares){ 
        int objX = s.getX(); 
        int desX = s.getDestX(); 
        if(objX <= desX){ 
         System.out.println("removing"); 
         this.squares.remove(s); 
        }else{ 
         s.setX(s.getX() - 10); 
        } 
       } 
       this.repaint(); 
       Thread.sleep(30); 
      }catch(Exception e){ 
      } 
     } 
    } 

    @Override 
    public void paintComponent(Graphics g){ 
     super.paintComponent(g); 
     for(Square s : squares){ 
      g.setColor(Color.blue); 
      g.fillRect(s.getX(), s.getY(), 50, 50); 
     } 
    } 
} 

class Square{ 

    public int x = 0, y = 0, destX = 0; 

    public Square(){ 
     this.x = 400; 
     this.y = 100; 
    } 

    public void moveTo(int destX){ 
     this.destX = destX; 
    } 

    public int getX(){ 
     return this.x; 
    } 
    public int getDestX(){ 
     return this.destX; 
    } 

    public void setX(int x){ 
     this.x = x; 
    } 

    public int getY(){ 
     return this.y; 
    } 
} 
+1

你也來看看[這裏](http://stackoverflow.com/questions/14886232/swing-animation-running-extremely-慢/ 14902184#14902184)和[this](http://stackoverflow.com/questions/13540534/how-to-make-line-animation-smoother/13547895#13547895)和[this](http:// stackoverflow。 com/questions/14593678/multiple-bouncing-balls-thread-issue/14593761#14593761)and [this](http://stackoverflow.com/questions/13022754/java-bouncing-ball/13022788#13022788)和[this ](http://stackoverflow.com/questions/12642852/the-images-are-not-loading/12648265#12648265)(僅僅因爲我喜歡它) – MadProgrammer 2013-03-10 23:51:00

+1

讓我們從開始,沒有一個工作的例子,我們不可能幫助你。但是讓我們從毫無意義的Thread.sleep(1)開始吧。這是。然後繼續提及Swing在更新模型時可能執行重繪 – MadProgrammer 2013-03-10 23:52:22

+0

@MadProgrammer我添加了一個sscce。如果我不放'Thread.sleep(1);'沒有任何繪製。 – 2013-03-10 23:52:51

回答

1

首先說明,出於某種原因,我曾與JPanel在MacOS下運行它時,執行Runnable問題 - 我不知道爲什麼,但是這就是爲什麼我感動出來。

你的squares可能被更新,而它被用來繪製哪些會導致異常(同時,從迭代中刪除元素也不是一個好主意))

相反,我有兩個列表。我有一個模型,列表可以修改,然後使用方法可以使用的繪製列表。這允許線程修改模型,同時正在進行噴漆過程。

爲了防止任何衝突,我在一個鎖,以防止一個線程修改/訪問油漆列表中所增加,而另一個線程有它鎖定。

現在。解決真正的問題。你遇到的主要問題不是更新之間的時間間隔,而是你移動的距離。減少距離(使其變慢)並使更新標準化。

大多數人不會注意到什麼太大了25fps的,所以試圖然後就是在浪費CPU週期和飢餓的重繪管理器,防止其實際更新屏幕做更多的工作。

這是一個平衡的行爲,以確保...

import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.concurrent.locks.ReentrantLock; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class TestAnimation11 extends JPanel { 

    private ArrayList<Square> squares = new ArrayList<>(); 
    private ReentrantLock lock; 

    public TestAnimation11() { 
     lock = new ReentrantLock(); 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 
       JFrame frame = new JFrame(); 
       frame.setSize(500, 500); 
       frame.setLocationRelativeTo(null); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setVisible(true); 
       frame.add(TestAnimation11.this); 
       Thread t = new Thread(new UpdateEngine()); 
       t.start(); 
      } 
     }); 
    } 

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

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Square[] paint = null; 
     lock.lock(); 
     try { 
      paint = squares.toArray(new Square[squares.size()]); 
     } finally { 
      lock.unlock(); 
     } 
     for (Square s : paint) { 
      g.setColor(Color.blue); 
      g.fillRect(s.getX(), s.getY(), 50, 50); 
     } 
    } 

    public class UpdateEngine implements Runnable { 

     private List<Square> model = new ArrayList<>(squares); 

     @Override 
     public void run() { 
      int ticks = 0; 
      List<Square> dispose = new ArrayList<>(25); 
      while (true) { 
       ticks++; 
       dispose.clear(); 
       for (Square s : model) { 
        int objX = s.getX(); 
        int desX = s.getDestX(); 
        if (objX <= desX) { 
         dispose.add(s); 
        } else { 
         s.setX(s.getX() - 2); 
        } 
       } 
       model.removeAll(dispose); 
       if (ticks == 11) { 
        Square sqr = new Square(); 
        sqr.moveTo(0); 
        model.add(sqr); 
       } else if (ticks >= 25) { 
        ticks = 0; 
       } 
       lock.lock(); 
       try { 
        squares.clear(); 
        squares.addAll(model); 
       } finally { 
        lock.unlock(); 
       } 
       repaint(); 
       try { 
        Thread.sleep(40); 
       } catch (Exception e) { 
       } 
      } 
     } 
    } 

    class Square { 

     public int x = 0, y = 0, destX = 0; 

     public Square() { 
      this.x = 400; 
      this.y = 100; 
     } 

     public void moveTo(int destX) { 
      this.destX = destX; 
     } 

     public int getX() { 
      return this.x; 
     } 

     public int getDestX() { 
      return this.destX; 
     } 

     public void setX(int x) { 
      this.x = x; 
     } 

     public int getY() { 
      return this.y; 
     } 
    } 
} 
+0

謝謝,我稍後再看看這個! – 2013-03-11 14:48:45