0

The flickering doesnt always happen, but when it does (about 50% of time) its very bad. I tried doing a few things, initialy i was using canvas then i tried changing to jpanel and overriding paintcomponent, but the problem continues.

Im using two different methods to paint, that i call on my main loop (the first one paints a background terrain and the second one paints images on top of it) at 60 fps.

This is how i created the Jpanel:

private void createDisplay(){

    frame = new JFrame(title);   //linha mais importante, é criada uma JFrame com as propriedades definidas em baixo
    frame.setSize(width, height); //tamanho
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //linha necessário para que a operação acabe quando se sai da janela
    frame.setResizable(false); //remove a opção de alterar o tamanho da janela
    frame.setLocationRelativeTo(null); //definição da posição relativa, neste caso nula
    frame.setVisible(true); //torna a janela visivel

    canvas = new JPanel();


    //canvas = new Canvas(); //inicialização da canvas
    canvas.setPreferredSize(new Dimension(width, height)); //alteração do tamanho da canvas
    canvas.setMaximumSize(new Dimension(width, height));   //tamanho máximo e minimo são definidos para que a 
    canvas.setMinimumSize(new Dimension(width, height));   //canvas tenha sempre o mesmo tamanho

    frame.add(canvas);  //linha essencial, adicina a canvas á jframe

    frame.pack(); //necessário para que a canvas fique bemcentrada na frame (para que se veja toda a canvas)
    frame.addMouseListener(new MouseInput());
    canvas.addMouseListener(new MouseInput());


    }

This is part of my main class loop where i invoke the paint methods:

@Override
public void run() {

init();
Terrain.init();


int fps = 60;
double timePerTick = 1000000000 / fps;
double delta = 0;
long now;
long lastTime = System.nanoTime();
@SuppressWarnings("unused")
int ticks = 0;
long timer = 0;

while(running)  {

    now = System.nanoTime();        
    delta += (now - lastTime) / timePerTick;

    timer += now - lastTime;

    lastTime = now;

    if(delta >= 1){


gamepack.Terrain.paintComponent(g);

gamepack.Units.tick();

gamepack.Enemy.tick();


//gamepack.Enemy.render();




gamepack.Render.paintComponent(g);



ticks++;

delta--;

    }

    if(timer >= 1000000000){
        //System.out.println(ticks);  Verificação das actualizações (ticks e render por segundo)
        ticks = 0;
        timer = 0;
    }

 }
stop();
}    

This is the first paint method for the terrain (its very long i only included the first part):

