理解BufferStrategy

13

我对Java比较陌生。我想做一个游戏。经过了很多的研究,我还是不太明白什么是缓冲策略。

我知道一些基础知识,就是它能创建一个离屏图像,你可以把它放到你的窗口对象中,这一点我已经理解了。

public class Marco extends JFrame {
    private static final long serialVersionUID = 1L;
    BufferStrategy bs; //create an strategy for multi-buffering.

    public Marco() {
       basicFunctions(); //just the clasics setSize,setVisible,etc
       createBufferStrategy(2);//jframe extends windows so i can call this method 
       bs = this.getBufferStrategy();//returns the buffer strategy used by this component
    }

   @Override
   public void paint(Graphics g){
      g.drawString("My game",20,40);//some string that I don't know why it does not show
      //guess is 'couse g2 overwrittes all the frame..
      Graphics2D g2=null;//create a child object of Graphics
      try{
         g2 = (Graphics2D) bs.getDrawGraphics();//this new object g2,will get the
         //buffer of this jframe?
         drawWhatEver(g2);//whatever I draw in this method will show in jframe,
         //but why??
      }finally{
         g2.dispose();//clean memory,but how? it cleans the buffer after
         //being copied to the jframe?? when did I copy to the jframe??
      }
      bs.show();//I never put anything on bs, so, why do I need to show its content??
      //I think it's a reference to g2, but when did I do this reference??
   }

   private void drawWhatEver(Graphics2D g2){
       g2.fillRect(20, 50, 20, 20);//now.. this I can show..
   }
  }

我不知道...我一直在研究这个问题很长时间了..但是毫无进展..也许答案就在那里,很明显很简单,只是我太蠢了看不到..

感谢所有的帮助.. :)

1个回答

28

这是它的工作原理:

  1. 当你调用createBufferStrategy(2);时,JFrame会构造一个BufferStrategyBufferStrategy知道它属于那个特定的JFrame实例。您正在检索并将其存储在bs字段中。
  2. 当您需要绘制内容时,您需要从bs中检索一个Graphics2D对象。此Graphics2D对象与bs拥有的内部缓冲区之一相关联。在绘制时,所有内容都将进入该缓冲区。
  3. 最后调用bs.show()时,bs将使您刚刚绘制的缓冲区成为JFrame的当前缓冲区。它知道如何做到这一点,因为(请参见第1点)它知道它是为哪个JFrame提供服务的。

就是这样。

关于您的代码,您应该稍微改变一下绘图例程。不要使用以下方式:

try{
    g2 = (Graphics2D) bs.getDrawGraphics();
    drawWhatEver(g2);
} finally {
       g2.dispose();
}
bs.show();

你应该有一个类似这样的循环:

do {
    try{
        g2 = (Graphics2D) bs.getDrawGraphics();
        drawWhatEver(g2);
    } finally {
           g2.dispose();
    }
    bs.show();
} while (bs.contentsLost());

这样可以保护不丢失缓冲区帧,根据文档,这种情况偶尔会发生。


为什么我们需要在显示缓冲区之前进行dispose()处理?我认为图形对象只是用于具有图形功能,但当它不再需要时,我们会“释放其工具和资源”,然后显示我们的缓冲图像? - homerun
2
@someFolk - 不一定非得按照那个顺序来做;调用 bs.show() 的语句可以移动到 try 块内部。但是没有特别的理由这样做,及时释放系统资源是一个好习惯。 - Ted Hopp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接