アニメーション(メディアプログラミング演習I)

これまでのプログラムは静止画を表示するだけでしたが、次はアニメーションやインタラクションに必要なプログラムの説明をおこないます(この回はアニメーションのみ)。

ここで必ず使う機能はsetup()draw()です。
このモードはProcessingプログラミングの中で一番よく使われるものです。
setup()で初期化し、draw()を繰り返し実行することでアニメーションなどが出来ます。
setup()は一度だけしか使えません。以下にその例を挙げます。

1. アニメーション

シンプルなアニメーション

ムービー

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int eSize = 5;  //オブジェクトのサイズ
int speed = 5;  //オブジェクトのスピード
int x = 0;  //オブジェクトのx座標
 
//初期化
void setup() {
  size(300, 300);
  noStroke();      //輪郭を描かない
  frameRate(30);  //再生速度を1秒30フレームに設定(初期値は1秒60フレーム)
  smooth();        //オブジェクトにアンチエイリアスをかける
  fill(0);      //オブジェクトを黒で塗りつぶす
}
 
//ひたすら{ }で囲まれた中を繰り返す
void draw() {
  background(255);  //画面の色を更新
  ellipse(x, height/2, eSize, eSize);    //円を描く
  x = x + speed;    //x座標にspeedの値を足す
 
}

どうだろうか。要はdraw()の { } で囲まれた中のプログラムがひたすら繰り返されるので、xの値がどんどん増えていき、それが結果的にグラフィックとしてはアニメーションしているように見える訳です。
プログラム上でのアニメーションは全てがこの原理に従っています。要は変数の値を変えていき、それがx, y座標の値を変えていけばいいという事なのです。

繰り返し
上のプログラムのように、x座標がひたすら増えていった場合、オブジェクトが画面の外に出てしまったらその先がどうなったか分かりません。ということで、同じアニメーションを繰り返すプログラムを作ってみましょう。

ムービー

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int eSize = 5;  //オブジェクトのサイズ
int speed = 5;  //オブジェクトのスピード
int x = 0;  //オブジェクトのx座標
 
void setup() {
  size(300, 300);
  noStroke();      //輪郭を描かない
  frameRate(30);  //再生速度を1秒30フレームに設定(初期値は1秒60フレーム)
  smooth();        //オブジェクトにアンチエイリアスをかける
  fill(0);      //オブジェクトを黒で塗りつぶす
}
 
void draw() {
  background(255);  //画面の色を更新
  ellipse(x, height/2, eSize, eSize);    //円を描く
  x = x + speed;    //x座標にspeedの値を足す
  if (x >= width) {    //もし、xの値が画面の幅以上になったら、xを0に戻す
    x = 0;
  }
}

折り返し
ムービー

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int eSize = 5;  //オブジェクトのサイズ
int speed = 5;  //オブジェクトのスピード
int x = 0;  //オブジェクトのx座標
 
//初期化
void setup() {
  size(300, 300);
  noStroke();      //輪郭を描かない
  frameRate(30);  //再生速度を1秒30フレームに設定(初期値は1秒60フレーム)
  smooth();        //オブジェクトにアンチエイリアスをかける
  fill(0);  //黒で描く
}
 
//プログラムが終了するまで、draw()の中は繰り返される
void draw() {
  background(255);  //背景は白
  ellipse(x, height/2, eSize, eSize);    //円を描く
 
  x = x + speed;    //xの値にspeedを足す
 
  //もし、xの値が画面の右端より大きくなるか、左端より小さくなった場合、
  if(x > width || x < 0) {
    speed = -speed;    //speedの正負を入れ替える
  }
}

2. 変数のスコープ(範囲)

次は変数のスコープ(範囲)を学習します。
多くのプログラミング言語には、その変数が有効となる範囲があります。
代表的な変数は、グローバル変数ローカル変数です。
この2つの変数の意味を覚えておけば、ここでの学習はかなりの部分が終わったといえます。
このProcessingはJavaをベースにして作られているので、実際にはメンバ変数というのもありますがここでは必要ありません。
ここでは、グローバル変数とローカル変数だけを理解しておきましょう。
まずは、以下の2つのサンプルコードをProcessing上で再生してみてください。
その際、変数 i の値がテキストエリアに表示されますが、その値がどのように違うかを調べてみること。

ローカル変数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int counter;
 
void setup() {
  counter = 0;
}
 
void draw() {
  int i = 0;
 
  if ( counter < 5) {
    println(i);
    i ++;
    counter ++;
  }
}

グローバル変数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int i;
int counter;
 
void setup() {
  i = 0;
  counter = 0;
}
 
void draw() {
 
  if ( counter < 5) {
    println(i);
    i ++;
    counter ++;
  }
}

再生してみれば分かると思いますが、上のローカル変数 i の場合は、値が常に0で変化しません。逆にグローバル変数 i はdraw( ) が実行されるたびに値が1ずつ増えているのが分かるでしょう。アニメーションをさせる場合には主にグローバル変数を使う事がほとんどです。それは前の値を保持しているからなのです。

また、ここで覚えておくことは、draw( ) のように { } で閉じられた部分を「関数」(function)と呼ぶことです。
ローカル変数は一つの関数の中のみで有効であり、グローバル変数は関数の外に書かれているので、どの関数からも共通して使われます
色々変数を宣言する場所を変えて試してみましょう。

3. 色彩のアニメーション

当然、x, y軸を変えるだけではなく、色彩も変化させることが出来ます。以下のサンプルを実行してみましょう。

ムービー

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int gray;  //grayの値
int speed;  //色の変化のスピード
 
//初期化
void setup() {
  size(300, 300);
  frameRate(30);  //再生速度を1秒30フレームに設定(初期値は1秒60フレーム)
  gray = 0;  //grayの初期初期値は0
  speed = 5;    //スピードの初期設定
}
 
//プログラムが終了するまで、draw()の中は繰り返される
void draw() {
 
  gray += speed;    //grayの値にspeedを足す
 
  //もし、grayの値が255(最大値)より大きくなるか、0(最小値)より小さくなった場合、
  if(gray > 255) {
    speed = -speed;  //speedの増える値を反転する
    gray = 255;  //grayを白にする
    println("speed = " + speed);
  }else if(gray < 0) {
    speed = -speed;  //speedの増える値を反転する
    gray = 0;  //grayを黒にする
    println("speed = " + speed);
  }
 
  background(gray);  //背景を描く
}

他にもサンプルがあるので、プログラムを自力で考えてみましょう。

サンプルプログラム1

4. タイマー

時間が経ったら変化するアニメーションを作りたいとき、タイマーを使うと有効です。
タイマーと言っても今まで学習した変数を使う簡単なもので十分機能します。
以下のサンプルを実行してみましょう。

ムービー

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int timer = 0;  //タイマー
 
//初期化
void setup() {
  size(300, 300);
  noStroke();
  frameRate(30);  //再生速度を1秒30フレームに設定(初期値は1秒60フレーム)
  smooth();
}
 
//プログラムが終了するまで、draw()の中は繰り返される
void draw() {
  background(255);
 
  //時間を計るときには、再生速度が1秒30フレームに設定されているので、秒数に30を掛ける必要がある
  if(timer > 3*30 ){    //もし、counterが3秒を超えたら、
    fill(255, 0, 0);     //赤にする
  }
  else{                 //そうでなかったら、
    fill(0, 255, 0);    //緑にする
  }
  ellipse(width/2, height/2, 100, 100); 
 
  if(mousePressed) {    //マウスが押されたら、
    println(timer/30);         //経過時間を出力する(秒)。
  }
  timer ++;
}