2013-03-10 3 views
1

Я хотел бы сделать мое приложение рисованием движущегося изображения немного более гладким, чем то, как он в настоящее время рисует их. Я не уверен, что делать, чтобы сделать это.Сглаживание анимации рисования на Java

Это то, что выглядит моя основная игра Thread как:

@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(); 
    } 
} 

Это метод, который вычисляет элементы следующего х/у позиции

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); 
    } 
} 

Возможно, это больше информации, чем необходимо, но я хотел бы знать, что мне делать, чтобы вещи перемещались из left -> righttop -> bottom настолько плавно, насколько это возможно, без значительной потери производительности?

Edit: Запрошенный 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- slow/14902184 # 14902184) и [this] (http://stackoverflow.com/questions/13540534/how-to-make-line-animation-smoother/13547895#13547895) и [это] (http: // stackoverflow. com/questions/14593678/multiple-bouncing-balls-thread-issue/14593761 # 14593761) и [this] (http://stackoverflow.com/questions/13022754/java-bouncing-ball/13022788#13022788) и [это ] (http://stackoverflow.com/questions/12642852/the-images-are-not-loading/12648265#12648265) (только потому, что мне это нравится) – MadProgrammer

+1

Начнем с того, что без рабочего примера это не чтобы быть в состоянии помочь вам. Но давайте начнем с того, как бессмысленна Thread.sleep (1); это. И затем добавим, что Swing может выполнять перерисовку при обновлении модели – MadProgrammer

+0

@MadProgrammer. Я добавил sscce. Если я не помещаю 'Thread.sleep (1);' ничего не получается. –

ответ

1

Прежде всего заметим, по какой-то причине, у меня были проблемы с JPanel реализующего Runnable при работе под MacOS - я понятия не имею, почему, но именно поэтому я переехал это из.

Возможно, ваше обновление squares будет обновляться, пока оно будет использоваться для рисования, что вызовет исключение (также удаляя элементы из списка, пока вы повторяете, это тоже не очень хорошая идея;))

Вместо этого у меня есть два списка. У меня есть модель, которую может изменить список, а затем список красок, который может использовать метод paint. Это позволяет потоку модифицировать модель, в то время как процесс рисования продолжается.

Чтобы предотвратить любое столкновение, я добавил в блокировку, которая предотвращает изменение/доступ нити к списку красок, а другой поток заблокирован.

Теперь. До настоящей проблемы. Основная проблема, с которой вы сталкиваетесь, - это не время между обновлениями, а расстояние, на которое вы двигаетесь. Уменьшите расстояние (чтобы сделать его медленнее) и обновите обновления.

Большинство людей ничего не заметят более чем на 25 кадров в секунду, поэтому, пытаясь сделать гораздо больше, это просто растрачивает циклы процессора и голодает менеджер перерисовки, не позволяя ему фактически обновлять экран.

Это балансирование, чтобы быть уверенным ...

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

Спасибо, я посмотрю на это чуть позже! –

Смежные вопросы