2012-07-31 132 views
3

所以我在做一个游戏,你可以把炸弹在你的角色的位置。当炸弹被显示时,每个炸弹都与GIF图像相关联,并最终进入BOOM(想想炸弹人)。多个实例

的问题是,当我试图在屏幕上绘制一个以上的炸弹,它是从GIF的最后一帧画。在调查中,我找到了image.flush()方法来重置GIF Cicle,但现在问题是每当我在屏幕上绘制第二个炸弹时,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()现在。谢谢你们。

+2

'image'的范围是什么? – trashgod 2012-07-31 17:36:42

+0

在应用程序的主要游戏状态中,我有一个炸弹列表。当我在游戏中放置炸弹时,会创建一个新的Tnt并添加到列表中,并在6秒(炸弹生命周期)后将炸弹从列表中移除。 'draw'方法只从list和'image'中绘制炸弹是Tnt内的一个变量。 – 2012-07-31 18:00:04

+0

请参阅[在Swing中显示动画BG](http://stackoverflow.com/questions/10836832/show-an-animated-bg-in-swing)。 – 2012-07-31 23:07:02

回答

6

底层Image被重用之间每个ImageIcon。 根据OpenJDK source code来判断,这似乎是因为每个人都只是通过Toolkit.getImage来请求图片。 这种方法有一个漂亮的警告,不过,这也说明当前的问题:

底层工具包试图对具有相同的文件名相同的图像返回多个请求。

相反,你应该完全跳过ImageIcon步骤(因为它是不恰当的摆在首位不必要地使用Swing类是),而是调用Toolkit.createImage,在文档中的规定:

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

好运。

+1

这听起来对我来说是正确的。 – aglassman 2012-07-31 17:56:28

+1

很好,谢谢你,先生! – 2012-07-31 18:12:14

+0

+1很好的解释和解决方案。我添加了一个示例代码,因为我尝试了我以前不知道的解决方案。 – 2012-07-31 20:46:20

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

} 
+0

+1 [sscce](http://sscce.org/)和@super_。 – trashgod 2012-07-31 23:20:50