iDevGames Forums
Java: Double Buffering - Printable Version

+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Programming Languages & Scripting (/forum-8.html)
+--- Thread: Java: Double Buffering (/thread-6677.html)



Java: Double Buffering - xDexx - Oct 18, 2003 10:24 AM

i found a tutorial on how to do double buffering in java and i cant get it to work. i have looked in many different places and they all have the same way of doing it. can some one point me in the right direction?(i am using eclipse). thanks in advance!

i get these errors:

Exception in thread "main" java.lang.NullPointerException
at DoubleBuffer.resetBuffer(DoubleBuffer.java:57)
at DoubleBuffer.paint(DoubleBuffer.java:30)
at Snaak.main(Snaak.java:21)

here is my .java files:

Snaak.java:
Code:
import javax.swing.*;
import java.awt.*;

public class Snaak
{
    public static void main(String[] args)
    {
        player p1 = new player(200,300);
        orbs o1 = new orbs(10,10,1);
        JFrame window = new JFrame();
        window.setSize(640,480);
        window.setVisible(true);
        window.setBackground(Color.black);
        
        DoubleBuffer buffer = new DoubleBuffer();
        Graphics g = window.getGraphics();


        while(true){
            o1.orbit(p1);
            buffer.paint(g);

        }
    }        
}

DoubleBuffer.java:
Code:
import java.awt.*;

public class DoubleBuffer extends Panel
{
        private int bufferWidth;
        private int bufferHeight;
        private Image bufferImage;
        private Graphics bufferGraphics;
        
    public DoubleBuffer(){
            super();
        }
        
    
    public void paint(Graphics g){
        if(bufferWidth!=getSize().width || bufferHeight!=getSize().height || bufferImage==null || bufferGraphics==null)
            resetBuffer();
        

        if(bufferGraphics!=null){
                    bufferGraphics.clearRect(0,0,bufferWidth,bufferHeight);

                    paintBuffer(bufferGraphics);

                    g.drawImage(bufferImage,0,0,this);
                }
    }

    private void resetBuffer(){
        bufferWidth=getSize().width;
        bufferHeight=getSize().height;

        if(bufferGraphics!=null){
            bufferGraphics.dispose();
            bufferGraphics=null;
        }
        if(bufferImage!=null){
            bufferImage.flush();
            bufferImage=null;
        }
        System.gc();

        bufferImage=createImage(bufferWidth,bufferHeight);
        bufferGraphics=bufferImage.getGraphics();
    }
        
    public void paintBuffer(Graphics g){
        g.drawRect(10,10,10,10);
    }

}



Java: Double Buffering - Fenris - Oct 18, 2003 02:01 PM

You are most likely dying in one of these lines:

bufferImage=createImage(bufferWidth,bufferHeight);
bufferGraphics=bufferImage.getGraphics();

