Javaグラフィックサンプル(アプレット版):図形アニ

Javaグラフィックサンプル(アプレット版):スレッドを使ったアニメーションサンプルです。アプレット内で図形をいろんな方向に動かしたり、回転させたりするサンプルです。

Home > サンプル集 > アプレットサンプル集 > アニメーションサンプル


アニメーションサンプル

このページには、以下のサンプルを掲載しています。 下の項目をクリックをすると各サンプルにジャンプします。 ※2週間以内の新着記事はNewアイコン、更新記事はUpアイコンが表示されます。
  1. 図形の移動(横移動1) ( AnimationSample01.java )  
  2. 図形の移動(横移動2) ( AnimationSample01.java )  
  3. 図形の移動(縦移動) ( AnimationSample03.java )  
  4. 図形の移動(斜め移動) ( AnimationSample04.java )  
  5. 図形の移動(スレッド間隔の操作) ( AnimationSample05.java )  
  6. 図形の回転 ( AnimationSample06.java )  

1. 図形の移動(横移動1)

[ サンプルプログラムのソースコード - AnimationSample01.java - ]
  1. import javax.swing.JApplet;
  2. import java.awt.Color;
  3. import java.awt.Graphics;
  4. import java.awt.Graphics2D;
  5. public class AnimationSample01 extends JApplet implements Runnable {
  6.   private int x,w,h;
  7.   private Thread t;
  8.   public void init(){
  9.     x = 0;
  10.     w = getWidth();
  11.     h = getHeight();
  12.     t = new Thread(this);
  13.     t.start();
  14.   }
  15.   public void paint(Graphics g){
  16.     Graphics2D g2 = (Graphics2D)g;
  17.     g2.setBackground(Color.WHITE);
  18.     g2.setColor(Color.BLUE);
  19.     g.clearRect(0, 0, w, h);
  20.     g.fillOval(x, 10, 30, 30);
  21.   }
  22.   public void run() {
  23.     while( t != null ) {
  24.       try {
  25.         Thread.sleep(10);
  26.         x++;
  27.         x = w <= x ? 0 : x;
  28.         repaint();
  29.       } catch(Exception e ) {
  30.         e.printStackTrace();
  31.       }
  32.     }
  33.   }
  34. }
[ サンプルプログラムの実行結果 ]
実行結果を見るには下のボタンをクリックしてください。
※実行結果は、別ウィンドウで開きます。実行には時間がかかることがありますのでご注意ください。


[ サンプルプログラムの解説 ]
図形を動かす場合、静止したままの図形を描画する場合と違ってプログラムにいくつかの処理を追加する必要があります。
まず、サンプル6行目の赤字部分に「implements Runnable 」と言う記述がありますが、これは、サンプルのアプレットクラスに スレッドの機能を追加させるためのものです。スレッドとは何かと言うと指定した時間間隔で実行させることのできる処理を指します。 この指定した時間間隔で実行させる処理は、run()メソッドの中に記述します。サンプルでは、28行目から38行目の青字部分になります。 「implements Runnable 」でスレッド機能を追加したアプレットは、スレッドの登録を行います(15行目)。そして、16行目で登録したスレッドを実行させます。 これで、run()メソッド内で指定した時間間隔(27行目)でrun()メソッドが実行されます。大雑把に構造は、大体下のような感じになります。
  1. public class [アプレットの名前] extends JApplet implements Runnable {
  2.   [スレッド内で利用する変数等の宣言]
  3.   Thread thread;
  4.   public void init() {
  5.     [スレッド内で利用する変数等の初期化]
  6.     t = new Thread(this);
  7.     t.start();
  8.   }
  9.   public void paint(Graphics g) {
  10.     [スレッドで処理を行った変数を使って図形の描画処理を行う]
  11.   }
  12.   public void run() {
  13.     while( t != null ) {
  14.       try {
  15.         Thread.sleep([スレッドの時間間隔(ミリ秒単位)]);
  16.         [図形描画に利用する変数等の処理]
  17.         repaint();
  18.       } catch(Exception e ) {
  19.         e.printStackTrace();
  20.       }
  21.     }
  22.   }
  23. }

このサンプルを実行してみた方は、わかるかと思いますが、このサンプルには少々欠点があります。それは、画面のちらつきです。 なぜこのようなことが起こるのかと言うと描画処理の際にシステムが利用する描画領域に直接書き込みを行っているからです。
サンプルの場合、下のような描画処理がスレッドの時間間隔で延々と実行されています。

描画領域のクリア → 四角形の描画 → 描画領域のクリア → 四角形の描画 ....

