i've made this little game but the image keeps on flickering. i've read about double buffering online, but i really don't know how to implement the code into my game. here's some of the source code from the constructor and paint method:

public Game(){
		super("test");
		setSize(495,429);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		try{
		    img = ImageIO.read(new File("background.png"));
		} 
		catch (IOException e){
		}
		
		start1 = new MovePlayer();
		start2 = new MoveEnemy();
		start2.start();
		start1.start();	
		
		addKeyListener(new ButtonListener1());
		
	}//close constructor
	public void paint(Graphics g){
		
		super.paint(g);
		
		g.setColor(Color.RED);
		g.fillRect(player.x,player.y,player.width,player.height);//player	
		g.setColor(Color.BLACK);
		g.fillRect(enemy.x,enemy.y,enemy.width,enemy.height);//enemy	
		g.drawImage(img, 0 - focusX, 0 - focusY, this);//background image
	
		
		
	
	}//close paint

i understand the concept of double buffering, but i need help on how to implement it for my case.
i've tried following this code http://www.realapplets.com/tutorial/DoubleBuffering.html but it seems that it only clears the rectangle and not an image like i need.

Recommended Answers

All 24 Replies

Drawing in applets is almost always done with double-buffering.
This means that drawing is first done to an offscreen image, and when all
is done, the offscreen image is drawn on the screen.

From your link.
Have you tried copying the ideas that are shown on that site?

Am I supposed to do that in the paint method? I don't understand why they use clearRect() every time they repaint. i thought it automatically clears everything every single time repaint is call. And also, I'm not familiar with the Graphics object.

In the example, did they create an offscreen image with basically nothing on it?

create an offscreen image with basically nothing on it?

Yes and then draw on it and then draw it in the paint method so it is visible in the GUI,

hmm i still lack clear understanding of the code in the example. i don't know what this is for:

public void update(Graphics g)
     {
          paint(g);
     }

i basically copy and paste the code, and here's what i got so far:

public Game(){
		super("test");
		setSize(495,429);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		dim = getSize(); 
		
		offscreen = createImage(dim.width,dim.height); 
		bufferGraphics = offscreen.getGraphics(); 

		
		
		addKeyListener(new ButtonListener1());
		
	}
	public void paint(Graphics g){
		
		super.paint(g);
		
		bufferGraphics.clearRect(0,0,dim.width,dim.width); 
		bufferGraphics.setColor(Color.RED);
		bufferGraphics.fillRect(player.x,player.y,player.width,player.height);//player	
		bufferGraphics.setColor(Color.BLACK);
		bufferGraphics.fillRect(enemy.x,enemy.y,enemy.width,enemy.height);//enemy	
		
		g.drawImage(offscreen, 0 - focusX, 0 - focusY, this);
	
		
		
	
	}//close paint
	
	public void update(Graphics g)
     {	
         paint(g);
     }

this still flickers a little, and also how and where do i load my background image?

UPDATE: i've tried doing this in the constructor, but it doesn't work.

try {
		   url = this.getClass().getResource ("background.png");	
			offscreen = Toolkit.getDefaultToolkit(). getImage(url);	   
		} 
		catch (Exception e) {
		}
		
		bufferGraphics = offscreen.getGraphics();

Your first piece of code is for the way AWT works. The normal update method processing is bypassed by calling the paint method.

where do i load my background image?

In the constructor?

i did tried to do that in the above code, but it doesn't work/compile.

try {
    url = this.getClass().getResource ("background.png");
    offscreen = Toolkit.getDefaultToolkit(). getImage(url);
    }
    catch (Exception e) {
    }
     
    bufferGraphics = offscreen.getGraphics();

what is wrong with this code?

it doesn't work/compile.

Please post the error messages or explain what "doesn't work".

The getImage method creates a thread and may not finish loading the image when the method returns. You need to use MediaTracker to wait for load to complete.
Better to use ImageIO read if you want the image on return.

try {
		 	url = new URL("background.png");	
			offscreen = ImageIO.read(url);   
		} 
		catch (Exception e) {
			
		}
		bufferGraphics = offscreen.getGraphics();

i'm getting the error "Exception in thread "main" java.lang.NullPointerException"
at bufferGraphics = offscreen.getGraphics();

You have an empty catch block. Is there an error you are ignoring?
add e.printStackTrace() to the catch block.

Also print out the value of url to see if it has a valid value.

i've changed the code a bit

try {
		 	url = this.getClass().getResource("background.png");
			offscreen = ImageIO.read(url);   
		} 
		catch (Exception e) {
			e.printStackTrace() 
		}
		bufferGraphics = offscreen.getGraphics();

but i'm getting the error: "Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException" at bufferGraphics.clearRect(0,0,dim.width,dim.width) from the paint method

the value of the url is file:/C:/java/game/background.png

What variable is null? Why doesn't it have a valid value?
Do you have a variable's definition hiding another of the same name?
What is the value of bufferGraphics on line 9 of the above code?

