演習問題: 問題1

ボールを斜めに落とした時の動きをアニメーションにする。 ボールは床(画面下部)と壁でバウンドさせる。 床と壁の弾性係数は elas (= 0.98等) とする。 画面サイズは高さ 480、幅 480 とする。

前回(第8週)の問題2 で、float の配列で表現していた属性を Ball クラスの属性に置き換えた。 また、ボールのオブジェクトを与えると、 その属性を次時刻のものに変更する関数 boundBall(Ball) を作成した。

Ball クラスにボールを動かすメソッド move を用意し、 関数 boundBall で行っていた処理を、メソッド move で行うように変更しなさい。

提出ファイル名: ball_02_oo2.pde

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

次の手順で書き換えるとよい。

  1. Ball クラスのクラス定義を変更し、必要に応じて属性を追加する。
    • 直径、色相、重力加速度、反発係数も追加する。
  2. 属性の値にアクセスするためのアクセサメソッドを、必要に応じて用意する。
    • アクセサメソッド: setXXXXX, getXXXXX
    • アクセサメソッドは必要とは限らない。
      • 例えば、内部のメソッドからしか参照しない値なら getXXXXX はなくてもよい。
      • 不要なアクセサメソッドは作成しない。
  3. 関数 boundBall を、クラス Ball に属するメソッド move に書き換える。
    • 引数で受け取っていたオブジェクトは、自分自身「this」に変更になる。
    • 「this.」は省略可能。

演習問題: 問題1 - ベースとなる第8回問題2の解答例(1/2)

// 定数
final float vx0min = -7;            // vxの初期値の下限
final float vx0max = 5;             // vxの初期値の上限
final float vy0min = 4;             // vyの初期値の下限
final float vy0max = 8;             // vyの初期値の上限
final float fps = 60;               // 1秒間あたりのフレーム数
final float gravity = 9.8 / fps;    // 1フレームあたりの重力加速度
final float elas = 0.98;            // 反発係数
final float d = 40;                 // ボールの直径
final float hueMax = 360.0;         // 色相の最大値

// 変数
Ball ball0;                         // ボールのオブジェクト1つを参照する変数

void setup() {
  frameRate(fps);
  size(480, 480);
  noStroke();
  colorMode(HSB, hueMax, 100, 100);
  fill(0, 0, 0);
  ball0 = new Ball();
  ball0.d  = d;
  ball0.x  = random(d / 2, width - d / 2);     // ボールの中心のx座標
  ball0.y  = random(d / 2, height / 5);        // ボールの中心のy座標
  ball0.vx = random(vx0min, vx0max);           // ボールの速度のx成分
  ball0.vy = random(vy0min, vy0max);           // ボールの速度のy成分
}

void draw() {
  background(0, 0, 100);
  boundBall(ball0);
  fill(calcHue(ball0.vx, ball0.vy), 100, 100);
  ellipse(ball0.x, ball0.y, ball0.d, ball0.d);
}

float calcHue(float vx, float vy) {
  return (sqrt(vx * vx + vy * vy) * 16) % hueMax;
}

演習問題: 問題1 - ベースとなる第8回問題1の解答例(2/2)

void boundBall(Ball ball) {
  ball.x  += ball.vx;          // ボールが速度ぶん移動する
  ball.vy += gravity;          // 速度のy成分に重力加速度を加算する
  ball.y  += ball.vy;          // ボールが速度ぶん移動する
  if (ball.x < d / 2) {
    ball.vx = - ball.vx * elas;
    ball.x = d / 2;
  } else if (ball.x > width - d / 2) {
    ball.vx = - ball.vx  * elas;
    ball.x = width - d / 2;
  }
  if (ball.y > height - d / 2) {
    ball.vy = - ball.vy * elas;
    ball.y = height - d / 2;
  } else if (ball.y < d / 2) {
    ball.vy = - ball.vy * elas;
    ball.y = d / 2;
  }
}

/** 動くボールを表す */
class Ball {
  float d;
  float x;
  float y;
  float vx;
  float vy;
}

演習問題: 問題2

問題1 では、ボールの色を決めて描画する処理は関数 draw の中で行われていた。 しかし、これはボールに関する処理なので、Ball クラスのメソッド内で処理することが望ましい。 Ball クラスにボールの色を決めて描画するメソッド draw を用意し、 関数 draw からは、ボールオブジェクトに対して Ball クラスの draw メソッドを呼び出すようにしなさい。

この変更により不要になったアクセサメソッドは廃止すること。

提出ファイル名: ball_02_oo3.pde

演習問題: 問題3

問題2 にインタラクティブ性を持たせることにする。 ボールにマウスカーソルを持って行くと、ボールの動きを止めることができるようにしなさい。 マウスカーソルをボールから離すと、 そのときのマウスカーソルの速度でボールが動き始めるものとする。

提出ファイル名: ballThrowable.pde

補足: マウスカーソルはウィンドウの外に出ないと仮定してよい。

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

Ball クラスの中に描画するメソッド draw を用意すれば、関数 draw の中身はこれだけになる。

void draw() {
  background(0, 0, 100);
  ball0.move();
  ball0.draw();
}

マウスカーソルに捕まっているか否かの判定は move の中で行なっている。

演習問題: 問題4 (Advanced)

問題3 を変更し、マウスカーソルがボールと重なっている時に、 ボールの大きさが徐々に変化するようにしなさい。 最初に重なっているときには徐々に大きく、次に重なっている時には徐々に小さくと、 交互に変化するようにしなさい。

提出ファイル名: ballThrowableExpanding.pde

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

演習問題: 問題5 (Advanced)

動く物体に対してマウスカーソルの位置でなんらかの働きかけをする、 独自のインタラクティヴなアニメーションを作成しなさい。 第7週・第8週の演習問題とは異なる物体・動きにすること。

第8週の演習問題では物体ごとにクラスを定義した。 今回は、物体ごとにクラスを定義するだけでなく、 適切なメソッドをクラスに用意し、それを利用するようにしなさい。

提出ファイル名: ObjectsAndMouseCursor_oo2.pde