8 アニメーション入門(いままで作ったものを動かそう)

8.1 学習目標

8.2 アニメーションの基本

ここからはオブジェクト指向プログラミングを使って、アニメーションを作っていきたいと思います。

8.2.1 回る家

まず、下のプログラムを実行してみましょう。

図 8.2.1.1 RotateHouse
リスト 8.2.1.1 RotateHouse.java
  1: /*
  2:  * タートルで書いた絵をまわすプログラム
  3:  * 
  4:  * 2003/06/16 Yoshiaki Matsuzawa
  5:  * 2012/10/31 改訂 Yoshiaki Matsuzawa
  6:  */
  7: public class RotateHouse extends Turtle {
  8: 
  9: 	// 起動処理
 10: 	public static void main(String[] args) {
 11: 		Turtle.startTurtle(new RotateHouse());
 12: 	}
 13: 
 14: 	// タートルを動かす処理
 15: 	public void start() {
 16: 		House house = new House();
 17: 		{ // アニメーションループ
 18: 			while (true) {
 19: 				sleep(0.1);
 20: 				{ // 処理を行う
 21: 					house.rt(5);
 22: 				}
 23: 				update();
 24: 			}
 25: 		}
 26: 	}
 27: 
 28: }

ここ をクリックすると、プログラムをダウンロードできます。

下のボタンを押すと、RotateHouseプログラムが実行できます。

ここでは、Houseのプログラムオブジェクトとして生成しています。 つまり、いままでタートルで作った絵を使うことができるのです。

タートルを使って自分の作ったオブジェクトを生成するには、次のような命令文を書きます。

図 8.2.1.2 オブジェクトの生成
使うオブジェクトを書くプログラムは同じフォルダに置く

例えば、RotateHouse.javaアニメーションで、House.javaを使う場合は、 その2つを同じフォルダに置く必要があります。

同じフォルダに置いていないとコンパイルエラーが出るので注意してください。

8.2.2 アニメーションの基本構造

RotateHouse.javaをもう一度よく見てみましょう。 特に、

while(true){
	//待つ

	//処理

	//再描画
}
				

ここの部分が、今までと異なる所で、アニメーションをするプログラムの特徴です。 どのようなアニメーションをするプログラムでも基本構造は同じです。 図解すると下のようになります。

図 8.2.2.1 アニメーションプログラムの構造
図 8.2.2.2 アニメーションプログラムの構造(具体的)

ちなみに、House.javaは次のようなプログラムでした。

リスト 8.2.2.1 House.java
  1: /*
  2:  * 家を書くプログラム
  3:  * 
  4:  * 2003/05/08 Yoshiaki Matsuzawa
  5:  * 2012/10/31 改訂 Yoshiaki Matsuzawa
  6:  */
  7: public class House extends Turtle {
  8: 
  9: 	// 起動処理
 10: 	public static void main(String[] args) {
 11: 		Turtle.startTurtle(new House());
 12: 	}
 13: 
 14: 	// タートルを動かす処理
 15: 	public void start() {
 16: 
 17: 		{// 屋根を書く
 18: 			rt(30); // 30度右を向く
 19: 			fd(50); // 50歩前に進む
 20: 			rt(120);
 21: 			fd(50);
 22: 			rt(120);
 23: 			fd(50);
 24: 		}
 25: 
 26: 		{// 本体を書く
 27: 			lt(90);
 28: 			fd(50);
 29: 			lt(90);
 30: 			fd(50);
 31: 			lt(90);
 32: 			fd(50);
 33: 			lt(90);
 34: 			fd(50);
 35: 		}
 36: 
 37: 	}
 38: 
 39: }

ここ をクリックすると、プログラムをダウンロードできます。

下のボタンを押すと、Houseプログラムが実行できます。

8.2.3 アニメーションをするための新しい命令

sleep([秒の指定])
指定された秒数だけ、眠り(止まり)ます。1を入れれば1秒止まり、0.1入れれば0.1秒止まります。
update()
画面を書き換えます。画面を書き換えないと、fd(5)などで移動しても、画面は書き換わらない(動かない)ので注意してください。
何秒眠るか

