好的,所以我正在制作一个游戏,用户在游戏中的角色后面移动一个图像(在我的代码中称为“地图”),这样就好像角色正在移动。
程序运行时,性能下降,背景图像(“map”)滞后,并不总是重新绘制。
这是我的主类调用绘制图片的类:
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(据我所知)。另外,重绘();在我的程序中,每16毫秒调用一次方法(是的,我尝试增加那段时间,问题仍然存在)。以下是用于重新绘制框架的计时器片段:
TimerTask task = new 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 :(得分:1)
考虑将重绘(...)限制在需要重新绘制的GUI的小区域。同时,不要在paint或paintComponent方法中处理由JVM传递给您的Graphics对象。只处理你自己创造的一个。
编辑1
如果图形的性能是关键,那么最好离开Swing并转移到针对游戏,动画和图形进行优化的库。
答案 1 :(得分:1)
您可以通过ResourceBundle缓存常用图像。以下代码提供对存储在jar或绝对路径中的图像的高速缓存访问,如ImageIcons。首次访问将把图像存储到Hashtable中。对同一图像的后续调用将是查找。必须在“default”包下设置此类:
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");
答案 2 :(得分:1)
如果您正在编写游戏,则应使用游戏引擎。编写高性能游戏很难,而且屏幕上所有内容的强力重绘都不会削减它。其他聪明人已经解决了这些问题,你可以利用他们累积的工作,而不是试图重新发明轮子。
我不是游戏引擎方面的专家,但谷歌“java游戏引擎”的第一个热门是jmonkeyengine.com。也许你应该尝试一下。
答案 3 :(得分:0)
我在Container内部交互式移动JComponent时遇到了性能问题,并发现在父上调用repaint()而不是在移动组件上调用,会大大提高速度。我不知道为什么 - 有人知道吗?