描画処理と言うのは、少し時間のかかる処理のためシステム描画領域に直接書き込むと描画が処理が完了しないうちに次のスレッドの 描画処理が開始されることがあります。正常に描画できたり描画が途中で終わったりと言うことが繰り返されるので画面のちらつきが発生します。
サンプルのプログラムでの描画する四角形の大きさを大きくしたり、スレッド間隔を短くしてみたりすると描画処理が間に合わない可能性が高くなるので、画面のちらつきが多くなります。
これを解決するには、オフスクリーンへの描画処理が必要になります。システム描画領域とは別に自前で描画領域を確保してそこに描画処理を行います。 描画処理が全て完了した時点で、システムの描画領域へ書き込みます。オフスクリーンを使った方法は、次のサンプル以降で紹介します。


2. 図形の移動(横移動2)

[ サンプルプログラムのソースコード - AnimationSample02.java - ]
  1. import javax.swing.JApplet;
  2. import java.awt.Color;
  3. import java.awt.Graphics;
  4. import java.awt.Graphics2D;
  5. import java.awt.RenderingHints;
  6. import java.awt.image.BufferedImage;
  7. public class AnimationSample02 extends JApplet implements Runnable {
  8.   
  9.   private int x,w,h;
  10.   private Thread t;
  11.   private BufferedImage offimg;
  12.   private Graphics2D offs;
  13.   
  14.   public void init(){
  15.     x = 0;
  16.     w = getWidth();
  17.     h = getHeight();
  18.     offimg = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
  19.     offs = (Graphics2D)offimg.getGraphics();
  20.     offs.setRenderingHint(
  21.             RenderingHints.KEY_ANTIALIASING,
  22.             RenderingHints.VALUE_ANTIALIAS_ON);
  23.     offs.setBackground(Color.WHITE);
  24.     offs.setColor(Color.BLUE);
  25.     t = new Thread(this);
  26.     t.start();
  27.   }
  28.   
  29.   public void paint(Graphics g){
  30.     g.drawImage(offimg, 0, 0, null);
  31.   }
  32.   
  33.   public void update(Graphics g) {
  34.     paint(g);
  35.   }
  36.   
  37.   public void run() {
  38.     while( t != null ) {
  39.       try {
  40.         Thread.sleep(10);
  41.         offs.clearRect(0, 0, w, h);
  42.         offs.fillOval(x, 10, 30, 30);
  43.         x = w <= x ? 0 : x + 1;
  44.         repaint();
  45.       } catch(Exception e ) {
  46.         e.printStackTrace();
  47.       }
  48.     }
  49.   }
  50. }
[ サンプルプログラムの実行結果 ]
実行結果を見るには下のボタンをクリックしてください。
※実行結果は、別ウィンドウで開きます。実行には時間がかかることがありますのでご注意ください。


[ サンプルプログラムの解説 ]
いかがでしょうか?AnimationSample01.javaよりも滑らかな動きになりましたよね?これは、AnimationSample01.javaのところで少しお話 しましたが、オフスクリーンで描画処理を行っているため滑らかな動きとなります。
14、15行目でオフスクリーン用のBufferedImageクラスとGraphics2Dクラスのオブジェクト変数を宣言しています。
21行目でアプレットの描画領域と同じ大きさのイメージ領域を確保しています。
22行目でGraphics2Dの画像描画領域を生成しています。 23〜25行目は、生成した画像描画領域に対して描画の際にアンチエイリアス処理を行うように指定しています。 アンチエイリアス処理というのは、画像描画の際に線等が滑らかに見えるようにするための処理です。コンピューター上の画像は、 点描なので、斜めの線などは、どんなにがんばってもギザギザになってしまいます。そこで、ギザギザの部分に線の色と背景の色の中間色 を描画して線が滑らかに見えるようにするのがアンチエイリアス処理です。下のようなイメージになります。

26、27行目でオフスクリーンに対して背景色と描画色の設定を行っています。
33行目は、オフスクリーンに描画した画像をシステムの描画領域にイメージ画像として描画しています。
44、45行目でオフスクリーンへの描画処理を行っています。サンプルでは、円形を描画しています。この処理は、スレッドの中の処理になるので 43行目で指定したスレッドの時間間隔(サンプルでは、10ms)で繰り返し実行されます。


3. 図形の移動(縦移動)

