I’m developing a physics sandbox game. I can easily fill the whole screen with rotated, scaled, textured boxes without noticing any FPS drops or excessive CPU usage, and drawing the character without a rotate transformation is fast.
However, if I rotate the character image, or scale it, CPU usage goes through the roof and there is a small but noticable FPS decrease. Using a profiler, I determined that drawImage() was the problem. As far as I can tell the character and texture images are being drawn the same way… It’s really confounding.
From the character:
private VolatileImage character = Util.getGraphicsConfiguration().createCompatibleVolatileImage(200, 200, Transparency.BITMASK); //I tried using Transparency.TRANSLUCENT
[...]
public void draw(Graphics g) throws BuildismException
{
updateImage(); //This line draws the appropriate sections of the player's skin in the right locations. If I remove it, the character is a white box, but drawing it is still slow!
Vec2D pos = getPart().getPosition().worldToScreen(Main.getView());
int w = (int) (200*(Main.getView().scaleFactor/8));
int h = (int) (200*(Main.getView().scaleFactor/8));
int imgX = (int) pos.getX() - w/2;
int imgY = (int) pos.getY() - h/2;
AffineTransform orig = ((Graphics2D)g).getTransform();
AffineTransform rotate = AffineTransform.getRotateInstance(-Math.toRadians(getPart().getRotation()), pos.getX(), pos.getY());
((Graphics2D)g).setTransform(rotate);
g.drawImage(character, imgX, imgY, w, h, null); //I tried using a scale transform here, didn't help
((Graphics2D)g).setTransform(orig);
}
For textured boxes (yes, I know this code is messy and unoptimized… but it works faster than the much simpler code for drawing a character!)
public void setTexture(BufferedImage t)
{
if(t != null)
{
VolatileImage i = Util.getGraphicsConfiguration().createCompatibleVolatileImage(t.getWidth(), t.getHeight(), Transparency.TRANSLUCENT);
Graphics2D g2 = (Graphics2D) i.getGraphics();
Composite old = g2.getComposite();
g2.setColor(transparent);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OUT));
g2.fillRect(0, 0, t.getWidth(), t.getHeight());
g2.setComposite(old);
g2.drawImage(t, 0, 0, null);
texture = i;
}
else
texture = null;
}
[...]
Graphics2D g2 = (Graphics2D) g;
Vec2D worldPos = new Vec2D(body.getPosition());
Vec2D imgPos = worldPos.add(new Vec2D(-getVec2DProp("Size").getX(), getVec2DProp("Size").getY()).mul(0.5)).worldToScreen(Main.getView());
Vec2D rotateCenter = worldPos.worldToScreen(Main.getView());
AffineTransform original = g2.getTransform();
AffineTransform scale = AffineTransform.getScaleInstance(scaleDimensionForScreen(texture.getWidth(), getVec2DProp("Size").getX()), scaleDimensionForScreen(texture.getHeight(), getVec2DProp("Size").getY()));
AffineTransform rotate = AffineTransform.getRotateInstance(-body.getAngle(), rotateCenter.getX(), rotateCenter.getY());
g2.setTransform(rotate);
g2.transform(scale);
g2.drawImage(texture, (int) (imgPos.getX() / ((Main.getView().scaleFactor * getVec2DProp("Size").getX())/texture.getWidth())), (int) (imgPos.getY() / ((Main.getView().scaleFactor * getVec2DProp("Size").getY())/texture.getHeight())), null); //ew
g2.setTransform(original);
Does anyone see a problem?