sleep()命令の中の数字を小さくすることによって、アニメーションを早くすることができます。 しかし、コンピュータの能力にも限界があります。 軽いアニメーションならば0.01秒(秒間100コマ)ぐらいまでならなんとか動きますが、 画像などを使うといくら小さい値を入れても、コンピュータの計算が追いつかなくなります。

人間が目に分かるのは、秒間30コマまでといわれています(テレビがそれぐらいです)ので、 それぐらいを目安に数値を決めると良いでしょう。

8.2.4 円を描く家

オブジェクトになっても、基本的なタートルの命令はどれでも使うことができます。 次のプログラムは、円を描く家のプログラムです。

図 8.2.4.1 CircleHouse
リスト 8.2.4.1 CircleHouse.java
  1: /*
  2:  * 家で円を描くプログラム
  3:  * 
  4:  * 2003/06/16 Yoshiaki Matsuzawa
  5:  * 2012/10/31 改訂 Yoshiaki Matsuzawa
  6:  */
  7: public class CircleHouse extends Turtle {
  8: 
  9: 	// 起動処理
 10: 	public static void main(String[] args) {
 11: 		Turtle.startTurtle(new CircleHouse());
 12: 	}
 13: 
 14: 	// タートルを動かす処理
 15: 	public void start() {
 16: 		House house = new House();
 17: 		{ // 赤い軌跡を描く準備
 18: 			house.color(java.awt.Color.red);
 19: 			house.down();
 20: 		}
 21: 		{ // アニメーションループ
 22: 			while (true) {
 23: 				sleep(0.1);
 24: 				{ // c//1コマの処理を行う
 25: 					house.rt(5);
 26: 					house.fd(5);
 27: 				}
 28: 				update();
 29: 			}
 30: 		}
 31: 	}
 32: 
 33: }

ここ をクリックすると、プログラムをダウンロードできます。

下のボタンを押すと、CircleHouseプログラムが実行できます。

down() 命令で、ペンを下ろして軌跡が描かれるようになっています。

図 8.2.4.2 円を描く家
初期値

いままでのタートルでは、down()命令をしなくても、 最初はペンを下ろした状態から始まっていました。

しかし、アニメーションでは、軌跡は要らないことが多いので、 初期値がペンを上げた状態になっています。

プログラムを書くときには、"最初の状態"を意識する必要があります。 これを「初期値」や「デフォルト値」といいます。

8.3 座標の制御

8.3.1 上向きのまま右に動かす

次に示すのは、家が右に動いていくプログラムです。

図 8.3.1.1 MoveRightHouse1
リスト 8.3.1.1 MoveRightHouse1.java
  1: /*
  2:  * 家を右に動かすプログラム(其の1: 右に向けて動かす方法)
  3:  * 
  4:  * 2003/06/16 Yoshiaki Matsuzawa
  5:  * 2012/10/31 改訂 Yoshiaki Matsuzawa
  6:  */
  7: public class MoveRightHouse1 extends Turtle {
  8: 
  9: 	// 起動処理
 10: 	public static void main(String[] args) {
 11: 		Turtle.startTurtle(new MoveRightHouse1());
 12: 	}
 13: 
 14: 	// タートルを動かす処理
 15: 	public void start() {
 16: 		House house = new House();
 17: 		house.rt(90);
 18: 		{ // アニメーションループ
 19: 			while (true) {
 20: 				sleep(0.1);
 21: 				{ // 1コマの処理を行う
 22: 					house.fd(5);
 23: 				}
 24: 				update();
 25: 			}
 26: 		}
 27: 	}
 28: 
 29: }

ここ をクリックすると、プログラムをダウンロードできます。

下のボタンを押すと、MoveRightHouse1プログラムが実行できます。

今までの方法では、前か後ろにしか進めませんが、 家は上向きのまま、右に動かしたい場合があります。

いままでの方法でも、下のように工夫することによって目的は達成できますが、 ここでは、warp命令を使ったエレガントな解決方法を考えます。

