BufferStrategy works with only 1 buffer...not 2

Hi again!

I’d like to thank trembovetski for helping me with my last post. I finally got it working.

But when I try to draw in my canvas, nothing works (this is with 2 buffers). However, when I use 1 buffer it seems to work…Heres the code:


//initialize the graphics when i create the canvas
public void initializeGraphics()
   {

      this.createBufferStrategy(this.numBuffers);
      this.bufferStrategy = this.getBufferStrategy();
   }


//draw the graphics on the canvas...called from a render loop
private void drawGraphics()
   {  
      try
      {  Graphics2D g2 =  (Graphics2D) this.bufferStrategy.getDrawGraphics();
         this.render(g2);
         this.bufferStrategy.show();
         g2.dispose();
      }  catch (Exception e)
      {  System.out.println("ERROR DRAWING GRAPHICS: " + e.toString());
      } 

   }

the render(g2) method simply uses g2 to draw some rectangles.

Now, when I initialize the graphics and call

this.createBufferStrategy(this.numBuffers)

and

this.numBuffers = 2

, nothing works (ie. the canvas is visible b/c I can see the background I set the canvas to display), but the canvas doesn’t draw anything. However, when I set

this.numBuffers = 1

, then the canvas draws everything I want it too (albiet it flickers ALOT). I’m assuming it flickers b/c there is only 1 buffer, and I’m drawing over the buffer everytime I call the render(g2) method.

Does anyone know how I would get 2 buffers to work?

Thanks for all your help!

Sincerely,
Jarrett
aka. Chisser98

I’d help if you post the whole app’s code, because it’s hard to follow the logic from the pieces.

For example, form your post it looks like you first create the strategy, and only then set the numBuffers to 2…

heh sry, I can see how that would be a bit confusing. Heres the full code:
This is the FRAME I use -->


package View;
import Model.World;


import java.awt.Canvas;
import java.awt.Color;
import java.awt.GraphicsEnvironment;
import java.awt.GraphicsDevice;
import java.awt.DisplayMode;
import java.awt.Frame;
import javax.swing.JFrame;
/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: </p>
 * @author not attributable
 * @version 1.0
 */

public class GameFrame extends Frame
{  private GameCanvas gameCanvas;
   private MainMenuCanvas mainMenuCanvas;
   private MenuCanvas menuCanvas;

   private World model;

   private GraphicsEnvironment ge;
   private GraphicsDevice gd;

   private int lengthX = 800;
   private int lengthY = 600;

   private DisplayMode originalDisplayMode;

   private boolean fullScreen;

   public GameFrame(World theModel)
   {  this.model = theModel;
      this.model.addView(this);

      this.ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
      this.gd = this.ge.getDefaultScreenDevice();

      this.fullScreen = this.gd.isFullScreenSupported();
      this.setUndecorated(this.fullScreen);
      this.setResizable(!this.fullScreen);
      this.setIgnoreRepaint(this.fullScreen);
      this.initializeFullScreen();

      this.gameCanvas = new GameCanvas(this.lengthX, this.lengthY);
      this.add(this.gameCanvas);
      this.gameCanvas.setVisible(true);

   }

   private void initializeFullScreen()
   {  if (this.fullScreen)
      {  this.originalDisplayMode = this.gd.getDisplayMode();

         try
         {  this.gd.setFullScreenWindow(this);
            DisplayMode newMode = new DisplayMode(this.lengthX, this.lengthY, 24, 60);
            this.gd.setDisplayMode(newMode);
         }  catch (Exception e)
         {  if (this.gd.isDisplayChangeSupported())
            {  if (!this.originalDisplayMode.equals(this.gd.getDisplayMode()))
               {  this.gd.setDisplayMode(this.originalDisplayMode);
               }

               this.gd.setFullScreenWindow(null);
            }
         }
      }

      this.setBackground(Color.black);
      this.pack();
      //this.setVisible(true);
   }

   public void updateView()
   {  this.gameCanvas.updateView();
   }
}


And this is the CANVAS I use -->


package View;
import Model.World;


import java.awt.Canvas;
import java.awt.BufferCapabilities;
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics2D;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: </p>
 * @author not attributable
 * @version 1.0
 */

public class GameCanvas extends Canvas
{  private BufferStrategy bufferStrategy;
   private int numBuffers = 2;

   private int lengthX;
   private int lengthY;