(Your message said line 57, but I don't know what line that is, as the line breaks are messed up in the message)

I'd have to take a look at the createImage method, because I'm very sure that something bad happens there. I think that createImage somehow returns a null pointer, and that .getGraphics() crashes on that. Could you show me createImage, and I'll have it fixed for you in no-time. Smile


Java: Double Buffering - xDexx - Oct 18, 2003 11:22 PM

here is the information on createImage http://java.sun.com/j2se/1.4.2/docs/api/java/awt/Toolkit.html
thanks for looking in to this!


Java: Double Buffering - Fenris - Oct 19, 2003 02:40 AM

Ah, createImage was from AWT, didn't see that. Sorry. Smile

This one was evil, and I'm not quite sure I've found the problem either... :-/

From http://java.sun.com/j2se/1.4.2/docs/api/java/awt/Component.html#createImage(int,%20int) :

Quote:Returns:
an off-screen drawable image, which can be used for double buffering. The return value may be null if the component is not displayable. This will always happen if GraphicsEnvironment.isHeadless() returns true.

So, that is definitely what happens. I'd check for that (just System.out.println (GraphicsEnvironment.isHeadless())Wink (Or something similar). If that returns true, then we've found the problem.

The problem then, is that to be able to call createImage, you have to call it from a displayable class (you derive DoubleBuffer from Panel, so that's covered) that is inserted into the view hierarchy. Unless you do something fancy outside the code you showed, then that is your problem. The DoubleBuffer panel needs to be added to the JFrame somehow - which kind of contradicts the purpose of a double buffer anyway.

Now, there are two ways to fix this. Either, give the DoubleBuffer class a pointer to your window, and connect that in the constructor:

Code:
DoubleBuffer buffer = new DoubleBuffer (window);

Then in the constructor:

DoubleBuffer (JFrame w)
{
    myWindow = w;
    super();
}

That would create a reference to a window that we can abuse to create your image. If you go with this method, you would create the empty buffer with myWindow.createImage (w, h); instead.

The other way is to insert the DoubleBuffer into the window anyway, and just make sure that it doesn't show itself. (We make it very, very small and put it outside the window)

Do this after you created the DoubleBuffer:
Code:
buffer.setBounds (-1,-1,1,1);
window.getContentPane().add (buffer);

...and stuff will work out fine. However, this will most definitely ruin your frame rate, as it might be that it will render everything twice. (Not sure about this, try it out).

The third way is to experiment with window.setDoubleBuffered(true), but I have never used that, so your mileage may vary.

Good luck, and post back! Smile


Java: Double Buffering - davecom - Oct 21, 2003 02:11 PM

Looks like bufferWidth is undefined when paint() is called. Didn't look hard though maybe I missed something.


Java: Double Buffering - Steven - Oct 21, 2003 04:33 PM

What would really help is: what line of code is number 57?


Java: Double Buffering - deadrat - May 23, 2006 07:10 PM

I am having a problem with buffering images.. i just need to find a way to double buffer the paint function
Code:
//
//  Map.java
//  Yutog
//
//  Created by Eric Haldenby on 5/17/06.
//  Copyright 2006 __MyCompanyName__. All rights reserved.
//
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferStrategy;
import java.awt.Window;
import java.awt.image.BufferedImage;

public class Map extends JFrame implements KeyListener{
    BufferStrategy strat;
    BufferedImage offscreen;
    Player mainChar;
    int needRefresh;
    Scene [][]scene;
    int curX,curY;
    int maxX,maxY;
    
    public Map(int charac,String name)
    {
        curX=0;
        curY=0;
        mainChar=new Player(charac,name);
        setSize(20*25,16*25);
        FileParser myFile=new FileParser("Yutog.in");
        int []xy=myFile.getAmountScenes();
        scene=new Scene[xy[0]][xy[1]];
        maxX=xy[0]-1;
        maxY=xy[1]-1;
        for (int y=0;y<xy[1];y++)
            for (int x=0;x<xy[0];x++)
                scene[x][y]=new Scene(myFile.read());
        mainChar=new Player(charac,name);
        needRefresh=3;
        setVisible(true);
        System.out.println("Creating class");
        addKeyListener(this);
        }
    
        
public void keyPressed(KeyEvent ke){
    if (ke.getKeyCode()==KeyEvent.VK_UP | ke.getKeyCode()==KeyEvent.VK_DOWN | ke.getKeyCode()==KeyEvent.VK_RIGHT | ke.getKeyCode()==KeyEvent.VK_LEFT) {
        
        if (ke.getKeyCode()==KeyEvent.VK_UP){
        if (mainChar.getGlobY()==0)
        {
        if (curY!=maxY)
                if (scene[curX][curY+1].getTexture(mainChar.getGlobX(),14).getMoveable())
                {
                mainChar.resetDY();
                curY+=1;
                }
                else
                System.out.println("cannot go");
                }    
            else if (scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()-1).getActiveateable())
            scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()-1).doAction(mainChar);
            else if (scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()-1).getMoveable()) {
            mainChar.move(Sprite.kMoveUp);
            }
        }
        if (ke.getKeyCode()==KeyEvent.VK_DOWN){
        if (mainChar.getGlobY()==14)
        {
            if (curY!=0)
                if (scene[curX][curY-1].getTexture(mainChar.getGlobX(),0).getMoveable())
                {
                mainChar.resetUY();
                curY-=1;
                }else
                System.out.println("cannot go");
        }else if (scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()+1).getActiveateable())
            scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()+1).doAction(mainChar);
            if (scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()+1).getMoveable()) {
            mainChar.move(Sprite.kMoveDown);
            }
        }
        if (ke.getKeyCode()==KeyEvent.VK_RIGHT) {
            if (mainChar.getGlobX()==19)
                {
                    if (curX!=maxX)
                    if (scene[curX+1][curY].getTexture(0,mainChar.getGlobY()).getMoveable()){
                    mainChar.resetRX();
                    curX+=1;
                    }
                    else
                System.out.println("cannot go");
                }
            else if (scene[curX][curY].getTexture((mainChar.getX()/25)+1,mainChar.getGlobY()).getActiveateable())
            scene[curX][curY].getTexture((mainChar.getX()/25)+1,mainChar.getGlobY()).doAction(mainChar);
            else if (scene[curX][curY].getTexture((mainChar.getX()/25)+1,mainChar.getGlobY()).getMoveable()) {
            mainChar.move(Sprite.kMoveRight);
            }
        }
        if (ke.getKeyCode()==KeyEvent.VK_LEFT) {
            if (mainChar.getGlobX()==0)
            {
                if (curX!=0)
                    if (scene[curX-1][curY].getTexture(14,mainChar.getGlobY()).getMoveable()){
                    mainChar.resetLX();
                    curX-=1;
                    }
                    else
                System.out.println("cannot go");
            }else if (scene[curX][curY].getTexture((mainChar.getX()/25)-1,mainChar.getGlobY()).getActiveateable())
                scene[curX][curY].getTexture((mainChar.getX()/25)-1,mainChar.getGlobY()).doAction(mainChar);
                else if (scene[curX][curY].getTexture((mainChar.getX()/25)-1,mainChar.getGlobY()).getMoveable()) {
                mainChar.move(Sprite.kMoveLeft);
                }
                
    
        }

        /*if (mainChar.getX()<=0) {
            mainChar.resetLX();
            needRefresh=3;
            curX-=1;
            }else if ( mainChar.getX()>25*19) {
        if (curX!=25){
            mainChar.resetRX();
            needRefresh=3;
            curX+=1;
            }
        }*/
        paint(getGraphics());
        System.out.println("curX: "+curX + " curY: "+curY + " globX: " +mainChar.getGlobX()+" globY: "+mainChar.getGlobY());
    }
}

