2017-01-26 5 views
-1

Может ли кто-нибудь сказать мне, как я могу замедлить внешний вид спрайтов, чтобы создать более плавную анимацию? Когда я запускаю код, он выглядит последним (27-м) спрайтом в JPanel. Обработка анимации выполняется слишком быстро!Анимированные спрайты с Java Swing

Кто-то сказал мне о свинг таймер, но, к сожалению, я несколько раз пытался с этим, и я не мог поставить код, чтобы хорошо работать :(

Вот код, который я до сих пор:

package sprites; 

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class Sprites extends JFrame { 

public static void main(String[] args) { 
    JFrame frm1 = new JFrame(); 
    frm1.setSize(400, 400); 
    frm1.setLocationRelativeTo(null); 
    frm1.setResizable(false); 
    frm1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    Painel1 pn1 = new Painel1(); 
    frm1.getContentPane().add(pn1); 
    frm1.setVisible(true); 
    } 
} 

class Painel1 extends JPanel { 

    BufferedImage img; 

    public Painel1() { 
     setBackground(Color.yellow); 
    try 
    { 
     img = ImageIO.read(new File("images/dummy.png")); 
    } 
    catch (IOException e) 
    {} 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
    int[][] spriteSheetCoords = {{8, 10, 119, 129}, 
           {138, 10, 118, 130}, 
           {267, 10, 118, 132}, 
           {402, 11, 113, 132}, 
           {538, 12, 106, 134}, 
           {671, 13, 103, 133}, 
           {804, 12, 102, 132}, 
           {23, 161, 100, 134}, 
           {157, 162, 96, 134}, 
           {287, 159, 95, 135}, 
           {418, 158, 95, 133}, 
           {545, 159, 99, 133}, 
           {673, 159, 102, 134}, 
           {798, 158, 108, 130}, 
           {9, 309, 116, 126}, 
           {137, 309, 118, 127}, 
           {274, 310, 110, 128}, 
           {412, 311, 102, 129}, 
           {541, 312, 103, 130}, 
           {671, 312, 104, 131}, 
           {806, 312, 98, 132}, 
           {29, 463, 94, 135}, 
           {155, 462, 98, 135}, 
           {279, 461, 104, 135}, 
           {409, 461, 106, 135}, 
           {536, 461, 109, 135}, 
           {662, 461, 112, 133}}; 
    Image subSprite; 
    for (int i = 0; i <= 26; i++) { 
     super.paintComponent(g); 
     subSprite = img.getSubimage(spriteSheetCoords[i][0], spriteSheetCoords[i][1], spriteSheetCoords[i][2], spriteSheetCoords[i][3]); 
     g.drawImage(subSprite, 140, 120, null); 
    } 
    } 
} 

это, предполагают, чтобы создать цикл от 1-го спрайта до последнего (27-я) спрайта

+1

[Более продвинутый подход] (http://stackoverflow.com/questions/35472233/load-a-sprites-image-in-java/35472418#35472418) и [пример основного принципа] (http: // stackoverflow .com/questions/35979697/java-basic-2d-game-animation-stutter/35979771 # 35979771) – MadProgrammer

+1

Я также предлагаю взглянуть на [Concurrency in Swing] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency /) и [Как использовать таймеры Swing] (http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html) – MadProgrammer

+1

1) 'img = ImageIO.read (новый файл («images/dummy.png»)); «Ресурсы приложений станут частью встроенных ресурсов к моменту развертывания, поэтому разумно начать доступ к ним, как если бы они были, прямо сейчас. К [тегу: embedded-resource] должен быть доступен URL, а не файл. См. [Info. страница для встроенного ресурса] (http://stackoverflow.com/tags/embedded-resource/info) для того, как формировать URL-адрес. 2) 'catch (IOException e) {}' должен быть 'catch (IOException e) {e.printStackTrace(); } '3)' public void paintComponent (Graphics g) { int [] [] spriteSheetCoords', так как этот метод .. –

ответ

2
  1. Прежде всего у вас есть много белых промежутков между каждой линией, это делает его трудно читать код.

  2. Да, вы можете попробовать использовать свинг Timer, вот example и другой example и другой example.

  3. У вас есть пустой catch блок, который не является безопасным, по крайней мере, сделать это:

    catch (IOException e){ 
        e.printStackTrace(); 
    } 
    
  4. Вы не размещая свою программу на Event Dispatch Thread (EDT), чтобы решить просто изменить метод main следующим образом:

    public static void main(String[] args) { 
        SwingUtilities.invokeLater(new Runnable() { 
         @Override 
         public void run() { 
          //Your constructor here 
         } 
        }); 
    } 
    
  5. вы простирающийся JFrame, но не делает использование кадра, сформированного ею, и в то же время вы создаете экземпляр JFrame, удалите extends JFrame в своем коде. Связанные чтения: Java Swing using extends JFrame vs calling it inside of class

  6. Вместо вызова frm1.setSize(400, 400); переопределение getPreferredSize() метод в соответствии с Painel1 «s вернуть новый Dimension из 400, 400 и вызвать frm1.pack()

    @Override 
    public Dimension getPreferredSize() { 
        return new Dimension(400, 400); 
    } 
    
  7. Обработка анимации слишком быстро!

    Это не обработка анимации слишком быстро, но петля for мешает GUI быть окрашены до его окончания, поэтому вы видите только последний спрайт красили.


Со всеми выше пунктов в виду, теперь вы можете иметь свой код следующим образом, который включает в себя использование свинг таймера и вышеупомянутые рекомендации уже включены:

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 

import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 

public class Sprites { 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       JFrame frm1 = new JFrame(); 
       Painel1 pn1 = new Painel1(); 
       frm1.getContentPane().add(pn1); 

       frm1.pack(); 
       frm1.setVisible(true); 
       frm1.setLocationRelativeTo(null); 
       frm1.setResizable(false); 
       frm1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      } 
     }); 
    } 
} 

