アニメーションを作成しようとするときに RepaintManager がどのように機能するかを正しく理解するのに役立つことを願っています。基本的に、生き物/画像をJFrameに描画して更新するプログラムを作成しています。各クリーチャー オブジェクトには、x、y 座標や BufferedImage など、ペイントで描画できるすべての情報が含まれています。現在、クリーチャー オブジェクトが移動するたびに、repaint() が呼び出されます。これは、以下の paint/paintComponent (どちらが最適かはわかりません) メソッドでわかるように、既存のすべてのクリーチャーをループして、画面上の位置とグラフィックを更新します。 .
私の質問は、 RepaintManager が画面上のすべてを再描画していることを懸念しているため、これがこれを行うための最良の方法です。これはあまり効率的ではありません。更新メソッドのクリッピングまたはオーバーライドに関するいくつかの投稿/記事を読んだことがありますが、それらについて理解することはできません-再描画が呼び出されるたびに、変更されたオブジェクト/クリーチャーのみを更新することは可能ですか?
私が話していることのいくつかのコード:
public void paintComponent (Graphics g) {
super.paintComponent(g);
//setDoubleBuffered(true); //Probably not needed?
Graphics2D g2d = (Graphics2D) g;
//Draws the land area for penguins.
g2d.setColor(new Color(121,133,60));
g2d.fill3DRect(land.x, land.y, land.width, land.height, true);
//OR g2d.fill(land);
g2d.setColor(Color.BLUE);
g2d.fill(sea);
drawCreatures(g2d);
}
paint メソッドのすべてのグラフィックスは変更されず、再描画する必要はありませんが、以下のメソッドは...
private void drawCreatures(Graphics2D g2d) {
try {
for (Creature c : crlist) {
g2d.drawImage(c.createImage(txs,tys), c.getPos(1).width, c.getPos(1).height, this);
//g2d.drawImage(cImg,c.getPos(1).width,c.getPos(1).height,this);
if (c instanceof Fish && c.getMating().equals(Mating.WBABY)) {
int xos=0;
for (Creature fb : c.getChildren()) {
if (fb.getMating().equals(Mating.BABY)) g2d.drawImage(fb.createImage(txs,tys),c.getPos(1).width+xos,c.getPos(1).height+50,txs/2,tys/2,this);
xos+=25;
}
}
if (c.getInfo()==true) displayInfo(g2d,c); //This changes when a creature is clicked on.
else if (c.getState()!=State.NORMAL || c.getMating().equals(Mating.LOVE)) drawState(g2d,c); //updated through a creature's move/search methods.
}
}
catch(ConcurrentModificationException cme) { System.out.println("CME ERROR!"); }
}
重要な部分は、強化された for ループの最初の行です。これは、JFrame ウィンドウに画像を描画するためです。createImage メソッドは単純に生き物の画像を取得し、変換/変更します。たとえば、ペイントが使用する前に左に移動すると反転します。
アニメーションは現在、スレッドを実行している各クリーチャーによって処理されますが、クリーチャーが新しいクリーチャーを crlist に追加しようとすると現在 ConcurrentModificationException が発生しているため、Swing Timer の方が良いかどうかも疑問です。
private class Creature implements Behaviours<Creature>, Runnable {
//...variables
//...constructor
//...methods for updating the creature/object
@Override
public void run() {
while (getState()!=State.DEAD) {
move(); //where the coordinates of a creature is updated.
repaint();
try { Thread.sleep(1000); }
catch(InterruptedException e) {}
}
}
したがって、クリーチャーの移動と再描画ごとに1秒ごとに呼び出されますが、ペイント内の各クリーチャーをループする必要がないか、再描画が呼び出されたときにそれを呼び出したクリーチャーのみを更新する方法が必要です。
提案や別の投稿を教えていただければ幸いです。ありがとう。