提问者:小点点

动画精灵与Java摇摆


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

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

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

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

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


共2个答案

匿名用户

>

  • 首先,每行之间有很多空格,这使得阅读代码变得困难。

    是的,您可以尝试使用SwingTimer,这是一个示例和另一个示例和另一个示例。

    您有一个不安全的空catch块,至少这样做:

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

    您没有将程序放在事件调度线程(EDT)上来解决它,只需更改您的main方法,如下所示:

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

    您正在扩展JFrame,但没有使用它生成的框架,同时您正在创建JFrame的实例,删除代码中的扩展JFrame。相关阅读:Java使用扩展JFrame的Swing与在类内部调用它

    而不是调用frm1. setSize(400,400);覆盖Painel1getPreferredSize()方法以返回400,400的新Dimension并调用frm1.pack()

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

    动画处理太快了!

    不是动画处理太快,而是for循环阻止GUI在结束前被绘制,这就是为什么你只看到最后一个精灵被绘制。

    考虑到上述所有要点,您现在可以使用如下代码,其中包括使用Swing Timer和上述建议:

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

    如您所见,Timer有50毫秒的延迟以使精灵的转换更平滑,您可以随心所欲地调整它。

  • 匿名用户

    我已经改变了一些精灵工作表,因为我可以找到一个类似的图像,但它应该给你的想法:

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