[ サンプルプログラムのソースコード - AnimationSample03.java - ]
  1. import javax.swing.JApplet;
  2. import java.awt.Color;
  3. import java.awt.Graphics;
  4. import java.awt.Graphics2D;
  5. import java.awt.RenderingHints;
  6. import java.awt.image.BufferedImage;
  7. public class AnimationSample03 extends JApplet implements Runnable {
  8.   private int y,w,h;
  9.   private Thread t;
  10.   private BufferedImage offimg;
  11.   private Graphics2D offs;
  12.   public void init(){
  13.     y = 0;
  14.     w = getWidth();
  15.     h = getHeight();
  16.     offimg = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
  17.     offs = (Graphics2D)offimg.getGraphics();
  18.     offs.setRenderingHint(
  19.         RenderingHints.KEY_ANTIALIASING,
  20.         RenderingHints.VALUE_ANTIALIAS_ON);
  21.     offs.setBackground(Color.WHITE);
  22.     offs.setColor(Color.BLUE);
  23.     t = new Thread(this);
  24.     t.start();
  25.   }
  26.   public void paint(Graphics g){
  27.     g.drawImage(offimg, 0, 0, null);
  28.   }
  29.   public void update(Graphics g) {
  30.     paint(g);
  31.   }
  32.   public void run() {
  33.     while( t != null ) {
  34.       try {
  35.         Thread.sleep(10);
  36.         offs.clearRect(0, 0, w, h);
  37.         offs.fillOval(10, y, 30, 30);
  38.         y = h <= y ? 0 : y + 1;
  39.         repaint();
  40.       } catch(Exception e ) {
  41.         e.printStackTrace();
  42.       }
  43.     }
  44.   }
  45. }
[ サンプルプログラムの実行結果 ]
実行結果を見るには下のボタンをクリックしてください。
※実行結果は、別ウィンドウで開きます。実行には時間がかかることがありますのでご注意ください。

[ サンプルプログラムの解説 ]
基本的には、 AnimationSample02.javaと変わりません。図形(円形)の描画位置に使う(x, y)座標で、x座標を固定値にしてy座標を スレッド処理で増減させれば縦移動させることができます。サンプルでは、47行目でy座標の増減を行っています。
ちなみにこの処理は、三項演算と言います。書式は、下のようになっています。
[変数] = [条件式] ? [条件式が真の時、変数に入れる値] : [条件式が偽の時、変数に入れる値]
これは、下のような処理に書き換えることもできます。
if ( h <= y ) {
  y = 0;
} else {
  y = y + 1;
}
この処理によって図形が画面の下まで行ったらもう一度画面上部から描画するようになります。


4. 図形の移動(斜め移動)

[ サンプルプログラムのソースコード - AnimationSample04.java - ]
  1. import javax.swing.JApplet;
  2. import java.awt.Color;
  3. import java.awt.Graphics;
  4. import java.awt.Graphics2D;
  5. import java.awt.RenderingHints;
  6. import java.awt.image.BufferedImage;
  7. public class AnimationSample04 extends JApplet implements Runnable {
  8.   private int x,y,w,h;
  9.   private Thread t;
  10.   private BufferedImage offimg;
  11.   private Graphics2D offs;
  12.   public void init(){
  13.     x = 0;
  14.     y = 0;
  15.     w = getWidth();
  16.     h = getHeight();
  17.     offimg = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
  18.     offs = (Graphics2D)offimg.getGraphics();
  19.     offs.setRenderingHint(
  20.         RenderingHints.KEY_ANTIALIASING,
  21.         RenderingHints.VALUE_ANTIALIAS_ON);
  22.     offs.setBackground(Color.WHITE);
  23.     offs.setColor(Color.BLUE);
  24.     t = new Thread(this);
  25.     t.start();
  26.   }
  27.   public void paint(Graphics g){
  28.     g.drawImage(offimg, 0, 0, null);
  29.   }
  30.   public void update(Graphics g) {
  31.     paint(g);
  32.   }
  33.   public void run() {
  34.     while( t != null ) {
  35.       try {
  36.         Thread.sleep(10);
  37.         offs.clearRect(0, 0, w, h);
  38.         offs.fillOval(x, y, 30, 30);
  39.         x = w <= x ? 0 : x + 1;
  40.         y = h <= y ? 0 : y + 1;
  41.         repaint();
  42.       } catch(Exception e ) {
  43.         e.printStackTrace();
  44.       }
  45.     }
  46.   }
  47. }
[ サンプルプログラムの実行結果 ]
実行結果を見るには下のボタンをクリックしてください。
※実行結果は、別ウィンドウで開きます。実行には時間がかかることがありますのでご注意ください。

[ サンプルプログラムの解説 ]
横移動と縦移動のサンプルを組み合わせたものです。スレッド内でx座標、y座標ともに増減させると斜め移動をさせることができます。 このように描画位置をスレッド内で計算することで図形にさまざまな動きを与えることができます。たとえば円運動、ジグザグ移動、乱数 を使ってふらふらした動きなんかもさせることができます。


5. 図形の移動(スレッド間隔の操作)

