If it’s helpful to anyone, here’s some code I use to take care of all of the VolatileImage rendering. My game sprite objects just hold a reference to the AcceleratedImage and draw the VolatileImage returned by acceleratedImage.getAndCheckVolatileImage(). All VolatileImages are held in the static ImageBank so there’s only one copy rather than having lots floating around wasting memory.
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import java.net.*;
import javax.imageio.*;
/**
*
* @author Keith
*/
public class ImageBank{
static HashMap<String, VolatileImage> volatileImageMap = new HashMap<String, VolatileImage>();
static String imageDirName = "images/";
public ImageBank(){
}
static public void loadAndPutImages(String[] relativeURLNames){
for (String relativeURLName : relativeURLNames){
loadAndPutImageFromRelativeURLString(relativeURLName);
}
}
static public void loadAndPutImageFromRelativeURLString(String relativeURLName){
VolatileImage volatileImage = null;
volatileImageMap.put(relativeURLName, volatileImage);
}
static public void putVolatileImage(String relativeURLName, VolatileImage volatileImage){
volatileImageMap.put(relativeURLName, volatileImage);
}
static public VolatileImage getVolatileImage(String relativeURLName){
return volatileImageMap.get(relativeURLName);
}
public static HashMap<String, VolatileImage> getVolatileImageMap() {
return volatileImageMap;
}
static public BufferedImage readBufferedImage(String relativeURLName){
URL imageURL = ImageBank.class.getResource(imageDirName + relativeURLName);
BufferedImage bufferedImage;
try{
bufferedImage = ImageIO.read(imageURL);
}catch(IOException e){
e.printStackTrace();
return null;
}
System.out.println("ImageBank.loadAndPutImageFromRelativeURLString(): relativeURLName == "+relativeURLName+", w == "+bufferedImage.getWidth()+", h == "+bufferedImage.getHeight());
return bufferedImage;
}
public static VolatileImage createVolatileImage(int width, int height, int transparency) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
VolatileImage image = null;
image = gc.createCompatibleVolatileImage(width, height, transparency);
int valid = image.validate(gc);
if (valid == VolatileImage.IMAGE_INCOMPATIBLE) {
image = createVolatileImage(width, height, transparency);
}
//System.out.println(ImageBank.class.getSimpleName() + ": created new VolatileImage");
return image;
}
public static VolatileImage createTransparentVolatileImage(int width, int height) {
VolatileImage image = ImageBank.createVolatileImage(width, height, Transparency.TRANSLUCENT);
Graphics2D g = (Graphics2D)image.getGraphics();
g.setColor(new Color(0,0,0,0));
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OUT));
g.fillRect(0, 0, image.getWidth(), image.getHeight());
return image;
}
}
import java.util.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import sydneyengine.shooter.*;
import java.net.*;
/**
*
* @author woodwardk
*/
public class AcceleratedImage extends SSAdapter{
String imageURLString;
int width;
int height;
public AcceleratedImage(){
width = -1;
height = -1;
}
public AcceleratedImage(String imageURLString){
this.imageURLString = imageURLString;
// record the width and height
VolatileImage volatileImage = getAndCheckVolatileImage();
width = volatileImage.getWidth();
height = volatileImage.getHeight();
}
protected void drawOntoVolatileImage(VolatileImage vImage, BufferedImage bufferedImage){
Graphics2D g = vImage.createGraphics();
g.drawImage(bufferedImage, 0, 0, null);
g.dispose();
}
public VolatileImage getAndCheckVolatileImage(){
//System.out.println(this.getClass().getSimpleName() + ": drawOntoImage(), "+this.getIndexX()+", "+this.getIndexY()+", time == "+v.getWorld().getTimeNowSeconds());
VolatileImage vImage = ImageBank.getVolatileImage(imageURLString);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
if (vImage == null || vImage.validate(gc) != VolatileImage.IMAGE_OK) {
BufferedImage bufferedImage = ImageBank.readBufferedImage(imageURLString);
vImage = ImageBank.createTransparentVolatileImage(bufferedImage.getWidth(), bufferedImage.getHeight());
ImageBank.putVolatileImage(this.imageURLString, vImage);
drawOntoVolatileImage(vImage, bufferedImage);
}
do {
int valid = vImage.validate(gc);
if (valid == VolatileImage.IMAGE_INCOMPATIBLE) {
BufferedImage bufferedImage = ImageBank.readBufferedImage(imageURLString);
vImage = ImageBank.createTransparentVolatileImage(bufferedImage.getWidth(), bufferedImage.getHeight());
ImageBank.putVolatileImage(this.imageURLString, vImage);
drawOntoVolatileImage(vImage, bufferedImage);
}
} while (vImage.contentsLost());
return vImage;
}
public String getImageURLString() {
return imageURLString;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
}