問題1: 体が成長する人 (コンストラクタ版)

第9回(前々回)の例で、体が成長するアニメーションを作成した(grownHuman.pde)。 これを、オブジェクト指向的でない部分について、 オブジェクト指向的に変更し、 さらにコンストラクタでオブジェクトを生成するよう改良しなさい。

生成するオブジェクトごとに最終の体型を変えられるよう、 最終の胴体の長さ、胴体の幅、頭の直径の3つの値をコンストラクタの引数で指定できるようにすること。

提出ファイル名: grownHuman_oo1.pde

問題1: 体が成長する人 (コンストラクタ版)

改良前 (grownHuman.pde)

final float fps = 60;            // フレームレート
final int x = 200;               // 人の中心の x座標
final int y = 320;               // 人の足元の y座標
final float h0 = 40;             // 初期の胴体の長さ
final float w0 = 20;             // 初期の胴体の幅
final float d0 = 25;             // 初期の頭の直径
final float he = 240;            // 最終の胴体の長さ
final float we = 140;            // 最終の胴体の幅
final float de = 50;             // 最終の頭の直径
final float growthRate = 0.004;  // 成長率
Human someone;

void setup() {
  size(400, 400);                  // ウィンドウのサイズ
  frameRate(fps);
  noStroke();                      // 輪郭線を無効に
  colorMode(HSB, 360, 100, 100);   // カラーモードをHSBに
  someone = new Human();
  someone.h = h0;
  someone.w = w0;
  someone.d = d0;
}

問題1: 体が成長する人 (コンストラクタ版)

改良前 (grownHuman.pde)

/**
 *  人の成長を描く
 */
void draw() {
  background(0, 0, 100);      // 背景色(白)
  someone.grown();            // 人を成長させる
  drawHuman(someone);         // 人を描く
}

void drawHuman(Human a) {
  fill(35, 60, 100);
  ellipse(x, y - a.h, a.d, a.d);           // 顔
  fill(220, 87, 100);
  ellipse(x, y - a.h / 2 + a.d / 2, a.w, a.h); // 胴体
}

class Human {
  float h;
  float w;
  float d;
  void grown(){
    if ( h < he )
      h = h * (1.0 + growthRate);
    if ( w < we )
      w = w * (1.0 + growthRate * 0.8);
    if ( d < de )
      d = d * (1.0 + growthRate * 0.5);
  }
}

問題1: 体が成長する人 (コンストラクタ版)

改良方針

問題2: 体が成長する人 (多人数版)

問題1で体が成長する人のアニメーションを作成した。 実世界では、成長の止まるタイミングは人それぞれであり、 メタボになるかも人それぞれである。 そこで、成長のしかたの異なる複数(5人以上)の人が成長する様子を観察しよう。 背の高さを比較するため、全員、足元のy座標は同じにする。 最初は全員同じ体型で、どこまで身長が伸び、太るかが異なるようにする。

胴体の色はコンストラクタの引数で指定しなくともランダムに定まるようにすること。 複数の人を管理するためにオブジェクトの配列を使うこと。

提出ファイル名: grownHumans.pde

問題3: 一定回数跳ね返ると色が変化するボール (コンストラクタ版)

前回、床で一定回数跳ね返ると色が変わるようにした。 色が変化してからも、また一定回数、床で跳ね返れば次の色に変化する。

今回は、ボールの x, y, vx, vy を引数にとるコンストラクタと、 引数をとらないコンストラクタの2つを用意すること。 引数をとらないコンストラクタを使った場合には、コンストラクタ内部で乱数を発生させ、 x, y, vx, vy の初期値を決めるものとする。

提出ファイル名: ballColorChanging_oo1.pde

問題3: 一定回数跳ね返ると色が変化するボール (非コンストラクタ版の例)

// constants
final int fps = 60;                 // 1秒間あたりのフレーム数
final float vx0min = -7;            // vxの初期値の下限
final float vx0max = 5;             // vxの初期値の上限
final float vy0min = 4;             // vyの初期値の下限
final float vy0max = 8;             // vyの初期値の上限
final float d = 40;                 // ボールの直径
final float hueMax = 360.0;         // 色相の最大値

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

