带有 Java Swing 的动画精灵 [英] Animated Sprites with Java Swing

查看:28
本文介绍了带有 Java Swing 的动画精灵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谁能告诉我如何减慢精灵外观以创建更流畅的动画?当我运行代码时,它出现在 JPanel 中的最后一个(第 27 个)精灵.动画处理太快了!

有人告诉我关于 Swing Timer,但不幸的是我尝试了几次,但我无法让代码运行良好:(

这是我到目前为止的代码:

包精灵;导入 java.awt.Color;导入 java.awt.Graphics;导入 java.awt.Image;导入 java.awt.image.BufferedImage;导入 java.io.File;导入 java.io.IOException;导入 javax.imageio.ImageIO;导入 javax.swing.JFrame;导入 javax.swing.JPanel;公共类精灵扩展 JFrame {公共静态无效主(字符串 [] 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);}}类 Painel1 扩展 JPanel {缓冲图像 img;公共Painel1(){设置背景(颜色.黄色);尝试{img = ImageIO.read(new File("images/dummy.png"));}捕获(IOException e){}}@覆盖公共无效paintComponent(图形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}};图像子精灵;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);}}}

假设创建一个从第一个精灵到最后一个(第 27 个)精灵的循环.

解决方案

  1. 首先,每行之间有很多空格,这使得代码难以阅读.

  2. 是的,您可以尝试使用 Swing

    如您所见,Timer 有 50ms 的延迟,使精灵的过渡更平滑,您可以随意调整.

    Can someone tell me how can I slowdown the sprites appearance to create a more smooth animation? When I run the code it appears the last (27th) sprite in the JPanel. The animation processing is too fast!

    Someone told me about Swing Timer, but unfortunately I tried several times with that and I couldn't put the code to run well :(

    Here is the code that I have so far:

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

    It is suppose to create a loop from the 1st sprite to the last (the 27th) sprite.

    解决方案

    1. First of all you have a lot of white spaces between each line, it makes it hard to read the code.

    2. Yes, you could try using a Swing Timer, here is an example and another example and another example.

    3. You have an empty catch block which is not secure, at least do this:

      catch (IOException e){
          e.printStackTrace();
      }
      

    4. You're not placing your program on the Event Dispatch Thread (EDT) to solve it just change your main method as follows:

      public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
              @Override
              public void run() {
                  //Your constructor here
              }
          });
      }
      

    5. You're extending JFrame but not making use of the frame generated by it, and at the same time you're creating an instance of a JFrame, remove the extends JFrame in your code. Related reading: Java Swing using extends JFrame vs calling it inside of class

    6. Instead of calling frm1.setSize(400, 400); override the Painel1's getPreferredSize() method to return a new Dimension of 400, 400 and call frm1.pack()

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

    7. The animation processing is too fast!

      It's not the animation processing too fast, but the for loop prevents the GUI to be painted before it ends, that's why you're only seeing the last sprite being painted.


    With all the above points in mind, you now can have your code as follows, which includes the use of a Swing Timer and the above recommendations already included:

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

    As you can see the Timer has a delay of 50ms to make the transition of the sprites smoother, you can adjust it as you please.

    这篇关于带有 Java Swing 的动画精灵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