This discussion is archived
1 2 Previous Next 15 Replies Latest reply: Aug 10, 2012 9:02 AM by Patcha RSS

Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer

Patcha Newbie
Currently Being Moderated
Hai all!
As suggested to me by gimbal2 over here: Re: AWT - How to delete (make transparent) a part of an Image
I was trying to implement Canvas and BufferStrategy in my project.

My old selfmade buffer method was the following (note: the explanation is shortened):
- I use to extend a Frame
- I create a BufferedImage with this
Image buffer = this.getGraphicsConfiguration().createCompatibleImage(buff_xo, buff_yo);
- I made a class to manage buffer (BufferManager)
BufferManager buffMan = new BufferManager(buffer);
- Then I start a scheduled thread with a class which extends TimerTask, which is Runnable (CoreThread)
ScheduledExecutorService core = Executors.newScheduledThreadPool(1);
core.scheduleAtFixedRate(new CoreThread(buffMan), 5, 16, TimeUnit.MILLISECONDS);
- The I overriden directly Frame's update() and paint(g) methods to write "buffer" image on frame's graphic
@Override
public void paint(Graphics graph) {
     // Drawing everything from the buffer, and removing flicker effect
     graph.drawImage(buffer, buff_x, buff_y, null);
}

@Override
public void update(Graphics graph) {
     paint(graph);
}
- a the end of my Thread, when I need to update my screen, I call Frame's paint(g) method.

And this is pratically how my buffering works... as you see, I miss a Canvas and a BufferStrategy.

Looking at this tutorial http://www.javalobby.org/forums/thread.jspa?threadID=16867
I see he uses to implement the Canvas (easy, I can do that), and then get the BufferStrategy from it.
After doing that, he gets the graphic from the BufferStrategy and uses it in the Threat do make paints on it.
Then he disposes the graphic and uses the BufferStrategy's method show() to paint the buffer and update screen image.