void setup() {
  frameRate(fps);
  size(480, 480);
  noStroke();
  colorMode(HSB, hueMax, 100, 100);
  fill(0, 0, 0);
  aBall = new Ball();
  aBall.setD(d);
  aBall.setX(random(d / 2, width - d / 2));
  aBall.setY(random(d / 2, height / 5));
  aBall.setVX(random(vx0min, vx0max));
  aBall.setVY(random(vy0min, vy0max));
}

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

問題3: 一定回数跳ね返ると色が変化するボール (非コンストラクタ版の例)

/** 動くボールを表す */
class Ball {
  final float gravity = 9.8 / fps;    // 1フレームあたりの重力加速度
  final float elas = 0.98;            // 反発係数
  float d;                            // ボールの直径
  final float dH = 30;                // 色相の増加分
  float x;
  float y;
  float vx;
  float vy;
  float h = 0;                        // 色相
  int bounds = 0;                     // 跳ね返り回数
  void setD(float d) {
    this.d = d;
  }
  void setX(float x) {
    this.x = x;
  }
  void setY(float y) {
    this.y = y;
  }
  void setVX(float vx) {
    this.vx = vx;
  }
  void setVY(float vy) {
    this.vy = vy;
  }

問題3: 一定回数跳ね返ると色が変化するボール (非コンストラクタ版の例)

  void move() {
    x  += vx;          // ボールが速度ぶん移動する
    vy += gravity;     // 速度のy成分に重力加速度を加算する
    y  += vy;          // ボールが速度ぶん移動する
    if (x < d / 2) {
      vx = - vx * elas;
      x = d / 2;
    } else if (x > width - d / 2) {
      vx = - vx  * elas;
      x = width - d / 2;
    }
    if (y > height - d / 2) { // 床
      vy = - vy * elas;
      y = height - d / 2;
      // バウンド回数による色相の変更
      bounds += 1;
      if (bounds >= 4) {
        bounds = 0;
        h += dH;
        if (h > hueMax) {
          h -= hueMax;
        }
      }
    } else if (y < d / 2) {
      vy = - vy * elas;
      y = d / 2;
    }
  }
  void draw() {
    fill(h, 100, 100);
    ellipse(x, y, d, d);
  }
}

問題4: 一定回数跳ね返ると分裂するボール

問題3 と同じようにバウンドするボールを考える。 床で一定回数跳ね返るとボールが分裂するようにすること。 ボールは分裂すると、元のボールよりもその直径が若干小さくなる(例えば2/3)ものとする。

分裂するとボールが2つになるが、その片方は元のボールが小さくなったもの、 もう片方は新たに生まれたものと考えるとよい。 元のボールの速さと方向は通常の跳ね返りと同じとし、 新たに生まれるボールの速さと方向は任意とする (ただし分裂直後に床に当たらないように速度のy成分を決めること)。 ボール間の衝突は考慮しなくてよい。 色はボールの直径に応じて変化させること。 ボールの数の上限は適宜定めてよい (例えば 200)。

正しいバウンド回数で分裂しているかを確認をするため、 print/println関数を用いて各ボールのバウンド回数を逐次表示すること。

提出ファイル名: ballBoundingAndSplitting.pde

問題4: 一定回数跳ね返ると分裂するボール - ヒント

問題5: マウスカーソルで触れると分裂するボール (Advanced)

問題4 と同じように、分裂するボールを考える。 マウスカーソルがボールと重なり、その後ボールから離れる瞬間に分裂するようにすること。 ボールは分裂すると、元のボールよりもその直径が若干小さくなる(例えば2/3)ものとする。

ボール間の衝突は考慮しなくてよい。 色はボールの直径に応じて変化させること。 ボールの数の上限は適宜定めてよい (例えば 200)。

提出ファイル名: ballSplitter.pde

問題6: インタラクティブに物体などの数が変化するアニメーション (Advanced)

問題5 のように、ユーザのアクションによって物体などの数と動きが変化する、 独自のアニメーションを作成しなさい。

物体などの数の上限は適宜定めてよい。

提出ファイル名: interactiveCrowd.pde