3

所以我正在制作一个游戏,你可以在你的角色所在的位置放置炸弹。当炸弹显示并最终爆炸时,每个炸弹都与一个 GIF 图像相关联(想想炸弹人)。

问题是,当我试图在屏幕上绘制多个炸弹时,它是从 GIF 的最后一帧开始绘制的。经过调查,我找到了重置 GIF cicle 的方法 image.flush() 但现在的问题是,每次我在屏幕上绘制第二个炸弹时,屏幕上所有以前的炸弹都会重置 GIF 周期。

这是每个炸弹的构造函数:

public Tnt(int x, int y){
    this.x = x;
    this.y = y;
    ImageIcon ii = new ImageIcon("src/main/resources/modelObjects/tnt.gif");
    image = ii.getImage();
    image.flush();
}

我创建的每个炸弹都进入一个 ArrayList (listTnt) 并在 6 秒后被删除,所以我只绘制已经激活的炸弹。

这是我的绘图方法:

public void draw(Graphics2D g2d, JPanel board){
    for(Tnt tnt: listTnt){          
        g2d.drawImage(tnt.getImage(), tnt.getX(), tnt.getY(), board);
    }
}

编辑:似乎问题出在 ImageIcon 上,因为它使用 Toolkit.getImage 重用了图像。相反, Toolkit.createImage 创建一个不可重用的图像。

这是我的 Tnt 新构造函数,效果很好:

public Tnt(int x, int y){
    this.x = x;
    this.y = y;
    Toolkit t = Toolkit.getDefaultToolkit ();
    image = t.createImage("src/main/resources/modelObjects/tnt.gif");
}

image.flush()现在什至不需要。谢谢你们。

4

2 回答 2

8

底层Image在每个ImageIcon. 从OpenJDK 源代码来看,这似乎是因为每个都只是通过Toolkit.getImage请求 Image 。然而,这种方法有一个很好的警告,它解释了手头的问题:

底层工具包尝试将具有相同文件名的多个请求解析为相同的返回图像。

相反,您应该ImageIcon完全跳过该步骤(因为首先不必要地使用 Swing 类是不合适的),而是调用Toolkit.createImage,它在文档中指出:

返回的 Image 是一个新对象,不会与此方法的任何其他调用者或其 getImage 变体共享。

祝你好运。

于 2012-07-31T17:46:15.433 回答
2

由于我不知道如何解决这个问题,我尝试了@super_ 解决方案,它工作得很好。我为任何想要示例的人分享代码。+1 给他

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class TestAnimatedGif {

    private static final int IMAGE_COUNT = 9;

    protected void initUI() {
        JFrame frame = new JFrame(TestAnimatedGif.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JPanel panel = new JPanel();
        frame.add(panel);
        frame.setSize(600, 400);
        frame.setVisible(true);
        final Timer t = new Timer(1000, null);
        t.addActionListener(new ActionListener() {

            int count = 0;

            @Override
            public void actionPerformed(ActionEvent e) {
                if (count < IMAGE_COUNT) {
                    try {
                        JLabel image = new JLabel(new ImageIcon(Toolkit.getDefaultToolkit().createImage(
                                new URL("http://www.sitevip.net/gifs/bomba/BOMB-B_animado.gif"))));
                        panel.add(image);
                        count++;
                        panel.revalidate();
                        panel.repaint();
                        System.err.println("image added");
                    } catch (MalformedURLException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                } else {
                    t.stop();
                }
            }
        });
        t.start();
    }

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

            @Override
            public void run() {
                new TestAnimatedGif().initUI();
            }
        });
    }

}
于 2012-07-31T20:46:24.030 回答