I'm getting into Java graphics at the moment and I'm reading the book Killer game programming in Java by Andrew Davison. He programs a simple window application that uses the Image class for off-screen rendering and then copying the image to the component. What I find confusing is that one can just create the image and then get the graphics context with:
dbg = dbImage.getGraphics();
I find it confusing, because then we only use the dbg Graphics object to draw stuff but later on we use the dbImage in the paintComponent method to display all the stuff we have drawn to the dbg Object:
g.drawImage(dbImage, 0, 0, null);
So how does the dbImage "know", that it contains all the graphics stuff we have drawn onto the dbg Graphics object?
Here is the whole code:
public class GamePanel extends JPanel implements Runnable{
private static final int PWIDTH = 500;
private static final int PHEIGHT = 400;
private Thread animator;
private volatile boolean running = false;
private volatile boolean gameOver = false;
private Graphics dbg;
private Image dbImage = null;
private Counter counter;
public GamePanel(){
setBackground(Color.white);
setPreferredSize(new Dimension(PWIDTH, PHEIGHT));
// create game components eg. counter.
counter = new Counter(10);
counter.start();
}
private void stopGame(){
running = false;
}
@Override public void addNotify(){
super.addNotify();
startGame();
}
public void startGame(){
if(animator == null || !running){
animator = new Thread(this);
animator.start();
}
}
@Override
public void run() {
running = true;
while(running){
gameUpdate();
gameRender();
repaint();
try{
Thread.sleep(20);
}
catch(InterruptedException ex){
// do something with the exception...
}
}
}
private void gameUpdate(){
if(!gameOver){
// update game state...
if(counter.getCounter() == 0)
gameOver = true;
}
}
private void gameRender(){
if(dbImage == null){
dbImage = createImage(PWIDTH, PHEIGHT);
if(dbImage == null){
System.out.println("dbImage is null");
return;
}
else
dbg = dbImage.getGraphics(); // get graphics context for drawing to off-screen images.
}
// clear the background
dbg.setColor(Color.white);
dbg.fillRect(0, 0, PWIDTH, PHEIGHT);
// draw game elements here...
dbg.setColor(Color.black);
dbg.drawString(Integer.toString(counter.getCounter()), 10, 10);
if(gameOver)
dbg.drawString("Game over...", 10, 20);
}
@Override public void paintComponent(Graphics g){
super.paintComponent(g);
if(dbImage != null)
g.drawImage(dbImage, 0, 0, null);
}
}
the important parts are only the paintComponent method and the gameRender() method though.
Graphicsinstance is its own, it belongs to the image and nothing else. Simply put: theImageinstance keeps a reference to it. (Or the other way around, depending on the implementation. But the end result is the same.) - biziclop