図 8.3.1.2 MoveRightHouse2
リスト 8.3.1.2 MoveRightHouse2.java
  1: /*
  2:  * 家を右に動かすプログラム(其の2: 上に向いたまま右に動かす)
  3:  * 
  4:  * 2003/06/16 Yoshiaki Matsuzawa
  5:  * 2012/10/31 改訂 Yoshiaki Matsuzawa
  6:  */
  7: public class MoveRightHouse2 extends Turtle {
  8: 
  9: 	// 起動処理
 10: 	public static void main(String[] args) {
 11: 		Turtle.startTurtle(new MoveRightHouse2());
 12: 	}
 13: 
 14: 	// タートルを動かす処理
 15: 	public void start() {
 16: 		House house = new House();
 17: 		{ // アニメーションループ
 18: 			while (true) {
 19: 				sleep(0.1);
 20: 				{ // 1コマの処理を行う
 21: 					house.rt(90);
 22: 					house.fd(5);
 23: 					house.lt(90);
 24: 				}
 25: 				update();
 26: 			}
 27: 		}
 28: 	}
 29: 
 30: }

ここ をクリックすると、プログラムをダウンロードできます。

下のボタンを押すと、MoveRightHouse2プログラムが実行できます。

8.3.2 ワープを使う

warp命令を使うと、回転せずに、好きな所にオブジェクトを移動することができます。

図 8.3.2.1 WarpHouse
リスト 8.3.2.1 WarpHouse.java
  1: /*
  2:  * 4つの家をワープを使って配置するプログラム
  3:  * 
  4:  * 2003/06/16 Yoshiaki Matsuzawa
  5:  * 2012/10/31 改訂 Yoshiaki Matsuzawa
  6:  */
  7: public class WarpHouse extends Turtle {
  8: 
  9: 	// 起動処理
 10: 	public static void main(String[] args) {
 11: 		Turtle.startTurtle(new WarpHouse());
 12: 	}
 13: 
 14: 	// タートルを動かす処理
 15: 	public void start() {
 16: 		House house1 = new House();
 17: 		House house2 = new House();
 18: 		House house3 = new House();
 19: 		House house4 = new House();
 20: 		{ // アニメーションループ
 21: 			while (true) {
 22: 				sleep(0.1);
 23: 				{ // 処理を行う
 24: 					house1.warp(100, 100);
 25: 					house2.warp(100, 200);
 26: 					house3.warp(200, 100);
 27: 					house4.warp(200, 200);
 28: 				}
 29: 				update();
 30: 			}
 31: 		}
 32: 	}
 33: 
 34: }

ここ をクリックすると、プログラムをダウンロードできます。

下のボタンを押すと、WarpHouseプログラムが実行できます。

このプログラムの実行結果は以下のようになります。

図 8.3.2.2 WarpHouse.javaの実行結果
座標に関する新しい命令
warp([x座標, y座標])
指定されたx座標, y座標の位置に、そのオブジェクトをワープ(瞬間的に移動)させます。命令に数字2つ必要なので、カンマで区切るのを忘れずに。
getX()
現在のx座標を取得します。
getY()
現在のy座標を取得します。

ちなみに、一般にコンピュータ環境では、数学とはちょっと違った座標体系が使われます。 タートルの場合もそうです。以下のようになっているので気をつけてください。

図 8.3.2.3 タートルの座標体系

さあ、ワープを使って、家を右に移動しましょう。

図 8.3.2.4 MoveRightHouse3
リスト 8.3.2.2 MoveRightHouse3.java
  1: /*
  2:  * 家を右に動かすプログラム(其の3: 上に向いたまま右に動かす(ワープを使う))
  3:  * 
  4:  * 2003/06/16 Yoshiaki Matsuzawa
  5:  * 2012/10/31 改訂 Yoshiaki Matsuzawa
  6:  */
  7: public class MoveRightHouse3 extends Turtle {
  8: 
  9: 	// 起動処理
 10: 	public static void main(String[] args) {
 11: 		Turtle.startTurtle(new MoveRightHouse3());
 12: 	}
 13: 
 14: 	// タートルを動かす処理
 15: 	public void start() {
 16: 		House house = new House();
 17: 		{ // アニメーションループ
 18: 			while (true) {
 19: 				sleep(0.1);
 20: 				{ // 1コマの処理を行う
 21: 					int x = house.getX();
 22: 					int y = house.getY();
 23: 					house.warp(x + 5, y);
 24: 				}
 25: 				update();
 26: 			}
 27: 		}
 28: 	}
 29: 
 30: }

