Reputation: 3
Ok so I am making a game where the user moves an image(called "map" in my code) behind the character in the game so it appears as though the character is moving.
While the program is running, there are moderate performance drops, and the background image("map") lags and is not always repainted.
Here is a class that my main class calls to paint the pictures:
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);
}}
So I am wondering how I can display the image "map" faster or find an alternate route around this performance issue.
Note** This code is created as an object in my main class and the BufferedImages aren't being read from the files every single time this is executed(as far as I know). Also, the repaint(); method is called at every 16 milliseconds in my program (and yes i've tried increasing that time and the issues still remain). Here is a snippet of the timer used to repaint the frame:
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();
}};
Any help is greatly appreciated, thanks.
Upvotes: 0
Views: 2634
Reputation: 47985
If you are writing a game, you should use a game engine. Writing performant games is hard and brute force redrawings of everything on-screen is not going to cut it. Other smart people have already solved these problems and you can take advantage of their cumulated work rather than trying to reinvent the wheel.
I'm no expert on game engines, but the first hit on google for "java game engine" is jmonkeyengine.com. Maybe you should try it.
Upvotes: 1
Reputation: 285403
Consider limiting your repaint(...) to the small area of the GUI that needs to be repainted. Also and again, don't dispose the Graphics object passed to you by the JVM in the paint or paintComponent method. Only dispose one you've created yourself.
Edit 1
If performance of graphics is the key, you may be better off leaving Swing and moving to a library that is optimized for games, animations, and graphics.
Upvotes: 1
Reputation: 4000
You can cache frequently used images via ResourceBundle. The following code provides cache access to images stored in a jar or in absolute path as ImageIcons. First time access with will store an image into a Hashtable. Subsequent calls to the same image will be a lookup. This class must be set under "default" package:
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);
}
}
Usage:
ResourceBundle rsc = ResourceBundle.getBundle("ImageBundle"); //call rsc only once
...
ImageIcon icon = (ImageIcon) rsc.getObject("picture/plus.png");
Upvotes: 1
Reputation: 15729
I had a performance issue with an interactive moving JComponent inside a Container, and found that calling repaint() on the parent, not on the moving component, gave a huge speed increase. I have no idea why - anybody know?
Upvotes: 0