   public GameCanvas(int lengthX, int lengthY)
   {  super();
      this.lengthX = lengthX;
      this.lengthY = lengthY;

      this.setSize(this.lengthX, this.lengthY);

      this.registerListeners();

      this.setIgnoreRepaint(true);
      this.setBackground(Color.white);
   }

   public void registerListeners()
   {
   }

   /* Ready the buffers for drawing onto the canvas - Should only be needed to be
      called from within the canvas itself
   */
   public void initializeGraphics()
   {

      this.createBufferStrategy(this.numBuffers);
      this.bufferStrategy = this.getBufferStrategy();
   }

   /* Set the canvas visible/invisible, but also initialize the canvas BufferStrategy if
      the canvas is to be shown in the GameFrame
   */
   public void setVisible(boolean state)
   {  if (state)
      {  this.initializeGraphics();
      }
      super.setVisible(state);
   }

   /* This method will 'try' to get the BufferStrategys' graphics, draw on the canvas,
      and then display the canvas (using Page Flipping)
   */
   private void drawGraphics()
   {
      try
      {  Graphics2D g2 =  (Graphics2D) this.bufferStrategy.getDrawGraphics();
         this.render(g2);
         this.bufferStrategy.show();
         g2.dispose();
      }  catch (Exception e)
      {  System.out.println("ERROR DRAWING GRAPHICS: " + e.toString());
      }

   }

   /* This will draw (render) the graphics onto the graphics buffer supplied from
      BufferStrategy
   */
   private void render(Graphics2D g2)
   {  if (!this.bufferStrategy.contentsLost())
      {  System.out.println("Rendering graphics");
         g2.setColor(Color.green);
         g2.fillRect(0, 0, this.lengthX, this.lengthY);
         g2.setColor(Color.white);
         g2.drawString("Testing 1, 2, 3.  GameCanvas TEST.", 10, 10);
         g2.setColor(Color.magenta);
         g2.fillRect(40, 100, 80, 250);
      } else
      {  System.out.println("Contents of the buffer have been lost...Cannot render Canvas.");
      }
   }

   public void updateView()
   {  this.drawGraphics();
   }


}

Thx for any help you could offer. This is really driving me insane!

Thx again,
Jarrett
aka. Chisser98

Works fine after I made the following changes to the GameFrame code, and removing setVisible method from GameCanvas:


      this.gameCanvas = new GameCanvas(this.lengthX, this.lengthY);
      this.add(this.gameCanvas);
      this.initializeFullScreen();
      gameCanvas.initializeGraphics();
      new Thread(new Runnable() {
            public void run() {
                while (true) {
                  updateView();
                  try { Thread.sleep(300); } catch (Exception e) {}
                } // end of while ()
                
            }
          }).start();


(The threading stuff is just for testing)
So the order should be:

  • create canvas
  • add to frame
  • enter fs mode / change display mode
  • create buffer strategy

Thx for the help (again) :slight_smile:

I made the changes you suggested but to no avail. I think java hates me! I’m still having the same problem…I’m not seeing anything I draw onto the buffer when I have 2 buffers…but it seems to work when I only have 1 buffer (albiet it flickers). Its insane!

I did a system.out.println() when I created my bufferstrategy and it printed as “java.awt.Component$FlipBufferStrategy@17a29a1”, which I think is correct (I’m trying to do the flip buffer strategy). I think I’m gonna try to just draw onto the Frame…I’ve heard ppl who have problems with canvas do that and it works.

Thx again for your help trebovetski!

Jarrett
aka. Chisser98

OK, just to make sure you’re not running into some hw issue.
Here’s your code modified to run standalone.

Save the files and compile them separate from your project.
To run:
java GameFrame

GameFrame.java :


import java.awt.Canvas;
import java.awt.Color;
import java.awt.GraphicsEnvironment;
import java.awt.GraphicsDevice;
import java.awt.DisplayMode;
import java.awt.Frame;
import javax.swing.JFrame;
/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: </p>
 * @author not attributable
 * @version 1.0
 */
 
public class GameFrame extends Frame
{  private GameCanvas gameCanvas;
    private GraphicsEnvironment ge;
    private GraphicsDevice gd;
 
    private int lengthX = 800;
    private int lengthY = 600;
 
    private DisplayMode originalDisplayMode;
 
    private boolean fullScreen;
 