ここ をクリックすると、プログラムをダウンロードできます。

下のボタンを押すと、MoveRightHouse3プログラムが実行できます。

さらに、右端までいったら左端にワープするように改造します。

図 8.3.2.5 MoveRightHouse4
リスト 8.3.2.3 MoveRightHouse4.java
  1: /*
  2:  * 家を右に動かすプログラム(其の4: 右端に行ったら左端に戻す(ワープを使う))
  3:  * 
  4:  * 2003/06/16 Yoshiaki Matsuzawa
  5:  * 2012/10/31 改訂 Yoshiaki Matsuzawa
  6:  */
  7: public class MoveRightHouse4 extends Turtle {
  8: 
  9: 	// 起動処理
 10: 	public static void main(String[] args) {
 11: 		Turtle.startTurtle(new MoveRightHouse4());
 12: 	}
 13: 
 14: 	// タートルを動かす処理
 15: 	public void start() {
 16: 		House house = new House();
 17: 		{ // アニメーションループ
 18: 			while (true) {
 19: 				sleep(0.1);
 20: 				{ // 1コマの処理を行う
 21: 					int x = house.getX();
 22: 					int y = house.getY();
 23: 					{ // 右に移動
 24: 						house.warp(x + 5, y);
 25: 					}
 26: 					{ // 右端だったら左端にワープ
 27: 						if (x >= 300) {
 28: 							house.warp(0, y);
 29: 						}
 30: 					}
 31: 				}
 32: 				update();
 33: 			}
 34: 		}
 35: 	}
 36: 
 37: }

ここ をクリックすると、プログラムをダウンロードできます。

下のボタンを押すと、MoveRightHouse4プログラムが実行できます。

だんだんアニメーションらしくなってきました。

8.4 大きさの変更(拡大/縮小)

8.4.1 大きさを変更するプログラム

オブジェクトは、大きさを変更することもできます。

図 8.4.1.1 LargeHouse
リスト 8.4.1.1 LargeHouse.java
  1: /*
  2:  * 家を大きくするプログラム(大きさを測る)
  3:  * 
  4:  * 2003/06/16 Yoshiaki Matsuzawa
  5:  * 2012/10/31 改訂 Yoshiaki Matsuzawa
  6:  */
  7: public class LargeHouse extends Turtle {
  8: 
  9: 	// 起動処理
 10: 	public static void main(String[] args) {
 11: 		Turtle.startTurtle(new LargeHouse());
 12: 	}
 13: 
 14: 	// タートルを動かす処理
 15: 	public void start() {
 16: 		House house = new House();
 17: 		{ // アニメーションループ
 18: 			while (true) {
 19: 				sleep(0.1);
 20: 				{ // 1コマの処理を行う
 21: 					house.size(200, 200);
 22: 				}
 23: 				update();
 24: 			}
 25: 		}
 26: 	}
 27: 
 28: }

ここ をクリックすると、プログラムをダウンロードできます。

下のボタンを押すと、LargeHouseプログラムが実行できます。

大きさに関する新しい命令
size([横の長さ], [縦の長さ])
そのオブジェクトを横の長さと縦の長さを、指定された大きさにします。命令に数字2つ必要なので、カンマで区切るのを忘れずに。
getWidth()
現在の横幅を取得します。
getHeight()
現在の縦幅を取得します。

8.4.2 徐々に大きくする

アニメーションループをうまく利用すれば、徐々に大きくなっていくプログラムが書けます。

図 8.4.2.1 LargerHouse
リスト 8.4.2.1 LargerHouse.java
  1: /*
  2:  * 家を大きくするプログラム(其の1: 大きくしていく)
  3:  * 
  4:  * 2003/06/16 Yoshiaki Matsuzawa
  5:  * 2012/10/31 改訂 Yoshiaki Matsuzawa
  6:  */
  7: public class LargerHouse extends Turtle {
  8: 
  9: 	// 起動処理
 10: 	public static void main(String[] args) {
 11: 		Turtle.startTurtle(new LargerHouse());
 12: 	}
 13: 
 14: 	// タートルを動かす処理
 15: 	public void start() {
 16: 		House house = new House();
 17: 		{ // アニメーションループ
 18: 			while (true) {
 19: 				sleep(0.1);
 20: 				{ // 1コマの処理を行う
 21: 					int width = house.getWidth();
 22: 					int height = house.getHeight();
 23: 					house.size(width + 2, height + 2);
 24: 				}
 25: 				update();
 26: 			}
 27: 		}
 28: 	}
 29: 
 30: }

