演習問題: 問題1

例題「さまざまなアニメーション: 重力」のプログラム(次のスライドに再掲)では、 ボールのx座標の値 100、ボールの直径の値 40 などが数値としてソースコードに埋め込まれている。 これでは、ソースコードを読む際にその値が何を表しているのか解読が必要となってしまい、 ソースコードの可読性や保守性に難がある。

そこで、次の定数をソースコードの冒頭で定義し、これを利用するように書き換えなさい: 1秒間あたりのフレーム数 fps、ボールの直径 d、ボールのx座標 x、ボールのy座標の初期値 y0、 ボールの初速度 vy0。なお、ボールの初速度は 4 とする。 また、ボールの初期位置は、ボールが画面上部に接する位置にしなさい。

提出ファイル名: ball_y1.pde

復習: さまざまなアニメーション: 重力

// 定数
final float gravity = 9.8 / 60;  // <-- 1/60秒あたりの重力加速度
// 変数
float y;                         // <-- ボールのy座標
float vy;                        // <-- ボールの速度のy成分

void setup() {
  size(200, 480);
  noStroke();
  fill(0, 0, 0);
  y = 0;
  vy = 0;
}

void draw() {
  vy += gravity;    // <-- 速度に重力加速度を加算する
  y += vy;          // <-- ボールが速度ぶん移動する

  background(255, 255, 255);
  ellipse(100, y, 40, 40);
}

演習問題: 問題2

ボールを画面下部でバウンドさせる。 バウンドは 反発係数 elas (= 0.98等) を導入し、 ボールが接地したら、速度 vy = - vy * elas; とする。 なお、ボールを丁度接地した位置に描画するには ellipse(x, height - 直径/2, ...) とする。

提出ファイル名: ball_y2.pde

演習問題: 問題2

ヒントと補足

厳密には1/60秒ごとの各フレームの間のどこかのタイミングで床に到達するが、 跳ね返ったあとのアニメーションは、 床に接地した状態から書き始めてよいものとする。

y += vy で y を更新したのち、その y の位置だとボールが床にめり込むという場合には、 床に到達して跳ね返っているはずなので、y の値をボールが床に接する位置に変更する。

演習問題: 問題3

ボールの高さに応じて色(色相)が変わるように変更しなさい。 ボールの中心がウィンドウの上端と一致するとき(y == 0)、 ボールの色が赤になるようにすること (次のスライド参照)。

提出ファイル名: ball_y3.pde

演習問題: 問題3

ヒント

colorMode(HSB, 360, 100, 100); とした場合:

演習問題: 問題4

ボールの速度の大きさに応じて色(色相)が変わるように変更しなさい。 ボールが停止した時 (速度の大きさが0の時)、ボールの色が赤になるようにすること。

ボールの速度を与えると色相を返す関数 calcHue を作成して用いること。 なお、速度が上昇したときに色相が一回転して赤に戻ってもかまわないものとする。

提出ファイル名: ball_y4.pde

演習問題: 問題4 - ヒント

速度の値の大きさをコンソールに表示させると、その最大値は約 12 であることがわかる。 この値をそのまま色相(最大360)とすると変化が小さすぎるため、なんらかの係数をかけて調整をするとよい。

演習問題: 問題5

ボールを斜めに落とした時の動きをアニメーションにする。 画面幅は 200 から 480 にする。壁・天井の反発係数は床と同じ elas とする。

ボールの色は、ボールの速度の大きさに応じて色相が変化するようにすること。
(次のスライドに続く)

提出ファイル名: ball_01.pde

演習問題: 問題5

速度にx成分とy成分があるので、速度の大きさは以下の計算式で求める必要がある。

速度から色相を求める関数 calcHue を改造し、 ボールの速度のx成分 vx, ボールの速度のy成分 vy の2つを渡して色相を求める関数にし、 用いること。

演習問題: 問題6

ボールの x座標、y座標、速度のx成分、速度のy成分、を要素とする 4要素の配列を用意する。 この配列を参照する変数(仮に ball0 とする)を引数に与えると、 その配列の内容を更新し、ボールの位置・速度の情報を次の時刻(フレーム)のものに更新する関数 boundBall(ball0) を定義し、これを利用するよう問題5のプログラムを書き換えなさい。

提出ファイル名: ball_02.pde

演習問題: 問題6

ヒント

配列を参照する変数の名前を ball0 としたとき、 ball0[0] はx座標、ball0[1] はy座標、などと割り当てる。 以下の定数を用意しておくと、ball0[X], ball0[Y] などと書くことができる。

final int X = 0;
final int Y = 1;
final int VX = 2;
final int VY = 3;

演習問題: 問題7 (Advanced)

複数(例えば6個)のボールの初期位置と初期速度が入った 2次元配列 balls を用意する。 初期位置と初期速度は乱数で決めるものとする。 問題6で作成した、1つのボールを動かす関数 boundBall を複数回用いることにより、 すべてのボールが動くようにしなさい。

提出ファイル名: balls_01.pde

演習問題: 問題7 - ヒント

以下のような骨格になる。

// 定数
...
final int nBalls = 6;               // ボールの個数

// 変数
float[][] balls;                    // 複数のボールの位置と速度を保持する2次元配列を参照する変数

void setup() {
  // ここで 2次元配列を生成し、balls に代入
  balls = ...
  // 各ボールについて、1個ずつ、初期位置と初期速度を設定(乱数で)
  ...
}

void draw() {
  // ボールを 1個ずつ、移動させては描画
  ...
}

// その他の関数の定義
...

演習問題: 問題7 - ヒント

必要に応じて第3週のスライドを参照するとよい。

2次元配列 balls は、ボール1個についての情報を持つ1次元配列を、複数個分まとめたもの。

final int X = 0;
final int Y = 1;

...

float x = balls[i][X];      // i番目のボールのx座標
float y = balls[i][Y];      // i番目のボールのy座標

float[] ball = balls[i];    // i番目のボールの情報を持つ1次元配列
float ix = ball[X];         // i番目のボールのx座標

boundBall 関数は 1つのボールについての情報を格納した 1次元配列を引数にとる。 i番目のボールを動かしたければ、boundBall(balls[i]) とすればよい。

演習問題: 問題8

再帰的な構造を持つ以下の図形を描画しなさい。 ある円の中に、半径が半分の円が2つある。そのそれぞれの円の中にも、半径が半分の円が2つある。 以下同様だが、ある条件を満たしたときに描画を終わりにすること。 以下の例では、半径の値の下限を設定している。

半径が異なる円は、色も異なるようにすること。

提出ファイル名: nestedCircles.pde

演習問題: 問題9 (Advanced)

問題8をアニメーションにしなさい。 以下の例では回転運動にしているが、回転運動でなくてもかまわない。

提出ファイル名: nestedCirclesMoving.pde