public static void paintComponent(Graphics g) {  




  //  bs = Display.getCanvas().getBufferStrategy(); 

    //if(bs==null) {                                        
    //  Display.getCanvas().createBufferStrategy(3);  
    //  return;
    //}

    g = Display.getCanvas().getGraphics();                    

    g.clearRect(0, 0, 510, 510); 



    //Primeira Linha (1)
    g.drawImage(grasstopleftcorner ,0,0, null); //1                     
    g.drawImage(grasstopleftcorner ,34,0, null); //2
    g.drawImage(path ,68,0, null); //3
    g.drawImage(path ,102,0, null); //4
    g.drawImage(grasstopleftcorner ,136,0, null); //5

    g.drawImage(grasstopleftcorner ,170,0, null); //6
    g.drawImage(grasstopleftcorner ,204,0, null); //7
    g.drawImage(grasstopleftcorner ,238,0, null); //8
    g.drawImage(grasstopleftcorner ,272,0, null); //9
    g.drawImage(grasstopleftcorner ,306,0, null); //10

    g.drawImage(grasstopleftcorner ,340,0, null); //11
    g.drawImage(grasstopleftcorner ,374,0, null); //12
    g.drawImage(grasstopleftcorner ,408,0, null); //13
    g.drawImage(grasstopleftcorner ,442,0, null); //14
    g.drawImage(grasstopleftcorner ,476,0, null); //15

    //Segunda Linha (2)
    g.drawImage(grasstopleftcorner ,0,34, null); //1
    g.drawImage(grasstopleftcorner ,34,34, null); //2
    g.drawImage(path ,68,34, null); //3
    g.drawImage(path ,102,34, null); //4
    g.drawImage(grasstopleftcorner ,136,34, null); //5

    g.drawImage(grasstopleftcorner ,170,34, null); //6
    g.drawImage(grasstopleftcorner ,204,34, null); //7
    g.drawImage(grasstopleftcorner ,238,34, null); //8
    g.drawImage(grasstopleftcorner ,272,34, null); //9
    g.drawImage(grasstopleftcorner ,306,34, null); //10

    g.drawImage(grasstopleftcorner ,340,34, null); //11
    g.drawImage(grasstopleftcorner ,374,34, null); //12
    g.drawImage(grasstopleftcorner ,408,34, null); //13
    g.drawImage(grasstopleftcorner ,442,34, null); //14
    g.drawImage(grasstopleftcorner ,476,34, null); //15

And this is the last paint method for the images to be painted on top of the terrain (or background):

public static void paintComponent(Graphics g){


//Código Comum a todas as Classes   
//bs = Display.getCanvas().getBufferStrategy(); 

//if(bs==null) {                                        
/// Display.getCanvas().createBufferStrategy(3);  
//  return;
//}

    g = Display.getCanvas().getGraphics();    
//g.clearRect(0, 0, 510, 510);
//Enemies
p=0;

//Este while serve para actualizar as imagens de todas as unidades ao incrementar o p, todas as variáveis do drawimage são actualizadas no tick()
while(p<Main.enemylist.size()){ 

    if(Main.enemylist.get(p).health > 0){



//  g.drawImage(Main.castleimg,(int) 100,(int)100, null);
    g.drawImage(Main.enemylist.get(p).usedimg.getSubimage(Main.enemylist.get(p).imgx*32, Main.enemylist.get(p).imgy*32 , 32, 32),(int) Main.enemylist.get(p).targetx - 16,(int) Main.enemylist.get(p).targety- 16, null);
    }
    p++;
}

    //Units
    p=0;

    //Este while serve para actualizar as imagens de todas as unidades ao incrementar o p, todas as variáveis do drawimage são actualizadas no tick()
    while(p<Main.dudelist.size()){ 

        if(Main.dudelist.get(p).selected){

            g.drawImage(Main.dotimage,(int) Main.dudelist.get(p).currentx + 7,(int) Main.dudelist.get(p).currenty - 19, null);

        }
        if (Main.dudelist.get(p).health > 0){

    //  g.drawImage(Main.castleimg,(int) 100,(int)100, null);
        g.drawImage(Main.dudelist.get(p).usedimg.getSubimage(Main.dudelist.get(p).imgx*32, Main.dudelist.get(p).imgy*32 , 32, 32),(int) Main.dudelist.get(p).currentx ,(int) Main.dudelist.get(p).currenty, null);
        }
        p++;

    }














g.dispose(); 

}

I hope i explained my problem well and that i included all thats needed, im fairly new to java and programming, hopefully it wasnt very confusing.

Aquan1111
  • 65
  • 1
  • 7
  • 1
    1) For better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete Verifiable Example) or [SSCCE](http://www.sscce.org/) (Short, Self Contained, Correct Example). 2) One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). – Andrew Thompson Mar 05 '15 at 14:44
  • 1
    Further tips: 1) Use a logical and consistent form of indenting code lines and blocks. The indentation is intended to make the flow of the code easier to follow! 2) A single blank line of white space in source code is all that is *ever* needed. Blank lines after `{` or before `}` are also typically redundant. 3) `static` is not your friend. It more often breaks things than fixes them. – Andrew Thompson Mar 05 '15 at 14:46
  • It seems like you have a heavy load of images drawn in your paint-Method. Maybe you can try to reduce the number of images drawn, if you put like 4 adjacent images into one, that would reduce the performance-impact by far. Or, if thats not possible, you let java build a current large image, comprising of all small images, and draw this one larger image. (just an idea, don't know how the code should look like) – Officer Bacon Mar 05 '15 at 14:46
  • @OfficerBacon Thank you for the reply, i do have a lot of images because the background is composed of many different tiles and i paint a image in every single tile individually. Could this be causing the flickering? – Aquan1111 Mar 05 '15 at 15:07
  • @AndrewThompson Thank you for the help, i will try to tidy up and organize things better next time. I have noticed the problems that static can create i will try to avoid it as much as possible, however many times i cant because of the "you cant make a static reference to a non static method error" i guess i should read up on the subject and try to improve – Aquan1111 Mar 05 '15 at 15:10

2 Answers2

1

A JPanel by default is double buffered, preventing flickering. This relies on an event coming in on the sole Event Dispatching Thread, and then paintComponent is called. This paintComponent can also be invoked manually (indirectly) by for instance repaint(50L).

Animation can be done by a Swing Timer, with a periodically called method.

This should replace your while loop.

This is a bit inside-out, but does away with a long loop dealing with all. One writes separate event handlers that for instance on key-down can increase a speed counter, and such.

In the paintComponent, a clear (in general) is not needed. The optimization of the rest is a matter of inventiveness. A .png image for instance can have transparency so you could make an entire holed frame image.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
1
g = Display.getCanvas().getGraphics();     

Don't use the getGraphics() method.

The paintComponent() method already has a Graphics object. That is the object you should use for painting.

You should also have: super.paintComponent(g);

at the top of the method to clear the background of the panel. This is better than using the clearRect(...) method with hard coded values.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • Thank for your help. Ive made some changes and tried to use super.paintComponent(g); instead of getGaphics(); however ive been getting a java.lang.NullPointerException. If use the old line: g = Display.getCanvas().getGraphics(); the problems doesnt occur. – Aquan1111 Mar 06 '15 at 16:29
  • @Aquan1111, I have never had a NPE when using the Graphics object passed to the paintComponent() method of a Swing component, so I have no idea what you are doing. I suggest you start with the Swing tutorial on [Custom Painting](http://docs.oracle.com/javase/tutorial/uiswing/painting/index.html) to learn the basics first before writing more complex painting code. – camickr Mar 06 '15 at 19:08
  • Thank you for the reply, i have posted another question where i think I explain the problem better, if you would like too see its at: [link](http://stackoverflow.com/questions/28916103/java-lang-nullpointerexception-on-super-paintcomponentg) – Aquan1111 Mar 07 '15 at 14:55