[ サンプルプログラムのソースコード - AnimationSample05.java - ]
  1. import javax.swing.JApplet;
  2. import java.awt.Color;
  3. import java.awt.Graphics;
  4. import java.awt.Graphics2D;
  5. import java.awt.RenderingHints;
  6. import java.awt.image.BufferedImage;
  7. public class AnimationSample05 extends JApplet implements Runnable {
  8.   private int x,w,h,m;
  9.   private Thread t;
  10.   private BufferedImage offimg;
  11.   private Graphics2D offs;
  12.   public void init(){
  13.     x = 0;
  14.     w = getWidth();
  15.     h = getHeight();
  16.     m = 10;
  17.     offimg = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
  18.     offs = (Graphics2D)offimg.getGraphics();
  19.     offs.setRenderingHint(
  20.         RenderingHints.KEY_ANTIALIASING,
  21.         RenderingHints.VALUE_ANTIALIAS_ON);
  22.     offs.setBackground(Color.WHITE);
  23.     offs.setColor(Color.BLUE);
  24.     t = new Thread(this);
  25.     t.start();
  26.   }
  27.   public void paint(Graphics g){
  28.     g.drawImage(offimg, 0, 0, null);
  29.   }
  30.   public void update(Graphics g) {
  31.     paint(g);
  32.   }
  33.   public void run() {
  34.     while( t != null ) {
  35.       try {
  36.         Thread.sleep(m);
  37.         m = m < 100 ? m + 1 : 10;
  38.         offs.clearRect(0, 0, w, h);
  39.         offs.fillOval(x, 10, 30, 30);
  40.         x = w <= x ? 0 : x + 3;
  41.         repaint();
  42.       } catch(Exception e ) {
  43.         e.printStackTrace();
  44.       }
  45.     }
  46.   }
  47. }
[ サンプルプログラムの実行結果 ]
実行結果を見るには下のボタンをクリックしてください。
※実行結果は、別ウィンドウで開きます。実行には時間がかかることがありますのでご注意ください。

[ サンプルプログラムの解説 ]
移動方向は、AnimationSample01.javaと同じです。ただし、移動速度を変化させています。このサンプルでは、スレッドの実行間隔を 変化させることで移動速度の変化を表現しています(44、45行目)。また、別の方法としては、スレッドの時間間隔は、固定化しておいて、移動量を 変化させることで移動速度を変化させるという方法もあります。


6. 図形の回転

[ サンプルプログラムのソースコード - AnimationSample06.java - ]
  1. import javax.swing.JApplet;
  2. import java.awt.Color;
  3. import java.awt.Graphics;
  4. import java.awt.Graphics2D;
  5. import java.awt.RenderingHints;
  6. import java.awt.geom.AffineTransform;
  7. import java.awt.image.BufferedImage;
  8. public class AnimationSample06 extends JApplet implements Runnable {
  9.   private int r,w,h;
  10.   private Thread t;
  11.   private BufferedImage offimg;
  12.   private Graphics2D offs;
  13.   private AffineTransform at;
  14.   public void init(){
  15.     w = getWidth();
  16.     h = getHeight();
  17.     r = 0;
  18.     at = new AffineTransform();
  19.     offimg = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
  20.     offs = (Graphics2D)offimg.getGraphics();
  21.     offs.setRenderingHint(
  22.         RenderingHints.KEY_ANTIALIASING,
  23.         RenderingHints.VALUE_ANTIALIAS_ON);
  24.     offs.setBackground(Color.WHITE);
  25.     offs.setColor(Color.BLUE);
  26.     t = new Thread(this);
  27.     t.start();
  28.   }
  29.   public void paint(Graphics g){
  30.     g.drawImage(offimg, 0, 0, null);
  31.   }
  32.   public void update(Graphics g) {
  33.     paint(g);
  34.   }
  35.   public void run() {
  36.     while( t != null ) {
  37.       try {
  38.         Thread.sleep(10);
  39.         offs.clearRect(0, 0, w, h);
  40.         at.setToRotation(r*Math.PI/180.0f,55,55);
  41.         offs.setTransform(at);
  42.         offs.fillRect(30, 30, 50, 50);
  43.         r = r <= 360 ? r + 1 : 0;
  44.         repaint();
  45.       } catch(Exception e ) {
  46.         e.printStackTrace();
  47.       }
  48.     }
  49.   }
  50. }
[ サンプルプログラムの実行結果 ]
実行結果を見るには下のボタンをクリックしてください。
※実行結果は、別ウィンドウで開きます。実行には時間がかかることがありますのでご注意ください。

[ サンプルプログラムの解説 ]
AffineTransformオブジェクトのsetToRotationメソッドを使ってスレッド内で回転処理を行うと図形をくるくる回転させることができます。




最終更新日:2019/02/13

2015-03-01からの訪問者数
  6668 人