public void keyReleased(KeyEvent ke)
{
}
public void keyTyped(KeyEvent ke)
{
}
public void update(Graphics g)
{
    paint(g);
}
public void paintWorld() {
    Graphics g = strat.getDrawGraphics();
    
        
    g.drawImage(mainChar.getImage() ,mainChar.getX(),mainChar.getY(),25,25,null);
     strat.show();
    
}
public void paint(Graphics g)
{
    super.paint(g);
    System.out.println("painting refresh:"+needRefresh);
        for (int y=1;y<16;y++)
        for (int x=0;x<20;x++)
            g.drawImage(scene[curX][curY].getImage(x,y-1),x*25,y*25,25,25,null);
    
        g.drawImage(mainChar.getImage() ,mainChar.getX(),mainChar.getY(),25,25,null);
        
}
}



Java: Double Buffering - deadrat - May 23, 2006 08:13 PM

Im having the same trouble can any one show me how i can double buffer the paint method in this class.
Code:
//
//  Map.java
//  Yutog
//
//  Created by Eric Haldenby on 5/17/06.
//  Copyright 2006 __MyCompanyName__. All rights reserved.
//
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferStrategy;
import java.awt.Window;
import java.awt.image.BufferedImage;

public class Map extends JFrame implements KeyListener{
    BufferStrategy strat;
    BufferedImage offscreen;
    Player mainChar;
    int needRefresh;
    Scene [][]scene;
    int curX,curY;
    int maxX,maxY;
    