i hardcoded the values: bufferGraphics.clearRect(0,0,495,429), but i'm still getting the same error message. i don't know what value is null.

the value of bufferGraphics is: "sun.java2d.SunGraphics2D[font=java.awt.Font[family=Dialog,name=Dialog,style=plain,size=12],color=java.awt.Color[r=255,g=255,b=255]]"

i then got rid of bufferGraphics.clearRect(0,0,495,429), but the error came again for bufferGraphics.setColor(Color.RED); so something is wrong with bufferGraphics but i have no idea what b/c i am not familiar with bufferGraphics.

i don't know what value is null.

Print out the values of all the variables used on the line where the NullPointerException occurs to see which one is null.

Post the FULL text of the error message, all the lines. Your short, edited version is leaving out important information.

ok it says bufferGraphics is null initially, but its value changed after, i guess, the second time paint is called. so i did this:

if(x == true){
			super.paint(g);
			printStuff();
			//bufferGraphics.clearRect(0,0,dim.width,dim.height); 
			bufferGraphics.setColor(Color.RED);
			bufferGraphics.fillRect(player.x,player.y,player.width,player.height);//player	
			bufferGraphics.setColor(Color.BLACK);
			bufferGraphics.fillRect(enemy.x,enemy.y,enemy.width,enemy.height);//enemy	
			g.drawImage(offscreen, 0 - focusX, 0 - focusY, this);
			
		}
		x = true;

this works and i'm not getting any error messages, but it still flickers though not as bad as before.
also, i needed to get rid of bufferGraphics.clearRect(0,0,dim.width,dim.height) b/c it would give me a black screen if i include it.

Also, unless you absolutely need AWT, use Swing, among other things it has built in double buffering.

what aspect of awt am i using? so i erase much of my code and only load the background picture onto the screen, and it still flickers really bad.

public Jump(){
		super("test");
		setSize(495,429);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		try {
		 	url = this.getClass().getResource("background.png");
			background = ImageIO.read(url);  
		
		} 
		catch (Exception e) {
			
		}
		
		
		
	}
	public void paint(Graphics g){
		
			super.paint(g);
			g.drawImage(background, 0 - focusX, 0 - focusY, this);
			
			
			
		
			
	}//close paint

what aspect of awt am i using?

Do the names of the component you are using begin with J?
Those would be Swing, otherwise they are probably AWT

Can you post a small complete program that executes to demonstrate your problem?

Aviras is right. The OP's code includes
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
so this looks like Swing, in which case it's already double-buffered unless you have explicitly turned off double buffering.
It's almost always a mistake to override paint, you should override paintComponent instead.
Overriding update(Graphics g) is futile, as update is never called for a Swing component.
http://java.sun.com/products/jfc/tsc/articles/painting/#swing_summary

Finally liones 10-12 in your latest code

catch (Exception e) {
 
}

is a terrible mistake. Put the printStackTrace back and don't remove it!

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.awt.image.BufferedImage;
import javax.imageio.*;

public class Jump extends JFrame{
	
	URL url;
	Image background;
	Move begin;
	
	public Jump(){
		super("test");
		setSize(495,429);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		try {
		 	url = this.getClass().getResource("background.png");
			background = ImageIO.read(url);  
		
		} 
		catch (Exception e) {
			e.printStackTrace();
		}
		begin = new Move();
		begin.start();
		
	}
	public void paint(Graphics g){
			
		super.paint(g);
		g.drawImage(background, 0, 0, this);
				
			
	}//close paint
	
	private class Move extends Thread{
		public void run(){
			while(true){
				try{
					repaint();
					Thread.sleep(50);
				}
				catch(Exception e){
					break;
				}
			}
		}
	}
	
		
	
	
	
	
}

here's a working copy of the code, the flicker still happens (obviously flickers less if thread sleeps for a longer amount of time). i've attached the crappy background picture.

and what do you mean by overriding paintComponent?

Create a new inner class that extends JPanel and contains the paintComponent (not paint) method and add that to the JFrame.

public Jump(){
		super("test");
		setSize(495,429);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		try {
		 	url = this.getClass().getResource("background.png");
			background = ImageIO.read(url);  
		
		} 
		catch (Exception e) {
			e.printStackTrace();
		}
		begin = new Move();
		begin.start();
		p = new PaintStuff();
		add(p);
		
	}
	
	private class PaintStuff extends JPanel{
	
		public PaintStuff(){
			setPreferredSize(new Dimension(495,429));
		}
		public void paintComponent(Graphics g){
			super.paintComponent(g);
			g.drawImage(background, 0, 0, this);			
		}
		
	}//close paintStuff

this works!! i didn't realize that i was using paint instead of paintComponent. however, the picture wouldn't display until i resize the window. paintComponent doesn't even run until window is resized. any ideas why?

It works for me without any resizing.

Try NOT setting visible true until you are ready for the GUI to be seen. You are adding the image panel afterwards

thanks for all the help! that works!!

Glad to be able to help.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.