    public GameFrame() {
 
      this.ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
      this.gd = this.ge.getDefaultScreenDevice();
 
      this.fullScreen = this.gd.isFullScreenSupported();
      this.setUndecorated(this.fullScreen);
      this.setResizable(!this.fullScreen);
      this.setIgnoreRepaint(this.fullScreen);
 
      this.gameCanvas = new GameCanvas(this.lengthX, this.lengthY);
      this.add(this.gameCanvas);
      this.initializeFullScreen();
      gameCanvas.initializeGraphics();
      new Thread(new Runnable() {
            public void run() {
                while (true) {
                  updateView();
                  try { Thread.sleep(300); } catch (Exception e) {}
                } // end of while ()
                
            }
          }).start();
    
    }
 
    private void initializeFullScreen()
    {  if (this.fullScreen)
      {  this.originalDisplayMode = this.gd.getDisplayMode();
 
      try
          {  this.gd.setFullScreenWindow(this);
          DisplayMode newMode = new DisplayMode(this.lengthX, this.lengthY, 24, 60);
          this.gd.setDisplayMode(newMode);
          }  catch (Exception e)
            {  if (this.gd.isDisplayChangeSupported())
                {  if (!this.originalDisplayMode.equals(this.gd.getDisplayMode()))
                  {  this.gd.setDisplayMode(this.originalDisplayMode);
                  }
 
                this.gd.setFullScreenWindow(null);
                }
            }
      }
 
    this.setBackground(Color.black);
    this.pack();
    //this.setVisible(true);
    }
 
    public void updateView()
    {  this.gameCanvas.updateView();
    }

    public static void main (String[] args) {
      new GameFrame();
    } // end of main ()
    
} 

GameCanvas.java :


import java.awt.Canvas;
import java.awt.BufferCapabilities;
import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics2D;
 
/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: </p>
 * @author not attributable
 * @version 1.0
 */
 
public class GameCanvas extends Canvas
{  private BufferStrategy bufferStrategy;
    private int numBuffers = 2;
 
    private int lengthX;
    private int lengthY;
 
 
    public GameCanvas(int lengthX, int lengthY)
    {  super();
    this.lengthX = lengthX;
    this.lengthY = lengthY;
 
    this.setSize(this.lengthX, this.lengthY);
 
    this.registerListeners();
 
    this.setIgnoreRepaint(true);
    this.setBackground(Color.white);
    }
 
    public void registerListeners()
    {
    }
 
    /* Ready the buffers for drawing onto the canvas - Should only be needed to be
       called from within the canvas itself
    */
    public void initializeGraphics()
    {
 
      this.createBufferStrategy(this.numBuffers);
      this.bufferStrategy = this.getBufferStrategy();
    }
 
    /* Set the canvas visible/invisible, but also initialize the canvas BufferStrategy if
       the canvas is to be shown in the GameFrame
    */
    public void setVisible1(boolean state)
    {  if (state)
      {  this.initializeGraphics();
      }
    super.setVisible(state);
    }
 
    /* This method will 'try' to get the BufferStrategys' graphics, draw on the canvas,
       and then display the canvas (using Page Flipping)
    */
    private void drawGraphics()
    {
      try
          {  Graphics2D g2 =  (Graphics2D) this.bufferStrategy.getDrawGraphics();
          this.render(g2);
          this.bufferStrategy.show();
          g2.dispose();
          }  catch (Exception e)
            {  System.out.println("ERROR DRAWING GRAPHICS: " + e.toString());
            e.printStackTrace();
            }
 
    }
 
    /* This will draw (render) the graphics onto the graphics buffer supplied from
       BufferStrategy
    */
    static int frameNum = 0;
    private void render(Graphics2D g2)
    {  if (!this.bufferStrategy.contentsLost())
      {  System.out.println("Rendering graphics");
      g2.setColor(Color.green);
      g2.fillRect(0, 0, this.lengthX, this.lengthY);
      g2.setColor(Color.white);
      g2.drawString("Testing 1, 2, 3.  GameCanvas TEST Frame: "+frameNum++, 10, 10);
      g2.setColor(Color.magenta);
      g2.fillRect(40, 100, 80, 250);
      } else
          {  System.out.println("Contents of the buffer have been lost...Cannot render Canvas.");
          }
    }
 
    public void updateView()
    {  this.drawGraphics();
    }
 
 
}