class Painel1 extends JPanel { 

    int[][] spriteSheetCoords = { { 8, 10, 119, 129 }, { 138, 10, 118, 130 }, { 267, 10, 118, 132 }, 
      { 402, 11, 113, 132 }, { 538, 12, 106, 134 }, { 671, 13, 103, 133 }, { 804, 12, 102, 132 }, 
      { 23, 161, 100, 134 }, { 157, 162, 96, 134 }, { 287, 159, 95, 135 }, { 418, 158, 95, 133 }, 
      { 545, 159, 99, 133 }, { 673, 159, 102, 134 }, { 798, 158, 108, 130 }, { 9, 309, 116, 126 }, 
      { 137, 309, 118, 127 }, { 274, 310, 110, 128 }, { 412, 311, 102, 129 }, { 541, 312, 103, 130 }, 
      { 671, 312, 104, 131 }, { 806, 312, 98, 132 }, { 29, 463, 94, 135 }, { 155, 462, 98, 135 }, 
      { 279, 461, 104, 135 }, { 409, 461, 106, 135 }, { 536, 461, 109, 135 }, { 662, 461, 112, 133 } }; 

    int i = 0; 
    BufferedImage img; 

    private ActionListener actionListener = new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      i++; 
      if (i == spriteSheetCoords.length) { 
       i = 0; 
      } 
      revalidate(); 
      repaint(); 
     } 
    }; 

    public Painel1() { 
     Timer timer = new Timer(50, actionListener); 
     timer.setInitialDelay(0); 
     timer.start(); 
     setBackground(Color.yellow); 
     try { 
      img = ImageIO.read(new File("/home/jesus/Pictures/tokyo.jpg")); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     Image subSprite; 
     super.paintComponent(g); 
     subSprite = img.getSubimage(spriteSheetCoords[i][0], spriteSheetCoords[i][1], spriteSheetCoords[i][2], spriteSheetCoords[i][3]); 
     g.drawImage(subSprite, 140, 120, null); 
    } 

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

enter image description here

Как видите, Timer имеет задержку в 50 мс, чтобы сделать переход спрайтов более плавным, вы можете настроить его, как вам будет угодно.

+0

В downvoter, не могли бы вы объяснить причину? – Frakcool

+0

Большое спасибо @Frakcool, я изучу рекомендации, которые вы публикуете. –

+0

@PedroFigueiredo, если ответ решил проблема, пожалуйста [примите] (http://stackoverflow.com/help/accepted-answer) it – Frakcool

0

Я изменил некоторые спрайт лист COORDS, потому что я мог бы найти подобный образ, но это должно дать вам идею.:

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import java.util.Timer; 
import java.util.TimerTask; 

import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class Sprites extends JFrame { 

    public static void main(String[] args) { 
     JFrame frm1 = new JFrame(); 
     frm1.setSize(400,400); 
     frm1.setLocationRelativeTo(null); 
     frm1.setResizable(false); 
     frm1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     Painel1 pn1 = new Painel1(); 
     frm1.getContentPane().add(pn1); 
     frm1.setVisible(true); 
    } 

} 

class Painel1 extends JPanel { 

    BufferedImage img; 
    Timer timer; 
    int i; 
    Image subSprite; 
    int[][] spriteSheetCoords = { { 8, 10, 119, 129 }, { 138, 10, 118, 130 }, { 267, 10, 118, 132 }, 
      { 402, 11, 113, 132 }, { 538, 12, 106, 134 }, { 671, 13, 103, 133 }, { 671, 12, 102, 132 }, 
      { 23, 161, 100, 134 }, { 157, 162, 96, 134 }, { 287, 159, 95, 135 }, { 418, 158, 95, 133 }, 
      { 545, 159, 99, 133 }, { 673, 159, 102, 134 }, { 550, 158, 108, 130 }, { 9, 309, 116, 126 }, 
      { 137, 309, 118, 127 }, { 274, 310, 110, 128 }, { 412, 311, 102, 129 }, { 541, 312, 103, 130 }, 
      { 671, 312, 104, 131 }, { 600, 312, 98, 132 }, { 29, 463, 94, 135 }, { 155, 462, 98, 135 }, 
      { 279, 461, 104, 135 }, { 409, 461, 106, 135 }, { 536, 461, 109, 135 }, { 662, 461, 112, 133 } }; 

    public Painel1() { 
     setBackground(Color.yellow); 
     try 
     { 
      img = ImageIO.read(new File("images/ddd.png")); 
      timer = new Timer(); 
      timer.scheduleAtFixedRate(new TimerTask() { 
       @Override 
       public void run() { 
        subSprite = img.getSubimage(spriteSheetCoords[i][0], spriteSheetCoords[i][1], spriteSheetCoords[i][2], 
          spriteSheetCoords[i][3]); 
        i++; 
        repaint(); 
        revalidate(); 
       } 
      }, 500, 500); 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.drawImage(subSprite, 140, 120, null); 
    } 
} 
+1

Просто остерегайтесь того, что 'java.util.Timer' выполняется в рамках собственного контекста потока, что делает его плохим выбором при работе с Swing, поскольку Swing может пытаться рисовать, пока вы обновляете состояние полагается. Кроме того, вы должны проходить 'this' на' drawImage' – MadProgrammer