2011-11-05 132 views
0

好的,我正在制作一个游戏,用户在游戏中的角色后面移动一个图像(在我的代码中称为“地图”),这样看起来好像角色正在移动。Java:我如何更快地绘制这些图像?

程序运行时,性能下降适中,背景图像(“地图”)滞后,并且不总是重新绘制。

这里是我的主类调用来绘制图片类:

public graphics(int z,int s, int f) 
{ 
    x = z; 
    y = s; 
    d = f; 
    try { 
    map = ImageIO.read(new File("background.png")); 
    //br = ImageIO.read(new File("blackrectangle.jpg")); 
    s0 = ImageIO.read(new File("spriteshoot0.png")); 
    s10 = ImageIO.read(new File("spriteshoot10.png")); 
    s20 = ImageIO.read(new File("spriteshoot20.png")); 
    s30 = ImageIO.read(new File("spriteshoot30.png")); 
    s40 = ImageIO.read(new File("spriteshoot40.png")); 
    s50 = ImageIO.read(new File("spriteshoot50.png")); 
    s60 = ImageIO.read(new File("spriteshoot60.png")); 
    s70 = ImageIO.read(new File("spriteshoot70.png")); 
    s80 = ImageIO.read(new File("spriteshoot80.png")); 
    s90 = ImageIO.read(new File("spriteshoot90.png")); 
    s100 = ImageIO.read(new File("spriteshoot100.png")); 
    s110 = ImageIO.read(new File("spriteshoot110.png")); 
    s120 = ImageIO.read(new File("spriteshoot120.png")); 
    s130 = ImageIO.read(new File("spriteshoot130.png")); 
} catch (IOException e) {} 
} 
public void moveZ(int a,int b) 
{ 
    xz+=a; 
    yz+=b; 
} 

public void move(int a,int b) 
{ 
    x+=a; 
    y+=b; 
} 

public void angle(int t) 
{ 
    q=t; 

} 



public void paintComponent(Graphics g) { 

     g.drawImage(map,x,y,this); 

     if (q==1) 
     g.drawImage(s0,599,340,null); 

     if (q==2) 
     g.drawImage(s10,599,340,null); 

     if (q==3) 
     g.drawImage(s20,599,340,null); 

     if (q==4) 
     g.drawImage(s30,599,340,null); 

     if (q==5) 
     g.drawImage(s40,599,340,null); 

     if (q==6) 
     g.drawImage(s50,599,340,null); 

     if (q==7) 
     g.drawImage(s60,599,340,null); 

     if (q==8) 
     g.drawImage(s70,599,340,null); 

     if (q==9) 
     g.drawImage(s80,599,340,null); 

     if (q==10) 
     g.drawImage(s90,599,340,null); 

     if (q==11) 
     g.drawImage(s100,599,340,null); 

     if (q==12) 
     g.drawImage(s110,599,340,null); 

     if (q==13) 
     g.drawImage(s120,599,340,null); 

     if (q==14) 
     g.drawImage(s130,599,340,null); 
    }} 

所以我想知道怎样才能显示图像“地图”更快或找到解决这个性能问题的替代路线。

注* *此代码是作为我的主类中的一个对象创建的,并且每次执行时都不会从文件中读取BufferedImages(据我所知)。此外,repaint();方法在我的程序中每16毫秒调用一次(是的,我试图增加那个时间,问题仍然存在)。下面是用于重新绘制帧定时器的一个片段:)