    public Map(int charac,String name)
    {
        curX=0;
        curY=0;
        mainChar=new Player(charac,name);
        setSize(20*25,16*25);
        FileParser myFile=new FileParser("Yutog.in");
        int []xy=myFile.getAmountScenes();
        scene=new Scene[xy[0]][xy[1]];
        maxX=xy[0]-1;
        maxY=xy[1]-1;
        for (int y=0;y<xy[1];y++)
            for (int x=0;x<xy[0];x++)
                scene[x][y]=new Scene(myFile.read());
        mainChar=new Player(charac,name);
        needRefresh=3;
        setVisible(true);
        System.out.println("Creating class");
        addKeyListener(this);
        }
    
        
public void keyPressed(KeyEvent ke){
    if (ke.getKeyCode()==KeyEvent.VK_UP | ke.getKeyCode()==KeyEvent.VK_DOWN | ke.getKeyCode()==KeyEvent.VK_RIGHT | ke.getKeyCode()==KeyEvent.VK_LEFT) {
        
        if (ke.getKeyCode()==KeyEvent.VK_UP){
        if (mainChar.getGlobY()==0)
        {
        if (curY!=maxY)
                if (scene[curX][curY+1].getTexture(mainChar.getGlobX(),14).getMoveable())
                {
                mainChar.resetDY();
                curY+=1;
                }
                else
                System.out.println("cannot go");
                }    
            else if (scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()-1).getActiveateable())
            scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()-1).doAction(mainChar);
            else if (scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()-1).getMoveable()) {
            mainChar.move(Sprite.kMoveUp);
            }
        }
        if (ke.getKeyCode()==KeyEvent.VK_DOWN){
        if (mainChar.getGlobY()==14)
        {
            if (curY!=0)
                if (scene[curX][curY-1].getTexture(mainChar.getGlobX(),0).getMoveable())
                {
                mainChar.resetUY();
                curY-=1;
                }else
                System.out.println("cannot go");
        }else if (scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()+1).getActiveateable())
            scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()+1).doAction(mainChar);
            if (scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()+1).getMoveable()) {
            mainChar.move(Sprite.kMoveDown);
            }
        }
        if (ke.getKeyCode()==KeyEvent.VK_RIGHT) {
            if (mainChar.getGlobX()==19)
                {
                    if (curX!=maxX)
                    if (scene[curX+1][curY].getTexture(0,mainChar.getGlobY()).getMoveable()){
                    mainChar.resetRX();
                    curX+=1;
                    }
                    else
                System.out.println("cannot go");
                }
            else if (scene[curX][curY].getTexture((mainChar.getX()/25)+1,mainChar.getGlobY()).getActiveateable())
            scene[curX][curY].getTexture((mainChar.getX()/25)+1,mainChar.getGlobY()).doAction(mainChar);
            else if (scene[curX][curY].getTexture((mainChar.getX()/25)+1,mainChar.getGlobY()).getMoveable()) {
            mainChar.move(Sprite.kMoveRight);
            }
        }
        if (ke.getKeyCode()==KeyEvent.VK_LEFT) {
            if (mainChar.getGlobX()==0)
            {
                if (curX!=0)
                    if (scene[curX-1][curY].getTexture(14,mainChar.getGlobY()).getMoveable()){
                    mainChar.resetLX();
                    curX-=1;
                    }
                    else
                System.out.println("cannot go");
            }else if (scene[curX][curY].getTexture((mainChar.getX()/25)-1,mainChar.getGlobY()).getActiveateable())
                scene[curX][curY].getTexture((mainChar.getX()/25)-1,mainChar.getGlobY()).doAction(mainChar);
                else if (scene[curX][curY].getTexture((mainChar.getX()/25)-1,mainChar.getGlobY()).getMoveable()) {
                mainChar.move(Sprite.kMoveLeft);
                }
                
    
        }

        /*if (mainChar.getX()<=0) {
            mainChar.resetLX();
            needRefresh=3;
            curX-=1;
            }else if ( mainChar.getX()>25*19) {
        if (curX!=25){
            mainChar.resetRX();
            needRefresh=3;
            curX+=1;
            }
        }*/
        paint(getGraphics());
        System.out.println("curX: "+curX + " curY: "+curY + " globX: " +mainChar.getGlobX()+" globY: "+mainChar.getGlobY());
    }
}

