PaintComponent runs slow and flickers in Java

Started by
8 comments, last by P0jahn 11 years, 4 months ago
I have a game which is painting a lot of gifs and images everywhere and it runs a little bit slow meanwhile. Sometimes it can run very good for a minute or something, but then it starts to lag and stuff. Most of the images flicker from time to time. Not extremely much, but they still flicker a little bit.
I will shoe the relevant parts of my code and maybe you can find what I need to do. I have googled and seen things with dubble buffering and stuff, but I don't really get it.

The code here is just a lot of stuff, I have removed a lot of "game logic" and image files so the names are not the same, but you will at least get my method with this code:



public class Game3 extends JPanel implements ActionListener{

ImageIcon flowerIcon = new ImageIcon("img\\Dragon.gif");
Image flower = flowerIcon.getImage();
ImageIcon flowerhitIcon = new ImageIcon("img\\DragonHit.gif");
Image flowerhit = flowerhitIcon.getImage();
ImageIcon flowerfireIcon = new ImageIcon("img\\DragonFire.gif");
Image flowerfire = flowerfireIcon.getImage();

URL music = null;
AudioClip musicSound;
URL pop = null;
AudioClip popSound;
Font font;
Random r;
boolean skott = false;
Nalle nalle = new Nalle();
ArrayList<Bubble> bubblor = new ArrayList<Bubble>();
Timer tim;

Game3(){
try {
wee = new URL("file:img\\wee.wav");
}
catch (MalformedURLException exp) {
}
weeSound = Applet.newAudioClip(wee);
try {
namnam = new URL("file:img\\namnamn.wav");
}
catch (MalformedURLException exp) {
}
namnamSound = Applet.newAudioClip(namnam);
bubbles = Integer.parseInt(textBubbles);
tim = new Timer(20, this);
setFocusable(true);
addKeyListener(k);
musicSound.loop();
tim.start();
}
}

public void checkCollisions(){
blablabla
}

@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
if(Map.redLevel == true){
g2d.drawImage(background, himmelX, himmelY, null);
g2d.drawImage(background2, himmelX2, himmelY2, null);
g2d.drawImage(lava, grassX+80, grassY+355, null);
g2d.drawImage(lava, grassX+680, grassY+130, null);
repaint();
}
}

@Override
public void actionPerformed(ActionEvent arg0) {
blablabla....
}
Advertisement
Are you regulating the FPS (Frame per seconds) of your game loop ? You do not need to draw constantly the images because it will just provoke a huge lag. You can simply draw your images let's say 25 times per seconds. I don't think you should override the PaintComponent method to draw all your images as you can't control when this method is called.

I think you should try going with Slick2D API, it provides everything you need for your game and it's pretty simple to use. It's not a good idea to use Swing as you do for a game as Swing is slow and is not made for games, it's made for interface such as menus.

Slick2D will provide you a game engine which will regulate the FPS and a Graphic object where you can draw your images.
Hmm, but all my Images are kind of moving and If I don't repaint them, then they will not move?
Normally, you will repaint them but only a fixed number of times in a second. This way you can control the speed of the game. But first, I think you really shouldn't use Swing to make a game, you will get other performances issues like the one you have.
You can easily switch to Slick 2D it shouldn't be hard to do so. This is an example of a simple game application using Slick.


package slick.path2glory.SimpleGame;

import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;

public class SimpleGame extends BasicGame{

public SimpleGame()
{
super("Slick2DPath2Glory - SimpleGame");
}

@Override
public void init(GameContainer gc)
throws SlickException {
//this is where you will load your images
}

@Override
public void update(GameContainer gc, int delta)
throws SlickException
{
//this is where you will control the game AI
}

public void render(GameContainer gc, Graphics g)
throws SlickException
{
//This is where you can draw your images in the provided Graphics
}

public static void main(String[] args)
throws SlickException
{
AppGameContainer app =
new AppGameContainer(new SimpleGame());

app.setDisplayMode(800, 600, false);
app.start();
}
}


As you can see it's pretty much the same concept that you are using for drawing, but the API provides a game container which is a game loop in a independant window.
Well, in my case then I rely on the timer which is 20 frames per millisecond. If I make a separate update mechanism, wouldn't like 100 or something be a little bit too slow?
My game is very soon finished and it works fine as it is at the moment, but not perfect - that's why I made this thread. I will try the SLIK on my next game!
For the timer you can try differents values to test the stability of your games but as I said 25 frames per second should be enough.

And is the repaint() method call is really necessary in your paintComponent method ?

@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
if(Map.redLevel == true){
g2d.drawImage(background, himmelX, himmelY, null);
g2d.drawImage(background2, himmelX2, himmelY2, null);
g2d.drawImage(lava, grassX+80, grassY+355, null);
g2d.drawImage(lava, grassX+680, grassY+130, null);
repaint();
}
}
I just had a look at an old game I made and I did the following for double buffering. I can't remember why but I just played it and it runs fine.


panel.setDoubleBuffered(true);
RepaintManager.currentManager(frame).setDoubleBufferingEnabled(true);


Where panel is my extended JPanel with the overriden paintComponent() method (I saw that I'm not calling repaint() at the end of my paintComponent() method, which supports PsychotikRabbit's suggestion).
Where frame is a JFrame.

Hope this works for you too.

Matt
It's been a while since I last did graphics in native Java, but from the looks of it, you're not using active rendering. This article helped me a lot, when I got tired of the slow repaint() calls: http://www.gamedev.net/page/resources/_/technical/general-programming/java-games-active-rendering-r2418
I have 66 frames per second without any problems in Swing.

This topic is closed to new replies.

Advertisement