チラツキをなくせ! -- その2 --

クリッピング

------------------------------------

ごめんなさい。
Java対応ブラウザではここにアプレットが表示されます。



Source(MovingBall.java)
------------------------------------

単純にupdate()を上書きするだけでは上手くいかないので、他の方法を考えます。

何の工夫もしないアプレットではrepaint()を呼ぶとアプレット全体を再描画します。ここでアプレット全体でなく、必要な部分だけを再描画するようにすれば、全体の処理時間が短くなり、結果的にチラツキが減って見えるはずです。

このように描画を領域の一部に絞ることを「クリッピング」というそうです。私はJava言語入門で知りました。

------------------------------------

ボールが移動したときにしたいことは

なので、再描画が必要なのは「前にボールがあった位置」と「新しいボールの位置」です。この二つを別々に指定するのは面倒なので、この二つを含む最少の長方形をクリップします。

repaint()を呼ぶと直ちにpaint()が呼ばれていればこれで良いのですが、諸般の事情により次のrepaint()までpaint()の呼び出しがスキップされる場合があります。

そのため実際には「前にボールがあった位置」ではなく「最後に描画したときにボールがあった位置」と「新しいボールの位置」を含む長方形をクリップします。

------------------------------------

まずインスタンス変数

int lastPaintedX, lastPaintedY;

を導入し「最後に描画したときにボールがあった位置」を記憶させます。

update()を上書きして、その中で

int minX = x < lastPaintedX ? x : lastPaintedX;
int maxX = x > lastPaintedX ? x : lastPaintedX;
int minY = y < lastPaintedY ? y : lastPaintedY;
int maxY = y > lastPaintedY ? y : lastPaintedY;
g.clipRect(minX, minY, maxX - minX + r, maxY - minY + r);

必要な領域をクリップしています。最初の4行で描画が必要な長方形の座標を求め、最後の一行

g.clipRect(minX, minY, maxX - minX + r, maxY - minY + r);

でクリッピングをしています。

update()を上書きしているので、デフォルトのupdate()でなされる処理

g.setColor(getBackground());
g.fillRect(0, 0, width, height);

もこの中で行ないます。しかし、クリッピングを行なったあとなので、実際に描画が行なわれるのはクリップした長方形の内部だけです。

------------------------------------

最後にpaint()の中で

lastPaintedX = x;
lastPaintedY = y;

として「最後に描画したときにボールがあった位置」を記憶させています。

------------------------------------

前の項目へ次の項目へ

「リメイキング・オブ・MovingBall」のページへ