TimerTask的任务=新的TimerTask({

public void run()  { 

     if (onU) 
      g.move(0,3); 

     if (onL) 
      g.move(3,0); 

     if (onD) 
      g.move(0,-3); 

     if (onR) 
      g.move(-3,0); 
     //System.out.println(ze.getX(650,400,650,0,xZ,yZ)); 
     //System.out.println(ze.getY(650,400,650,0,xZ,yZ)); 
     if(onR||onL||onD||onU) 
     gameSurface.repaint(); 
    }}; 

任何帮助感激,谢谢。

+0

永远不要处理由paint或paintComponent方法中的JVM传递给您的Graphics对象。只处理你自己创建的一个。 –

+0

你试过双缓冲吗? – 2011-11-05 02:55:50

+0

不,我以为自动双缓冲 – user1030690

回答

1

如果你正在编写游戏,你应该使用游戏引擎。编写高性能游戏非常困难,萤幕上的所有内容的蛮力重绘都不会削减它。其他聪明人已经解决了这些问题,你可以利用他们的累积工作而不是试图重新发明轮子。

我不是游戏引擎方面的专家,但在“java游戏引擎”上的第一个搜索引擎是jmonkeyengine.com。也许你应该尝试一下。

+0

好的谢谢你,我一定会尝试。 – user1030690

1

考虑限制重新绘制(...)到需要重新绘制的GUI的小区域。另外,不要将JVM在Graphics或PaintComponent方法中传递给您的Graphics对象置于其中。只处理你自己创建的一个。

编辑1
如果显卡性能的关键是,你可能会更好离开Swing和移动到为游戏,动画和图形优化的库。

+0

好的,我已经删除了dispose();方法,但背景图像显示在整个JPanel中,每次移动时都需要重绘,所以我不能将repaint()方法限制为某些参数,因为整个JPanel需要更新。 – user1030690

+0

@ user1030690:看编辑 –

+0

是的,我会尝试一个高速性能的游戏库,谢谢。 – user1030690

1

您可以通过ResourceBundle缓存经常使用的图像。以下代码提供对存储在jar或绝对路径中的图像的缓存访问,如ImageIcons。首次访问会将图像存储到Hashtable中。随后对相同图像的调用将作为查找。这个类必须在“默认”包设置:

import java.util.*; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import java.net.*; 

import javax.imageio.ImageIO; 
import javax.swing.*; 

/** 
* ImageBundle is a ResourceBundle that retrieves the content of an image from an image file with supported extension. 
*/ 
public class ImageBundle extends ResourceBundle { 
    private static final String RESOURCE = "MyApp"; 
    private String __fileSuffix; 
    /** 
    * @uml.property name="__KEYS" 
    */ 
    private static final Vector<String> __KEYS; 
    private static Hashtable<String, ImageIcon> __TABLE; 

    static { 
     __KEYS = new Vector<String>(); 
     __KEYS.addElement(RESOURCE); 
     __TABLE = new Hashtable<String, ImageIcon>(); 
    } 

    /** 
    * Load image file stored in a JAR classpath 
    * @param imageName the filename of the image 
    * @return the ImageIcon of the image file 
    */ 
    private ImageIcon __loadImageFromJar(String imageName) { 
     String path = ""; //define the file path of the image file in imageName itself 

     String imagePath = path + imageName + __fileSuffix; 
     ImageIcon icon; 
     URL url; 

     icon = (ImageIcon)__TABLE.get(imageName); 

     if(icon != null) 
      return icon; 

     url = ImageBundle.class.getResource(imagePath); 

     icon = new ImageIcon(url); 
     __TABLE.put(imageName, icon); 

     return icon; 
    } 

    /** 
    * Load image file stored in a given path 
    * @param imageName the filename of the image 
    * @return the ImageIcon of the image file 
    */ 
    @SuppressWarnings("unused") 
    private ImageIcon __loadImageFromExternalSource(String imageName) { 
     String path = System.getenv("MY_APP_HOME_PATH"); 

     String imagePath = ((path != null) ? (path + imageName + __fileSuffix) : (imageName + __fileSuffix)); 
     ImageIcon value; 

     value = (ImageIcon)__TABLE.get(imageName); 

     if(value != null){ 
      //Outils.debugMessage("Cached " + imagePath + "> " + imageName + ": " + value); 
      return value; 
     } 
     else { 
      //Outils.debugMessage("New " + imagePath + "> " + imageName + ": " + value); 
     } 

     ImageIcon property = null; 
     BufferedImage image = null; 
     try { 
      image = ImageIO.read(new File(imagePath)); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     property = new ImageIcon(image); 

     value = property; 
     __TABLE.put(imageName, value); 

     return value; 
    } 

    protected ImageBundle(String suffix) { 
     __fileSuffix = suffix; 
    } 

    public ImageBundle() { 
     this(""); 
    } 

    /** 
    * @return 
    * @uml.property name="__KEYS" 
    */ 
    public Enumeration<String> getKeys() { 
     return __KEYS.elements(); 
    } 

    protected final Object handleGetObject(String key) { 
     return __loadImageFromJar(key); 
    } 
} 

用法:

ResourceBundle rsc = ResourceBundle.getBundle("ImageBundle"); //call rsc only once 
... 
ImageIcon icon = (ImageIcon) rsc.getObject("picture/plus.png"); 
+0

好吧,我在我的代码中实现了这一点,但没有性能改进。这可能是因为这个想法更快地读取图像,而不是更快地绘制/重新绘制图像,这是最大的性能问题所在。 – user1030690

+0

如何通过安装自己的重绘管理器来使用javax.swing.RepaintManager? – ecle

0

我有一个性能问题与容器内的交互式移动的JComponent,发现调用重绘()上父母,而不是在移动的组件,给了巨大的速度增加。我不知道为什么 - 有人知道吗?

+0

我试过这个,但是我没有看到重绘容器和重新绘制框架的性能有任何区别。 – user1030690