2003 -0116 ver 0.11 草稿開始 -0120 ver 0.92 草稿終了 -0120 ver 1.00 発行版 ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃.&&&& **** %%%%.  JavaScript&Javaで目指そう!基本情報技術者試験  ┃ ┃&&&&&&******%%%%%%  http://www.yscon.co.jp/j/java/jmaga/      ┃ ┃'&┃&''*┃*''%┃%'      (C)2002 斎藤末広 jmaga@yscon.co.jp  ┃ ┗━┻━━┻━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ 前回の発行部数 7774部(まぐまぐ:6517 melma!:744 Pubzine:478             ティアラオンライン:20 めろんぱん:15) ★解除・登録 :http://www2.odn.ne.jp/~egu33/jmaga/java-maga.html ★バックナンバー :http://www.yscon.co.jp/j/java/jmaga/ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓  第34号 2003/01/20  基本テクニック編 アニメーション ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛  プログラムを作成する上での注意事項:  Windows98SE, SDK(JDK) 1.4.0,IE 5.5 を前提としています。  拡張子を表示するに設定してください。 ========================================================================= 交換広告(交換希望の方は,jmaga@yscon.co.jpまで) ----☆PR☆-------------------------------------------------------------- 「ネットワークのおべんきょしませんか?」 TCP/IPってなに?LANってなに?ルータってなに?というネットワーク に関することをわかりやすく解説します。シスコCCNAやドットコムマス ター、情報処理試験対策にもぴったりです! http://www.mag2.com/m/0000046467.htm --------------------------------------------------------------☆PR☆---- ----☆PR☆--------------------------------------------------------------           コンピュータ関係の資格を取りたい方へ              毎日届く,宿題メールの勉強仲間に入りませんか? .&&&& **** %%%%. &&&&&&******%%%%%% 登録: http://backno.mag2.com/reader/Back?id=0000001414 '&┃&''*┃*''%┃%' 発行元:末広ページ http://3721p.com --------------------------------------------------------------☆PR☆---- ======================================================================== ▼ アニメーション  Jマガの第32号では,スレッドを利用して時刻を表示続けるプログラム作成 しました。この号では,絵を動かす,基本テクニックを勉強しましょう。 ------------------------------------------------------------------------ ▼ 復習 時刻表示  スレッドを利用した時刻表示をまず,見てみましょう。 例 j32-03 xSmpThread02.java スレッドを利用したアプレット 時刻表示 ソース http://www.yscon.co.jp/j/java/jmaga/j32/xSmpThread02.java 実行  http://www.yscon.co.jp/j/java/jmaga/j32/xSmpThread02.htm 1: /* 2: スレッドを利用したアプレット 時刻表示 3: */ 4: import java.applet.Applet; 5: import java.awt.Graphics; 6: import java.util.Date; // 日付・時刻関係 7: 8: public class xSmpThread02 extends Applet implements Runnable { 9: 10: Date xdNow; 11: Thread xth; // スレッドにインスタンス名を付ける。 12: 13: public void start(){ 14: xth = new Thread(this); // スレッド生成 15: xth.start(); // スレッド開始(ready状態へ) 16: } 17: 18: // Runnable対象部分 スレッド実行の時間管理 19: public void run(){ 20: while(true){ // 実行を継続する条件 21: repaint(); // 繰返し仕事(画面書き換え) 22: try { //「指定ミリ秒の間,眠る」をモニタ 23: Thread.sleep(1000); // 1 秒休み 24: } 25: catch(InterruptedException xe){ 26: } 27: } 28: } 29: 30: // 画面に表示(繰返し仕事) 31: public void paint(Graphics xg){ 32: xdNow = new Date(); 33: xg.drawString("今の時刻は " + xdNow, 30, 30); 34: } 35: }  このプログラムは,  スレッド生成  スレッド実行の時間管理  繰返し仕事 に分かれていました。アニメーションをするには,この「繰返し仕事」のところ を画像表示に変更すればいいはずです。 xSmpThread02 の繰返し仕事 30: // 画面に表示(繰返し仕事) 31: public void paint(Graphics xg){ 32: xdNow = new Date(); 33: xg.drawString("今の時刻は " + xdNow, 30, 30); 34: }  この部分を画像を表示するように書き換えてみましょう。  importや,変数,インスタンス宣言も必要になります。  このプログラムをできるだけ残しながら画像を表示してみましょう。 ------------------------------------------------------------------------ ▼ スレッドを利用したアニメーション  ボールの画像を上から下に動作させます。 例 j34-01 xAnime01.java 単純なアニメーション ソース http://www.yscon.co.jp/j/java/jmaga/j34/xAnime01.java 実行  http://www.yscon.co.jp/j/java/jmaga/j34/xAnime01.htm 1: /* 2: スレッドを利用したアニメーション もっとも単純 3: */ 4: import java.applet.Applet; 5: import java.awt.Graphics; 6: import java.awt.Image; 7: 8: public class xAnime01 extends Applet implements Runnable { 9: 10: Thread xthKeeper; 11: Image ximgBall; 12: 13: int y = 0; 14: 15: public void start(){ 16: 17: ximgBall = getImage(getCodeBase( ), "ball.gif"); 18: 19: xthKeeper = new Thread(this); // スレッド生成 20: xthKeeper.start(); // スレッド開始(ready状態へ) 21: } 22: 23: // Runnable対象部分 スレッド実行の時間管理 24: public void run(){ 25: while(true){ // 実行を継続する条件 26: repaint(); // 繰返し仕事(画面書き換え) 27: try { 28: Thread.sleep(50); 29: } 30: catch(InterruptedException xe){ 31: } 32: } 33: } 34: 35: // 画面に表示(繰返し仕事) 36: public void paint(Graphics xgPen){ 37: 38: y = y + 5; 39: if (y>200){ 40: y = 0; 41: } 42: 43: xgPen.drawImage(ximgBall, 30, y, this); 44: } 45: }  このプログラムも,  スレッド生成  スレッド実行の時間管理  繰返し仕事  の構造をそのまま利用してます。  画像を使用するということで, 6: import java.awt.Image;  で,Image クラスをインポートしてきています。 11: Image ximgBall;  画像の名前を,ximgBall としました。  start() の中で 17: ximgBall = getImage(getCodeBase( ), "ball.gif");  で,ball.gif と画像を ximgBall に記憶させています。getCodeBase() は, この xAnime01 があるディレクトリーの場所を調べて教えてくれます。以下, プログラムの中で,ximgBall という名前で,ball.gif を扱うことができます。  繰返し仕事,つまり,繰り返して表示する仕事は, 35: // 画面に表示(繰返し仕事) 36: public void paint(Graphics xgPen){ 37: 38: y = y + 5; 39: if (y>200){ 40: y = 0; 41: } 42: 43: xgPen.drawImage(ximgBall, 30, y, this); 44: } です。xgPen.drawImage() で,画面に画像を描きます。  アニメーション(動画)は,教科書に端に書いたパラパラの絵のように,連続し て,すこしずつ変化する絵を連続的に表示することで実現します。  パラパラのタイミングは, 28: Thread.sleep(50);  で,50ミリ秒としました。50ミリごとに, 38: y = y + 5; 39: if (y>200){ 40: y = 0; 41: } を実行して,画像の縦の位置を 5 ずつ増やして,200 を超えたら,0 としてい ます。表示は, 43: xgPen.drawImage(ximgBall, 30, y, this);  です。表示位置の座標は,x 方向(水平)は,30で,これは,数学の座標と同じで, 数が増えるほど,右側になります。y方向(垂直)は,数学の座標と反対で,数が 大きいほど,下になります。  y は,一こま描くたびに,5 ずつ増えますので,ball の絵は下に移動するよう に見えます。  次は,背景も加えてみましょう。 ------------------------------------------------------------------------ ▼ 背景画像の導入  背景も画像の一種です。ボールの画像と同じように,画像を指す名前を宣言し, getImageしてきます。表示も同じように行います。表示する位置は,0,0を指示 することで,画面の左上から貼ることできます。 例 j34-02 xAnime02.java バックグランド(背景)の導入 ソース http://www.yscon.co.jp/j/java/jmaga/j34/xAnime02.java 実行  http://www.yscon.co.jp/j/java/jmaga/j34/xAnime02.htm 1: /* 2: アニメーション バックグランド画像の導入 3: */ 4: import java.applet.Applet; 5: import java.awt.Graphics; 6: import java.awt.Image; 7: 8: public class xAnime02 extends Applet implements Runnable { 9: 10: Thread xthKeeper; 11: Image ximgBall, ximgBackGround; 12: 13: int y = 0; 14: // 15: public void start(){ 16: 17: ximgBall = getImage(getCodeBase(), "ball.gif"); 18: ximgBackGround = getImage(getCodeBase(), "bg.jpg"); 19: 20: xthKeeper = new Thread(this); // スレッド生成 21: xthKeeper.start(); // スレッド開始(ready状態へ) 22: } 23: 24: // Runnable対象部分 スレッド実行の時間管理 25: public void run(){ 26: while(true){ // 実行を継続する条件 27: repaint(); // 繰返し仕事(画面書き換え) 28: try { 29: Thread.sleep(50); 30: } 31: catch(InterruptedException xe){ 32: } 33: } 34: } 35: 36: // 画面に表示(繰返し仕事) 37: public void paint(Graphics xgPen){ 38: 39: y = y + 5; 40: if (y>200){ 41: y = 0; 42: } 43: xgPen.drawImage(ximgBackGround,0,0,this); 44: xgPen.drawImage(ximgBall, 30, y, this); 45: } 46: } anime01 と違ってところは,(行番号ついている方が,anime01) 11: Image ximgBall; を Image ximgBall, ximgBackGround; 17: ximgBall = getImage(getCodeBase( ), "ball.gif"); を ximgBall = getImage(getCodeBase(), "ball.gif"); ximgBackGround = getImage(getCodeBase(), "bg.jpg"); 43: xgPen.drawImage(ximgBall, 30, y, this); を xgPen.drawImage(ximgBackGround,0,0,this); xgPen.drawImage(ximgBall, 30, y, this); です。  表示するときは,背景が先ですね。  この xAnime02 を実行すると,背景は一応,表示されますが,ときどき,背景 が乱れて,白い帯が入ります。これを防ぐテクニックを次に考えてみます。 ------------------------------------------------------------------------ ▼ 背景をきれいに描く  背景,前景(ボール)がかかれる流れを見てみます。anime02 のプログラムに おいて, 24: // Runnable対象部分 スレッド実行の時間管理 25: public void run(){ 26: while(true){ // 実行を継続する条件 27: repaint(); // 繰返し仕事(画面書き換え) 28: try { 29: Thread.sleep(50); 30: } 31: catch(InterruptedException xe){ 32: } 33: } 34: }  の 27 行目のところで,repaint() が実行されています。  ここで,少し復習します。アプレットの表示の仕方は,  表示したいものは,paint() の中に書く  表示が必要になったら,自動的に paint() が実行される  repaint() で,意図的に paint() を実行できる  でした。今まで説明しませんでしたが,repaint() が,paint() を実行する ときに,正確には,repaint()の中で,update()が実行され,その中から,paint() が実行されています。つまり,repaint() から,paint() に移るときに,update() が実行されています。  update()は,アプレットの中で,再定義をしない(つまり省略する)と,画面を 消し,そのあとに,paint()を呼び出します。  今,anime02 では,paint() の中で,背景を描いています。そうすると, この背景を描く前に,update() で,画面がクリアされているので,時間的に この動作が近いため,画面に白い帯ができてしまいます。背景を描けば,画面 クリアの必要はありません。ですから,update() では,paint() しかしないと anime02 の中で,書けば,この問題は解決します。 public void update(Graphics gpen) { paint(gpen); } を,anime02.java の 45 行目の下に挿入すれば,終わりです。anime03 とし 作成してました。 例 j34-03 xAnime03.java 単純なアニメーション ソース http://www.yscon.co.jp/j/java/jmaga/j34/xAnime03.java 実行  http://www.yscon.co.jp/j/java/jmaga/j34/xAnime03.htm (リストは省略します)  実行してみてください。背景に白い帯が入らなくなったでしょう。  次は,動く画像が増えたたときの問題を扱ってみましょう。 ------------------------------------------------------------------------ ▼ ボールを30個描く  描く画像が増えると,コンピュータの処理に付加がかかり,ちらつきが発生し ます。  次のプログラムを動作せて見てください。表示するボールの数を30にしまし た。 例 j34-04 xAnime04.java アニメーション ボタン30個動作 ソース http://www.yscon.co.jp/j/java/jmaga/j34/xAnime04.java 実行  http://www.yscon.co.jp/j/java/jmaga/j34/xAnime04.htm 1: /* 2: スレッドを利用したアニメーション 3: ボタン30個動作 4: */ 5: import java.applet.Applet; 6: import java.awt.Graphics; 7: import java.awt.Image; 8: 9: public class xAnime04 extends Applet implements Runnable { 10: 11: Thread xthKeeper; 12: Image ximgBall, ximgBackGrand; 13: 14: int y= 0; 15: // 16: public void start(){ 17: 18: ximgBall = getImage(getCodeBase( ), "ball.gif"); 19: ximgBackGrand = getImage(getCodeBase(), "bg.jpg"); 20: 21: xthKeeper = new Thread(this); // スレッド生成 22: xthKeeper.start(); // スレッド開始(ready状態へ) 23: } 24: 25: // Runnable対象部分 スレッド実行の時間管理 26: public void run(){ 27: while(true){ // 実行を継続する条件 28: repaint(); // 繰返し仕事(画面書き換え) 29: try { // 「指定したミリ秒の間,眠る」をモニタ 30: Thread.sleep(50); // 31: } 32: catch(InterruptedException xe){ 33: } 34: } 35: } 36: 37: // 画面に表示(繰返し仕事) 38: public void paint(Graphics xgPen){ 39: 40: y = y + 3; 41: if (y>200){ 42: y = 0; 43: } 44: 45: xgPen.drawImage(ximgBackGrand,0,0,this); 46: 47: for(int i=0;i<30;i++){ 48: xgpen.drawImage(ximgBall, i*10, y, this); 49: } 50: } 51: 52: public void update(Graphics xgPen) { 53: paint(xgPen); 54: } 55: }  次のところで,単純にボールを30個表示しています。 47: for(int i=0;i<30;i++){ 48: xgpen.drawImage(ximgBall, i*10, y, this); 49: }  ボールを横に,10間隔で30個並べて描いています。  ボールを30個描くと,途中でちらつきが発生しています。これは,順々に 横にボールを30個描くときに,ハードウェアのレベルで,コンピュータが画面 をさらに高速に書き換えているため,タイミングの不一致で,発生します。  これを防ぐためには,別のところに画像をすべて作成して,一度に画面に描き 出すというテクニックを使います。別のところの画面を裏画面,見える画面を 表画面ということにしましょう。 ------------------------------------------------------------------------ ▼ スムーズに画像を表示する  xAnime04 を裏画面,表画面のテクニックを使って書き直した,xAnime05 にし たものです。 例 j34-05 xAnime05.java アニメーション ボタン30個動作 ソース http://www.yscon.co.jp/j/java/jmaga/j34/xAnime05.java 実行  http://www.yscon.co.jp/j/java/jmaga/j34/xAnime05.htm 1: /* 2: スレッドを利用したアニメーション 3: 裏画面利用 4: */ 5: import java.applet.Applet; 6: import java.awt.Graphics; 7: import java.awt.Image; 8: 9: public class xAnime05 extends Applet implements Runnable { 10: 11: Thread xthKeeper; 12: Image ximgBall, ximgBackGround; 13: 14: Image xuraGamen; 15: Graphics xuraGPen; 16: 17: 18: int y = 0; 19: // 20: public void start(){ 21: 22: xuraGamen = createImage(400, 200); 23: xuraGPen = xuraGamen.getGraphics(); 24: 25: ximgBall = getImage(getCodeBase( ), "ball.gif"); 26: ximgBackGround = getImage(getCodeBase(), "bg.jpg"); 27: 28: xthKeeper = new Thread(this); // スレッド生成 29: xthKeeper.start(); // スレッド開始(ready状態へ) 30: } 31: 32: // Runnable対象部分 スレッド実行の時間管理 33: public void run(){ 34: while(true){ // 実行を継続する条件 35: repaint(); // 繰返し仕事(画面書き換え) 36: try { 37: Thread.sleep(50); 38: } 39: catch(InterruptedException xe){ 40: } 41: } 42: } 43: 44: // 画面に表示(繰返し仕事) 45: public void paint(Graphics xgPen){ 46: 47: y = y + 3; 48: if (y>200){ 49: y = 0; 50: } 51: 52: xuraGPen.drawImage(ximgBackGround,0,0,this); 53: 54: for(int i=0;i<30;i++){ 55: xuraGPen.drawImage(ximgBall, i*10, y, this); 56: } 57: xgPen.drawImage(xuraGamen, 0, 0, this); 58: } 59: 60: public void update(Graphics gPen) { 61: paint(gPen); 62: } 63: }  裏画面は, 14: Image xuraGamen; 15: Graphics xuraGPen;  で名前を定義しています。裏画面に描き出すときの,ペン(Graphicsのインスタ ンス)は,別に用意する必要がありますので,xuraGPneとして用意しました。 22: xuraGamen = createImage(400, 200); 23: xuraGPen = xuraGamen.getGraphics();  裏画面の大きさを,400 * 200 で用意して,xuraGPne を裏画面専用のペンとし ています。  実際に paint() で一こま分を描き出すときは 52: xuraGPen.drawImage(ximgBackGround,0,0,this); 53: 54: for(int i=0;i<30;i++){ 55: xuraGPen.drawImage(ximgBall, i*10, y, this); 56: } 57: xgPen.drawImage(xuraGamen, 0, 0, this);  で,まず,52 行目で裏画面の背景を描きます,55行目で,裏画面にボールを 30個描きます。  57 行目で,裏画面をそのまま,表画面にまるごと描きます。  このように裏画面を用意して,そこに描いておき,一度に表に出すというやり 方をすると,ちらつきを防ぐことができます。このテクニックは,ダブルバッファー とも呼ばれて,複数の裏画面を用意して,そこに画像を書き出しておいて,高速 にそれを表に描き出すという風に利用することで,複雑なアニメーションを実現 することもできます。 ------------------------------------------------------------------------ ▼ その他のいくつかのテクニック  xAnime05 を動作させると,ボールが一番上からではなく,途中から動きはじ めます。これは,画像の準備が終わらないうちに動作を開始するからです。画像 の準備を終えてから,描き出すという風に変えます。これは,MediaTracker クラ スを利用して画像の準備ができたかどうかを管理させます。  また,裏画面を用意するときに,400,200 と固定をそのつど,指定するのは, 間違いのもとです。表画面の大きさを自動的に持ってくるように,変更します。 これは,getSize() を使います。  この2つのテクニックを導入したのが,xAnime06 です。 例 j34-06 xAnime06.java アニメーション MediaTracker, getSize()導入 ソース http://www.yscon.co.jp/j/java/jmaga/j34/xAnime06.java 実行  http://www.yscon.co.jp/j/java/jmaga/j34/xAnime06.htm 1: /* 2: スレッドを利用したアニメーション 3: 細かいテクニック導入 4: MediaTracker, getSize() 5: */ 6: import java.applet.Applet; 7: import java.awt.Graphics; 8: import java.awt.Image; 9: import java.awt.MediaTracker; 10: 11: public class xAnime06 extends Applet implements Runnable { 12: 13: Thread xthKeeper; 14: Image ximgBall, ximgBackGround; 15: MediaTracker xtracker; // 画像読み込み管理用 16: Image xuraGamen; 17: Graphics xuraGPen; 18: 19: int y = 0; 20: 21: public void init(){ 22: xuraGamen = createImage(getSize().width, getSize().height); 23: xuraGPen = xuraGamen.getGraphics(); 24: 25: xtracker = new MediaTracker(this); 26: ximgBall = getImage(getCodeBase(), "ball.gif"); 27: ximgBackGround = getImage(getCodeBase(), "bg.jpg"); 28: xtracker.addImage(ximgBall, 0); 29: xtracker.addImage(ximgBackGround,0); 30: try{ 31: xtracker.waitForAll(); 32: }catch(InterruptedException e){} 33: } 34: 35: public void start(){ 36: xthKeeper = new Thread(this); // スレッド生成 37: xthKeeper.start(); // スレッド開始(ready状態へ) 38: } 39: 40: // Runnable対象部分 スレッド実行の時間管理 41: public void run(){ 42: while(true){ // 実行を継続する条件 43: repaint(); // 繰返し仕事(画面書き換え) 44: try { 45: Thread.sleep(50); 46: } 47: catch(InterruptedException xe){ 48: } 49: } 50: } 51: 52: // 画面に表示(繰返し仕事) 53: public void paint(Graphics xgPen){ 54: 55: y = y + 3; 56: if (y>200){ 57: y = 0; 58: } 59: 60: xuraGPen.drawImage(ximgBackGround,0,0,this); 61: for(int i=0;i<30;i++){ 62: xuraGPen.drawImage(ximgBall, i*10, y, this); 63: } 64: xgPen.drawImage(xuraGamen, 0, 0, this); 65: } 66: 67: public void update(Graphics xgPen){ 68: paint(xgPen); 69: } 70: }  みなさんが,アニメーションのプログラムを作成しようと思った場合は,この プログラムの,繰返し部分を変更することで,作成可能でしょう。このサンプル を利用して,どんどん挑戦してください。 ----☆PR☆--------------------------------------------------------------           コンピュータ関係の資格を取りたい方へ              毎日届く,宿題メールの勉強仲間に入りませんか? .&&&& **** %%%%. &&&&&&******%%%%%% 登録: http://backno.mag2.com/reader/Back?id=0000001414 '&┃&''*┃*''%┃%' 発行元:末広ページ http://3721p.com --------------------------------------------------------------☆PR☆---- ------------------------------------------------------------------------ ▼ 次号の予定  次号では,文字列クラスの説明をします。  知りたいテクニック,また,解説してほしいクラスなどリクエストお寄せくだ さい。 ------------------------------------------------------------------------ ▼ 著作権について  このメールマガジンで公開しているプログラムソースは,著作権を当方スタッ フが所有しますが,商用を含めて,再利用,改変,発表を制限しません。  本文に関しては,斎藤末広が著作権を所有します。再利用に関しては,承諾を 必要とします。 ------------------------------------------------------------------------ ▼アンケート(以下を返信してください)  この号のJマガに対するご意見をお待ちしています。ぜひ,ご返信下さい。 内容のレベルは 1 難しいのでもっと簡単にしてほしい 2 ちょうどよい 3 もっと難しくてもよい その他ご要望