ここ をクリックすると、プログラムをダウンロードできます。

下のボタンを押すと、LargerHouseプログラムが実行できます。

大きくなりすぎたら、小さく戻してあげましょう。

図 8.4.2.2 LargerHouse2
リスト 8.4.2.2 LargerHouse2.java
  1: /*
  2:  * 家を大きくするプログラム (其の2: 大きくなりすぎたら小さくする)
  3:  * 
  4:  * 2003/06/16 Yoshiaki Matsuzawa
  5:  * 2012/10/31 改訂 Yoshiaki Matsuzawa
  6:  */
  7: public class LargerHouse2 extends Turtle {
  8: 
  9: 	// 起動処理
 10: 	public static void main(String[] args) {
 11: 		Turtle.startTurtle(new LargerHouse2());
 12: 	}
 13: 
 14: 	// タートルを動かす処理
 15: 	public void start() {
 16: 		House house = new House();
 17: 		{ // アニメーションループ
 18: 			while (true) {
 19: 				sleep(0.1);
 20: 				{ // 1コマの処理を行う
 21: 					int width = house.getWidth();
 22: 					int height = house.getHeight();
 23: 					house.size(width + 2, height + 2);
 24: 					{ // 横幅が大きくなりすぎたら小さくする
 25: 						if (width >= 300) {
 26: 							house.scale(0.25);
 27: 						}
 28: 					}
 29: 					{ // 縦幅が大きくなりすぎたら小さくする
 30: 						if (height >= 300) {
 31: 							house.scale(0.25);
 32: 						}
 33: 					}
 34: 				}
 35: 				update();
 36: 			}
 37: 		}
 38: 	}
 39: 
 40: }

ここ をクリックすると、プログラムをダウンロードできます。

下のボタンを押すと、LargerHouse2プログラムが実行できます。

大きさ変更に便利な命令
scale([倍率])
そのオブジェクトを指定された倍率の大きさにします。
large([長さ])
指定した長さだけ縦横を幅を大きくします。
small([長さ])
指定した長さだけ縦横の幅を小さくします。
wide([長さ])
指定した長さだけ横幅を大きくします。
narrow([長さ])
指定した長さだけ横幅を小さくします。
tall([長さ])
指定した長さだけ縦幅を大きくします。
little([長さ])
指定した長さだけ縦幅を小さくします。

8.5 練習問題

8.5.1 オブジェクトの回転

これまでの課題で作ったもの(四角形,星など)を回転させるアニメーションを作ってみましょう。

ファイル名は「Rotation.java」とすること.

8.5.2 流れ星アニメーションを作ろう

星を書くプログラム(Star.java)を使って、流れ星のプログラムを書いてみよう。

ダウンロードはこちらから

仕上がり例

下のボタンを押すと、ShootingStar2プログラムが実行できます。

流れ星は、次の手順で進めていくとうまくできます。

  1. Star.javaをダウンロードして動かしてみる
  2. ShootingStar.javaを新しく作る(Star.javaは変更しないこと)
  3. ShootingStar.javaに、Starオブジェクトを生成して表示するプログラムを書く
  4. 星を回してみる
  5. 座標を使って、星を右に動かしてみる
  6. 一番右端にいったら、左端に戻るようにする
  7. 星を下にも動かす
  8. 一番下にいったら、上に戻るようにする
  9. 星の大きさを変える
  10. 星を増やす

ファイル名は「ShootingStar.java」とすること.

8.5.3 ハードル走アニメーションを作ろう

以下の実行例のように、人間を描くプログラム(Person.java)とハードルを描くプログラム(Hurdle.java)を使って、ハードル走のプログラムを書いてみよう。

ダウンロードはこちらから

仕上がり例

下のボタンを押すと、Hurdlingプログラムが実行できます。

ファイル名は「Hurdling.java」とすること.