public void keyReleased(KeyEvent ke)
{
}
public void keyTyped(KeyEvent ke)
{
}
public void update(Graphics g)
{
    paint(g);
}
public void paintWorld() {
    Graphics g = strat.getDrawGraphics();
    
        
    g.drawImage(mainChar.getImage() ,mainChar.getX(),mainChar.getY(),25,25,null);
     strat.show();
    
}
public void paint(Graphics g)
{
    super.paint(g);
    System.out.println("painting refresh:"+needRefresh);
        for (int y=1;y<16;y++)
        for (int x=0;x<20;x++)
            g.drawImage(scene[curX][curY].getImage(x,y-1),x*25,y*25,25,25,null);
    
        g.drawImage(mainChar.getImage() ,mainChar.getX(),mainChar.getY(),25,25,null);
        
}
}



Java: Double Buffering - deadrat - May 23, 2006 09:23 PM

so.. basically i was foolin round with buffered image and... it is rly rly smooth now...
but... there are some bugs... the images are layed over top of each other when switching scenes. The important changes are in Map constructor and paint().
Code:
//
//  Map.java
//  Yutog
//
//  Created by Eric Haldenby on 5/17/06.
//  Copyright 2006 __MyCompanyName__. All rights reserved.
//
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferStrategy;
import java.awt.Window;
import java.awt.image.BufferedImage;

public class Map extends JFrame implements KeyListener{
    BufferedImage offscreen;
    Graphics graph;
    Player mainChar;
    int needRefresh;
    Scene [][]scene;
    int curX,curY;
    int maxX,maxY;
    JFrame window;
     BufferStrategy strategy;
    
    public Map(int charac,String name)
    {
        curX=0;
        curY=0;
        offscreen=new BufferedImage(20*25,15*25,BufferedImage.TYPE_BYTE_INDEXED);
        graph=offscreen.getGraphics();
        mainChar=new Player(charac,name);
        setSize(20*25,16*25);
        FileParser myFile=new FileParser("Yutog.in");
        int []xy=myFile.getAmountScenes();
        scene=new Scene[xy[0]][xy[1]];
        maxX=xy[0]-1;
        maxY=xy[1]-1;
        for (int y=0;y<xy[1];y++)
            for (int x=0;x<xy[0];x++)
                scene[x][y]=new Scene(myFile.read());
        mainChar=new Player(charac,name);
        needRefresh=3;
        setVisible(true);
        System.out.println("Creating class");
        addKeyListener(this);
        
        }
    
        
public void keyPressed(KeyEvent ke){
    if (ke.getKeyCode()==KeyEvent.VK_UP | ke.getKeyCode()==KeyEvent.VK_DOWN | ke.getKeyCode()==KeyEvent.VK_RIGHT | ke.getKeyCode()==KeyEvent.VK_LEFT) {
        
        if (ke.getKeyCode()==KeyEvent.VK_UP){
        if (mainChar.getGlobY()==0)
        {
        if (curY!=maxY)
                if (scene[curX][curY+1].getTexture(mainChar.getGlobX(),14).getMoveable())
                {
                mainChar.resetDY();
                curY+=1;
                }
                else
                System.out.println("cannot go");
                }    
            else if (scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()-1).getActiveateable())
            scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()-1).doAction(mainChar);
            else if (scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()-1).getMoveable()) {
            mainChar.move(Sprite.kMoveUp);
            }
        }
        if (ke.getKeyCode()==KeyEvent.VK_DOWN){
        if (mainChar.getGlobY()==14)
        {
            if (curY!=0)
                if (scene[curX][curY-1].getTexture(mainChar.getGlobX(),0).getMoveable())
                {
                mainChar.resetUY();
                curY-=1;
                }else
                System.out.println("cannot go");
        }else if (scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()+1).getActiveateable())
            scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()+1).doAction(mainChar);
            if (scene[curX][curY].getTexture(mainChar.getX()/25,mainChar.getGlobY()+1).getMoveable()) {
            mainChar.move(Sprite.kMoveDown);
            }
        }
        if (ke.getKeyCode()==KeyEvent.VK_RIGHT) {
            if (mainChar.getGlobX()==19)
                {
                    if (curX!=maxX)
                    if (scene[curX+1][curY].getTexture(0,mainChar.getGlobY()).getMoveable()){
                    mainChar.resetRX();
                    curX+=1;
                    }
                    else
                System.out.println("cannot go");
                }
            else if (scene[curX][curY].getTexture((mainChar.getX()/25)+1,mainChar.getGlobY()).getActiveateable())
            scene[curX][curY].getTexture((mainChar.getX()/25)+1,mainChar.getGlobY()).doAction(mainChar);
            else if (scene[curX][curY].getTexture((mainChar.getX()/25)+1,mainChar.getGlobY()).getMoveable()) {
            mainChar.move(Sprite.kMoveRight);
            }
        }
        if (ke.getKeyCode()==KeyEvent.VK_LEFT) {
            if (mainChar.getGlobX()==0)
            {
                if (curX!=0)
                    if (scene[curX-1][curY].getTexture(14,mainChar.getGlobY()).getMoveable()){
                    mainChar.resetLX();
                    curX-=1;
                    }
                    else
                System.out.println("cannot go");
            }else if (scene[curX][curY].getTexture((mainChar.getX()/25)-1,mainChar.getGlobY()).getActiveateable())
                scene[curX][curY].getTexture((mainChar.getX()/25)-1,mainChar.getGlobY()).doAction(mainChar);
                else if (scene[curX][curY].getTexture((mainChar.getX()/25)-1,mainChar.getGlobY()).getMoveable()) {
                mainChar.move(Sprite.kMoveLeft);
                }
                
    
        }

        /*if (mainChar.getX()<=0) {
            mainChar.resetLX();
            needRefresh=3;
            curX-=1;
            }else if ( mainChar.getX()>25*19) {
        if (curX!=25){
            mainChar.resetRX();
            needRefresh=3;
            curX+=1;
            }
        }*/
        repaint();
        System.out.println("curX: "+curX + " curY: "+curY + " globX: " +mainChar.getGlobX()+" globY: "+mainChar.getGlobY());
    }
}

