Java: Double Buffering

xDexx
Unregistered
 
Post: #1
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);
    }

}
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #2
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
Quote this message in a reply
xDexx
Unregistered
 
Post: #3
here is the information on createImage http://java.sun.com/j2se/1.4.2/docs/api/...olkit.html
thanks for looking in to this!
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #4
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/...nt,%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
Quote this message in a reply
davecom
Unregistered
 
Post: #5
Looks like bufferWidth is undefined when paint() is called. Didn't look hard though maybe I missed something.
Quote this message in a reply
Member
Posts: 370
Joined: 2002.04
Post: #6
What would really help is: what line of code is number 57?

Did you ever wonder why we had to run for shelter when the promise of a brave new world unfurled beneath the clear blue sky?
Quote this message in a reply
deadrat
Unregistered
 
Post: #7
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);
        
}
}
Quote this message in a reply
deadrat
Unregistered
 
Post: #8
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);
        
}
}
Quote this message in a reply
deadrat
Unregistered
 
Post: #9
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);
    
}
}
Quote this message in a reply
Nibbie
Posts: 3
Joined: 2008.04
Post: #10
It's early in the morning but I don't understand what's the problem?
Quote this message in a reply
Member
Posts: 67
Joined: 2006.06
Post: #11
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.

The machine does not run without the coin.
Quote this message in a reply
Nibbie
Posts: 1
Joined: 2009.01
Post: #12
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.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Char* to double, int, and back wyrmmage 18 6,708 Jun 24, 2007 11:09 AM
Last Post: akb825
  PyGame: Double-clickable game? aarku 6 6,092 Jul 30, 2003 04:44 AM
Last Post: aarku