Javaでアニメーションやゲームを作成したとき、画面がちらつくことがある。これは、背景を塗りつぶしてからキャラを描画するまでの間に、何もない画面が見えてしまうことで起こる。そこで、この背景を塗りつぶす作業も含めて一度に一枚の画像として描いてしまえばちらつきはなくなる。この方法を「ダブルバッファリング」といい、その画像をオフスクリーンバッファという。言葉では分かりにくいので図で説明しよう。部屋の中に亀の甲羅を書いてみる。1. ダブルバッファリングを使わずに描く
まずは背景を画面に描画する。2. ダブルバッファリングを使って描く
続いて亀の甲羅を描画する。
背景、キャラクターを描画する過程が見えてしまうのがイメージできるだろうか。これがちらつきの原因である。
オフスクリーンバッファに背景と亀の甲羅を描画する。
オフスクリーンバッファを画面に貼り付ける。
これにより、描画の過程を一切表に出さずに一枚の絵として描画できる。ダブルバッファリングは、特にキャラクターが移動やアニメーションを行う際に効果を発揮する。
では、プログラムではどうするか。
まず、描画画面いっぱいの大きさの画像(イメージ)を用意する。
新規に画像を作成する場合は、ComponentクラスのcreateImageメソッドを利用すればよい。AppletクラスやFrame等のGUIコンポーネントはCompnentクラスを継承しているのでこのメソッドが使える。例えば400x300の画像を作成するには次のようにする。Image imgBuf = createImage(400, 300);この画像をオフスクリーンバッファとして使う。また、バッファに描画するためのGraphicsオブジェクト(以下グラフィックコンテキスト)も取得する。これは、バッファのgetGraphicsメソッドを呼び出せば良い。Graphics gBuf = imgBuf.getGraphics();ここまで準備が整ったら、バッファのグラフィックコンテキストを使用してスレッドループ内で背景、キャラクターの描画を行う。背景が固定の場合は、背景も画像として作成し、スレッドループ内ではそれをペーストするだけの方が望ましい。そして、repaintメソッドを呼ぶことで実際の画面への描画を行う。gBuf.setColor(Color.white); gBuf.fillRect(0, 0, 400, 300); //バッファをクリア 〜背景の描画〜 〜キャラクターの描画〜 repaint();paintメソッドをオーバーライドして、バッファを画面に描画する。ここでは無駄な処理をせずにdrawImageメソッドを使って座標(0, 0)のところにバッファを描くだけである。
public void paint(Graphics g) { g.drawImage(imgBuf, 0, 0, this); }しかしこれで完成したと思ってはいけない。ここで実行しても画面はちらついてしまう。何故か?それは、repaintメソッドが呼びされると、updateメソッドが呼ばれ、画面を一旦背景色で塗りつぶすという作業が行われるからである。したがって、updateメソッドをオーバーライドし、そのままpaintメソッドにつなぐ。
public void update(Graphics g) { paint(g); }ダブルバッファリングを使わない場合と使った場合のサンプルを用意した。ちらつきの減少を実際にサンプルアプレットで体験してほしい。
【実行結果】 ダブルバッファリングテストアプレット 【ソース】 ダブルバッファリングを使用しない(NoBuffer)
ダブルバッファリングを使用(BufferTest)