public void keyReleased(KeyEvent ke)
{
}
public void keyTyped(KeyEvent ke)
{
}
//public void update(Graphics g)
//{
//    paint();
//}

public void paint(Graphics g)
{
    
    super.paint(graph);
    for (int y=1;y<16;y++)
        for (int x=0;x<20;x++)
            g.drawImage(scene[curX][curY].getImage(x,y-1),x*25,y*25,25,25,null);
    
        g.drawImage(mainChar.getImage() ,mainChar.getX(),mainChar.getY(),25,25,null);
    graph.drawImage(offscreen,0,0,null);
    
}
}



Java: Double Buffering - Tools10 - May 26, 2006 04:46 AM

It's early in the morning but I don't understand what's the problem?


Java: Double Buffering - StealthyCoin - Jun 16, 2006 11:00 PM

deadrat Wrote:so.. basically i was foolin round with buffered image and... it is rly rly smooth now...
but... there are some bugs... the images are layed over top of each other when switching scenes. The important changes are in Map constructor and paint().

A) Make your own thread.
B) Your ... writing....style made my blood pressure rise ever so slightly
C) I had a bunch of trouble reading your code, maybe my browser formatted it badly but still clean it up a little, whitespace is your friend Smile

I have this to say: If it is indeed a game you do NOT want to be using paint() ever. You want to set up your own rendering system using the BufferStrategy.

Here is what I use:

Code:
import java.awt.*;
import java.awt.image.BufferStrategy;

public class GameCanvas extends Canvas implements Runnable    {
    public static final int NUM_BUFFERS = 2;
    public static final int DEFAULT_PERIOD = 10;
    public static final int MAX_DELAYS = 16;
    
    private volatile int period;
    private volatile boolean running;
    private volatile boolean paused;
    private Thread animator;
    private BufferStrategy strategy;
    
