Timer描画プログラムの改良版

 

ざざっと作ったプログラムを翌日眺めてみると
自分が書いたコードなのに「何か変だな」と思えたりします。

毎度、管理人イガジーです。

作っている時は色々な事が頭の中にあり、「熱く」なっているのですが
一晩経つと「冷える=冷静になる」からでしょう。
昨日のタイマーでグラフィックを描画するサンプルも、改めてみると何か変です。
paintで描画するbufferedImage の扱いが、ダブルバッファとして使う予定だったのに
ひとつの図形(パーツ)とするように途中で変更してしまったからです。
(描画を速くしたい気持ちがそうさせたのです)

現状では、一部を他の窓で覆ってはずした場合、隠れていた部分が元に
戻らないので、やっぱりダブルバッファにする事にします。
そして、動かす際に移動量を含めた大きな範囲をクリアしてましたが
移動前に消して、移動後に描画すれば、すっきりします。
という訳で、改良したプログラムを掲載しておきます。

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.util.Timer;
import java.util.TimerTask;

public class AnimationTest {
	final int bww=30, bhh=30;
	final int bufw=200,bufh=170;
	BufferedImage b=new BufferedImage(bufw+bww,bufh+bhh,BufferedImage.TYPE_INT_RGB);
	final int speed=7;
	final int interval=50; //ms
	int x,y;
	Frame f;
	MyCanvas cv;
	Timer tmr;
	boolean done=false;
	int busycount=0;

	AnimationTest() { // constructor
		f=new Frame("AnimationTest");
		f.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent ev) {
				System.exit(0);
			}
		});
		cv=new MyCanvas();

		f.add(cv,BorderLayout.CENTER);
		Button stpbtn=new Button("Stop");
		stpbtn.addActionListener(new TimStop());
		f.add(stpbtn,BorderLayout.SOUTH);
		tmr=new Timer();
		tmr.schedule(new MyTimer(), 1000, interval);
		f.setSize(300,300);
		f.setVisible(true);
	}

	class MyTimer extends TimerTask {
		int vx=speed;
		int vy=2;
		public void run() {
			if (done) {
				cv.g.setColor(Color.BLACK);
				cv.g.fillRect(x, y, bww, bhh);
//				cv.g.fillRect(0, 0, bww+bufw, bhh+bufh);
				x+=vx;
				y+=vy;
				if ((x<=10)||(x>=bufw)) vx=-vx;
				if ((y<=40)||(y>=bufh)) vy=-vy;
				cv.g.setColor(Color.YELLOW);
				cv.g.fillRect(x, y, bww, bhh);
				done=false;
				cv.repaint();
			}else{
				System.out.print("Busy ");
				System.out.println(busycount++);
			}
		}
	}
	class TimStop implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent arg0) {
			tmr.cancel();
		}
	}
	class MyCanvas extends Canvas {
		private static final long serialVersionUID = 1L;
//		Toolkit tk=Toolkit.getDefaultToolkit();
		Graphics g;
		MyCanvas() {
			x=10;
			y=40;
			g=b.getGraphics();
//			this.setBackground(Color.BLACK);
		}
		@Override
		public void update(Graphics g0){
			paint(g0);
		}
		@Override
		public void paint(Graphics g0) {
			g0.drawImage(b,0,0,f);
//			tk.sync();
			done=true;
		}
	}
	public static void main(String[] args) {
		new AnimationTest();
	}
}

タイマールーチンにも、再入保護を入れました。
描画は思ってたよりも速くて、50ms毎(20fps)に追随してるように見えます。
(気のせいかもしれませんが)
これを下敷きにして試してみると、色々な発見がありそうです。
Toolkitにsync()というメソッドがあるのですが、上記ソースではコメントにしています。
管理人イガジーの環境では、ざっと見ですが、入れても入れなくても
動作に違いは無いように見えました(もう少し遊んでみます)。

この記事へのコメントはこちら

メールアドレスは公開されませんのでご安心ください。
また、* が付いている欄は必須項目となりますので、必ずご記入をお願いします。

内容に問題なければ、下記の「コメント送信」ボタンを押してください。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)