I have been trying to implement basic text bubbles for a small game I am developing. Not wanting to go too fancy, I started with a basic rounded rectangle with a border containing some text :
Then, I decided that text bubbles should fade out after a preset time. And this is where I stumbled upon a problem : when I tried to display the bubbles in a test window, everything worked fine, but when I displayed them in game, there was a distortion when the bubble faded out. I tested some more, debugged, and found the only difference between the two cases was that on the test window I drew the bubble with the paintComponent method's Graphics, while in game I used BufferedImages to simulate layers and used the graphics from image.createGraphics. I could then successfully replicate the bug :
Here, you see that when the bubble on the left is fading, its rounded corners change shape compared to before fading, whereas the bubble on the right's rounded corners do not change. Indeed, the left bubble is drawn on a BufferedImage which is then drawn on the panel, whereas the right bubble is directly drawn on the panel.
I have isolated the code which is needed to reproduce the problem :
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(400, 400);
JPanel panel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics graphics = image.createGraphics();
paintExampleBubble(graphics, 50, 50);
g.drawImage(image, 0, 0, this);
paintExampleBubble(g, 250, 50);
}
};
frame.getContentPane().add(panel);
frame.setVisible(true);
}
private static final Color background = new Color(1f, 1f, 1f, 0.5f);
private static final Color foreground = new Color(0f, 0f, 0f, 0.5f);
private static final int borderRadius = 16;
private static final int width = 100;
private static final int height = 50;
private static void paintExampleBubble(Graphics g, int x, int y) {
g.setColor(background);
g.fillRoundRect(x, y, width, height, borderRadius, borderRadius);
g.setColor(foreground);
g.drawRoundRect(x, y, width, height, borderRadius, borderRadius);
}
Here is the result the above code produces :
Anyways, this shows that drawing to the BufferedImage is what causes the problem, however it is not an option to let go of BufferedImages at the moment.
I tried to debug the code to see what could cause this difference and only could notice that the graphics object uses different components to draw when transparency was involved, however that doesn't help me in solving my problem as, even if it was possible to force the graphics to do what I want them to, I'd rather avoid hacking if possible.
Does anyone know of a relatively simple and efficient way to solve this problem, or work around it ?
Anyways, thanks for taking the time to read this :)
PS : As this is the first time I ask a question, I may have missed some stuff, so feel free to tell me if that is the case ! It'd be much appreciated.
EDIT : As I said in the comments, the game is pixel-art based therefore I would rather not use anti-aliasing, but keep the basic pixelated look of rounded rectangles.