    public GameCanvas()    {
        int refreshRate = GraphicsEnvironment
            .getLocalGraphicsEnvironment()
            .getDefaultScreenDevice()
            .getDisplayMode()
            .getRefreshRate();
        if (refreshRate == DisplayMode.REFRESH_RATE_UNKNOWN)    {
            period = DEFAULT_PERIOD;
        }
        else    {
            setFramePeriod(1000 / refreshRate);
        }
    }
    
    
    public void setFramePeriod(int newPeriod)    {
        if (newPeriod >= 0)    {
            period = newPeriod;
        }
    }
    
    public int getFramePeriod()    {
        return period;
    }
    
    public boolean isRunning()    {
        return running == true;
    }
    
    public void startGame()    {
        if (animator == null || !running)    {
            animator = new Thread(this);
            animator.start();
        }
    }
    
    public void stopGame()    {
        running = false;
    }
    
    public boolean isPaused()    {
        return paused == true;
    }
    
    public void setPaused(boolean pauseState)    {
        paused = pauseState;
    }
    
    public void run()    {
        try    {
            loopInit();
            gameLoop();
        } catch (Exception e)    {
            e.printStackTrace();
        } finally    {
            exitGame();
        }
    }
    
    public void loopInit()    {
        requestFocusInWindow();
        if (strategy == null)    {
            createBufferStrategy(NUM_BUFFERS);
            strategy = getBufferStrategy();
        }
        running = true;
    }
    
    public void gameLoop()    {
        long startTime = System.nanoTime();
        long currTime = startTime;
        long sleepTime = period;
        int numDelays = 0;
        while (running)    {
            long elapsedTime = System.nanoTime() - currTime;
            currTime += elapsedTime;
            Update(elapsedTime / 1000000L);
            render();
            long timeDiff = System.nanoTime() - currTime;
            sleepTime = period - timeDiff / 1000000L;
            if (sleepTime > 0)    {
                try    {
                    Thread.sleep(sleepTime);
                    numDelays = 0;
                } catch (InterruptedException ie)    {
                    ie.printStackTrace();
                    running = false;
                }
            }
            else if (++numDelays > MAX_DELAYS)    {
                Thread.yield();
                numDelays = 0;
            }
        }
    }
    
    
    private void render()    {
        Graphics g = null;
        try    {
            g = strategy.getDrawGraphics();
            draw(g);
        } catch (Exception e)    {
            e.printStackTrace();
        } finally    {
            g.dispose();
        }
        if (!strategy.contentsLost())    {
            strategy.show();
            Toolkit.getDefaultToolkit().sync();
        }    
        else    {
            System.out.println("contents lost");
        }
    }
    
    public void exitGame()    {
        try    {
            System.exit(0);
        } catch    (java.security.AccessControlException e)    {}
    }

    public void update(long elapsedTime)    {
    }
    
    public void draw(Graphics g)    {
    }
}

Subclass that and override the update and draw methods and you have yourself a central game manager or whatever you choose to call it.

A few things I did notice about your code are:
You are doing key handling the annoying way, no reason to change it now, but for future reference. You do not have to type out all the methods of KeyListener and not use them.

Create a an internal class similar to :

Code:
private class KeyHandler extends KeyAdapter    {
    
        public void keyPressed(KeyEvent e)    {}

and add :

Code:
addKeyListener(new KeyHandler());

too your constructor, no more overriding all the methods and using one of them Wink

You also have crammed WAY too much into one class. You shouldn't combine a rendering class and a data storage class AND a controller/manager class. There should be a serperate class called the MapRenderer or something like that.

If you sort out this code ( I would start over ) you want a main class that handles everything, a subclass of the GameCanavas I showed you. Inside this you want a map class a resource managing class that will load your map from a file. Then you want a rendering class that draws the contents of a map class.

I could not read enough of the code to get the jist of what is going on, is it just a guy walking around in an area?


To the thread starter: This code is double buffered though it is not the paint function. The problem with this code is you need to modify swing elements to draw them.


Hope this helps some.


Java: Double Buffering - paven - Jan 27, 2009 03:48 AM

Hi StealthyCoin
i wonder if i may use your gameCanvas under a
GPL3 code collection project i doing for educational purposes.
basicaly I put al code examples i class in an open source collection.
and your code looks clean and useful for my students.