My problem on implementing BufferStrategy, is that I use often the "buffer" Image all over my code (expecially when I need to make calculations with it's size), and not simply his graphic.
So to implement the use of BufferStrategy, should I send all over the BufferStrategy where now I send the Image buffer?
And then should be enough to call BufferStrategy's show() method instead of patint(g) at the end fo my Thread, when needed to update screen?

Thank you all!
  • 1. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    gimbal2 Guru
    Currently Being Moderated
    Typically when I use a BufferStrategy I don't pass the BufferStrategy itself but the Graphics2D object I create through it to draw a 'frame'.
  • 2. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    Patcha Newbie
    Currently Being Moderated
    But my problem is Graphic2D object doesn't contains data about current size of drawed area... does it?
    I do lot of calculations here and there about size or buffer's borders collisions.
  • 3. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    gimbal2 Guru
    Currently Being Moderated
    Patcha wrote:
    But my problem is Graphic2D object doesn't contains data about current size of drawed area... does it?
    I do lot of calculations here and there about size or buffer's borders collisions.
    No, but the BufferStrategy also doesn't deal with such things; the canvas has dimensions.

    I'm quite lazy in that respect and I tend to have a singleton class in there which application components can invoke to figure out basic details such as dimensions. That singleton class then has access to such things as the frame and the canvas, the rest of the code doesn't have to know they exist. All drawing is then done to the basic Graphics interface, which might be the BufferStrategy backbuffer or for example that of a scratch image if I want to do some composition before I blast the end-result to the screen.

    Some people will condemn me for using a Singleton, but I don't care much about that really ;)
  • 4. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    Patcha Newbie
    Currently Being Moderated
    Uhm... I could build in my main class some methods to return each time Graphics, Dimensions or any other Frame / Canvas / BufferStrategy related stuffs, and... then pass "this" to my custom BufferManager class, which itself would replicate same methods... and then pass it (BufferManager) here and there where now I use to pass Image buffer.

    What do you think about it?

    The alternative is to make private Frame, Canvas and BufferStrategy available via static methods...
  • 5. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    gimbal2 Guru
    Currently Being Moderated
    Its too vague a description for me, but my opinion on such questions is "Does it work? Can you read it? Do you think in 6 months time you can still understand it? Then be at peace!"
  • 6. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    Patcha Newbie
    Currently Being Moderated
    Ok, ok... I'll check for the best way to share Frame / Canvas / BufferStrategy stuffs & infos without sharing themselves...

    I think I got the point, anyway. :)
  • 7. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    gimbal2 Guru
    Currently Being Moderated
    Excellent attitude. Having the information spoon-fed to you really does not teach you anything. Go experiment and share what you can come up with for some feedback.
  • 8. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    Patcha Newbie
    Currently Being Moderated
    I'm trying to get a result on using Canvas and BufferStrategy with a "single draw" simple system first, before going for massive implementation in the thread...

    What I did is to add canvas in the Frame extender class' constructor, and then to draw something in the canvas in the main method... but seems not working for now... am I mistaking something?

    PS: this is just an extract of the code...
    public class Piove extends Frame implements KeyListener, MouseListener, MouseMotionListener, FocusListener {
         protected static Canvas canvas;
    
         protected int width_size = 800;
         protected int height_size = 600;
    
         public Piove() {
              super("Piove");
              setBackground(Color.BLACK);
              addWindowListener(new BasicWindowMonitor());
              addKeyListener(this);
              addMouseListener(this);
              addMouseMotionListener(this);
              addFocusListener(this);
    
              pack();
              canvas = new Canvas();
              add(canvas);
              setSize(width_size, height_size);
              canvas.createBufferStrategy(2);
    
              Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
              setLocation((screenSize.width / 2) - (getWidth() / 2),
                        (screenSize.height / 2) - (getHeight() / 2));
         }
    
         public static void main(String args[]) {
              // Define game window
              Frame frame = new Piove();
              frame.setResizable(false);
              frame.setVisible(true);
    
              BufferStrategy strategy = canvas.getBufferStrategy();
              Dimension c_dim = canvas.getBounds().getSize();
              System.out.println(c_dim.getHeight() + ", " + c_dim.getWidth());
              Graphics2D graphic = (Graphics2D) strategy.getDrawGraphics();
              graphic.setColor(Color.WHITE);
              graphic.drawLine(0, 0, (int) c_dim.getHeight(), (int) c_dim.getWidth());
              System.out.println(c_dim.getHeight() + ", " + c_dim.getWidth());
              graphic.dispose();
              strategy.show();
         }
    
         [...]
    }
    This should draw an obligue line which runs from 0, 0 to canvas opposite vertex... but I see only blank screen... what am I missing?
  • 9. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    gimbal2 Guru
    Currently Being Moderated
    The call to pack() BEFORE you add the canvas seems a bit odd to me. Also I'd expect you to give the canvas a size, not the frame directly. The pack() call will then adjust the frame to the size of the canvas.
  • 10. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    Patcha Newbie
    Currently Being Moderated
    Now the canvas section of the constructor is like this:
    canvas = new Canvas();
    canvas.setBounds(new Rectangle(new Dimension(buff_xo, buff_yo)));
    add(canvas);
    pack();
    canvas.createBufferStrategy(2);
    But still black screen.

    As it was before, canvas automatically got dimensions from window, too... so I think it works the same...
    But still black screen to me...


    The tutorial I linked before uses JFrame... so makes no pack...
  • 11. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    Patcha Newbie
    Currently Being Moderated
    To be totally sure nothing else was overriding my drawing, I made a totally new project dedicated to this test... it says nothing particularly new, and it still doesn't work... :(
    package test;
    
    import java.awt.*;
    import java.awt.image.BufferStrategy;
    
    public class Test extends Frame {
         protected static Canvas canvas;
     
         protected int width_size = 800;
         protected int height_size = 600;
    
         public Test() {
              super("Test");
              setBackground(Color.BLACK);
               addWindowListener(new BasicWindowMonitor());
    
              canvas = new Canvas();
              canvas.setBounds(new Rectangle(new Dimension(height_size, width_size)));
              add(canvas);
              pack();
              canvas.createBufferStrategy(2);
     
              Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
              setLocation((screenSize.width / 2) - (getWidth() / 2),
                        (screenSize.height / 2) - (getHeight() / 2));
         }
    
         public static void main(String[] args) {
              // Define game window
              Frame frame = new Test();
              frame.setResizable(false);
              frame.setVisible(true);
     
              BufferStrategy strategy = canvas.getBufferStrategy();
              Dimension c_dim = canvas.getBounds().getSize();
              System.out.println(c_dim.getHeight() + ", " + c_dim.getWidth());
              Graphics2D graphic = (Graphics2D) strategy.getDrawGraphics();
              graphic.setColor(Color.WHITE);
              graphic.drawLine(0, 0, (int) c_dim.getHeight(), (int) c_dim.getWidth());
              System.out.println(c_dim.getHeight() + ", " + c_dim.getWidth());
              graphic.dispose();
              strategy.show();
         }
    }
    The BasicWindowMonitor class is the following:
    package test;
    
    import java.awt.Window;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    
    public class BasicWindowMonitor extends WindowAdapter {
    
         @Override
         public void windowClosing(WindowEvent e) {
              Window w = e.getWindow();
              w.setVisible(false);
              w.dispose();
              System.exit(0);
         }
    }
    This is not an extract... this is the whole code for the test project!
  • 12. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    gimbal2 Guru
    Currently Being Moderated
    Hmm when I add
    Toolkit.getDefaultToolkit().sync();
    after the BufferStrategy.show() call it works, but I'm pretty sure that I never had to call that method myself. I'll have to check against code I have at home what I'm doing differently. Well, I render frames in a game loop 50 times a second, that's one thing I'm doing differently.


    Here is the modified code I used, I changed a few things around a bit to make the code more oriented on the canvas and less on the frame:
    import java.awt.Window;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.awt.*;
    import java.awt.image.BufferStrategy;
    import java.awt.geom.Line2D;
    
    public class Test extends Frame {
         protected static Canvas canvas;
     
         protected int width_size = 800;
         protected int height_size = 600;
     
         public Test() {
              super("Test");
               addWindowListener(new BasicWindowMonitor());
    
     
              canvas = new Canvas();
              canvas.setBounds(new Rectangle(new Dimension(height_size, width_size)));
              canvas.setBackground(Color.BLACK);
              add(canvas);
              pack();
              setResizable(false);
              
              canvas.createBufferStrategy(2);
     
              Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
              setLocation((screenSize.width / 2) - (getWidth() / 2),
                        (screenSize.height / 2) - (getHeight() / 2));
    
              setVisible(true);
         }
     
         public static void main(String[] args) {
              // Define game window
              Frame frame = new Test();
     
              BufferStrategy strategy = canvas.getBufferStrategy();
              Dimension c_dim = canvas.getBounds().getSize();
              System.out.println(c_dim.getHeight() + ", " + c_dim.getWidth());
              Graphics2D graphic = (Graphics2D) strategy.getDrawGraphics();
              graphic.setColor(Color.WHITE);
                    graphic.draw(new Line2D.Double(1, 1, 200, 200));
              System.out.println(c_dim.getHeight() + ", " + c_dim.getWidth());
              strategy.show();
              graphic.dispose();
              Toolkit.getDefaultToolkit().sync();
         }
         
      public class BasicWindowMonitor extends WindowAdapter {
       
           @Override
           public void windowClosing(WindowEvent e) {
                Window w = e.getWindow();
                w.setVisible(false);
                w.dispose();
                System.exit(0);
           }
      }
    
    }
  • 13. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    Patcha Newbie
    Currently Being Moderated
    Yes, I think it's a matter of screen synch, 'cause if you do it in debug mode, putting a block on the show() method call... then you do it manually with F8 (which means it has time before the application ends up) it works... so I think this test it's just a matter of synchronization...

    With a thread it shouldn't be a problem (I hope), 'cause it keeps continue after show() call... doesn't ends up soon after, like this application.
    I just suppose...

    Anyway... I inverted width with height somewhere! :D


    EDIT: I copy / pasted your version (and corrected width and height :D)... but still same reaction... if I run it is blank... but if I debug and do a "step" on show(), it works...

    Edited by: Patcha on 10-ago-2012 17.42
  • 14. Re: Pls helpme implement Canvas and BufferStrategy on my old "self made" buffer
    Patcha Newbie
    Currently Being Moderated
    Infact... seems BufferStrategy is just for threads... or so...

    This actually works:
    package test;
    
    import java.awt.*;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.awt.geom.Line2D;
    import java.awt.image.BufferStrategy;
    import java.util.TimerTask;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class Test extends Frame {
         protected static Canvas canvas;
    
         protected int width_size = 800;
         protected int height_size = 600;
    
         public Test() {
              super("Test");
              addWindowListener(new BasicWindowMonitor());
    
              canvas = new Canvas();
              canvas.setBounds(new Rectangle(new Dimension(width_size, height_size)));
              canvas.setBackground(Color.BLACK);
              add(canvas);
              pack();
              setResizable(false);
    
              canvas.createBufferStrategy(2);
    
              Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
              setLocation((screenSize.width / 2) - (getWidth() / 2),
                        (screenSize.height / 2) - (getHeight() / 2));
    
              setVisible(true);
         }
    
         public static void main(String[] args) {
              // Define game window
              Frame frame = new Test();
    
              //System.out.println(frame.getHeight() + ", " + frame.getWidth());
              //System.out.println(canvas.getBounds().getSize().getHeight() + ", " + canvas.getBounds().getSize().getWidth());
    
              // Starting thread
              ScheduledExecutorService core = Executors.newScheduledThreadPool(1);
              core.scheduleAtFixedRate(new CoreThread(canvas), 5, 16, TimeUnit.MILLISECONDS);
         }
    
    
         public class BasicWindowMonitor extends WindowAdapter {
              @Override
              public void windowClosing(WindowEvent e) {
                   Window w = e.getWindow();
                   w.setVisible(false);
                   w.dispose();
                   System.exit(0);
              }
         }
    
    
         public static class CoreThread extends TimerTask {
              private Canvas canvas;
              public CoreThread(Canvas canvas) {
                   this.canvas = canvas;
              }
    
              @Override
              public void run() {
                   BufferStrategy strategy = canvas.getBufferStrategy();
                   Dimension c_dim = canvas.getBounds().getSize();
                   Graphics2D graphic = (Graphics2D) strategy.getDrawGraphics();
                   graphic.setColor(Color.WHITE);
                   graphic.draw(new Line2D.Double(1, 1, c_dim.getWidth(), c_dim.getHeight()));
                   strategy.show();
                   graphic.dispose();
              }
         }
    }
    And this test also confirms why better to put a canvas before drawing... canvas infact jumps my borders problem... the only thing... I don't undestand why it seems to add 10 more pixels per side to the size you tried to set...
1 2 Previous Next

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points