演習問題: 問題1

横に並んだ2人を描きたい。 それぞれの胴体の長さと色(色相)はランダムとする。 次のスライドの穴埋めをしなさい。

提出ファイル名: coloredHumans.pde

演習問題: 問題1 - 穴埋め

final int dhumanX = 100;                 // 人の間隔
final int humanY = 300;                  // 人の列のy座標
final int humanBodyWidth = 30;           // 体の幅
final int faceDiameter = 50;             // 顔の直径
int humanX = 150;                        // 人のx座標の初期値

void setup() {
  size(400, 400);                  // ウィンドウのサイズ
  background(255, 255, 255);       // 背景色(白)
  noStroke();                      // 輪郭線を無効に
  colorMode(HSB, 360, 100, 100);   // カラーモードをHSBに

  ■■■■■;
  ■■■■■;

  ■■■■■ = (int)random(150, 190);      // 胴体の長さ
  ■■■■■ = (int)random(120, 240);      // 人の色
  drawHuman(humanX, humanY, man.bodyHeight, man.bodyColor);

  humanX += dhumanX;

  ■■■■■ = (int)random(130, 170);      // 胴体の長さ
  ■■■■■ = (int)random(0, 60);         // 人の色
  drawHuman(humanX, humanY, woman.bodyHeight, woman.bodyColor);
}

class Human {
  int bodyHeight;   // 胴体の長さ
  int bodyColor;    // 人の色
}

/**
 *  人の形を描く(色相はランダム)
 *  @param x 人のx座標(体の中央軸)
 *  @param y 人のy座標(足元)
 *  @param bodyHeight 人の胴体の長さ
 *  @param bodyColor 人の色
 */
void drawHuman(int x, int y, int bodyHeight, int bodyColor) {
  fill(bodyColor, 100, 100);
  ellipse(x, y - bodyHeight, faceDiameter, faceDiameter);                  // 顔
  rect(x - humanBodyWidth / 2, y - bodyHeight, humanBodyWidth, bodyHeight);    // 胴体
}

演習問題: 問題2

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

第6週の問題6では、ボールの現在位置と速度の入った4要素の配列を用意した。 これを、Ball クラスに置き換えること。 また、配列を与えると、その内容を次時刻のものに変更する関数 boundBall(float[] ball) は、 ボールのオブジェクトを与えるように書き換えて使用すること。

Ball クラスの属性(フィールド)に直径、色の情報を用意するかは任意とする。

提出ファイル名: ball_02_oo1.pde

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

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

  1. Ball クラスのクラス定義を記述する。
    • class Ball { .... }
    • 記述する場所は setup, draw 関数の外。
  2. Ball クラスのオブジェクトを保持する変数の型宣言をする。
    • Ball ball0;
    • 記述する場所は setup, draw 関数の外。
  3. Ball クラスのオブジェクトを生成し、変数に代入する。
    • ball0 = new Ball();
    • 記述する場所は setup 関数の中。
  4. 配列の添字を用いてアクセスしていた中心座標と速度の情報を、フィールド x, y, vx, vy を用いたものに変更する。
    • ball0[X] は ball0.x に、ball0[Y] は ball0.y に、...
  5. 関数 boundBall の引数の型を変更する。
    • Ball オブジェクトへの参照を渡すので、Ball

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

クラスを用いない ball_02.pde

// 定数
final int X  = 0;
final int Y  = 1;
final int VX = 2;
final int VY = 3;
final float vx0min = -7;            // vxの初期値の下限
final float vx0max = 5;             // vxの初期値の上限
final float vy0min = 4;             // vyの初期値の下限
final float vy0max = 15;            // 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;         // 色相の最大値

// 変数
float[] ball0;                      // ボールの x, y, vx, vy を要素とする配列を参照する変数

void setup() {
  frameRate(fps);
  size(480, 480);
  noStroke();
  colorMode(HSB, hueMax, 100, 100);
  fill(0, 0, 0);
  ball0 = new float[4];                         // ボールの x, y, vx, vy を要素とする配列
  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成分
}

クラスを用いると、定数 X, Y, VX, VY は不要になる。

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

クラスを用いない ball_02.pde

void draw() {
  background(0, 0, 100);
  boundBall(ball0);
  fill(calcHue(ball0[VX], ball0[VY]), 100, 100);
  ellipse(ball0[X], ball0[Y], d, d);
}

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

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

クラスを用いない ball_02.pde

void boundBall(float[] 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;
  }
}

演習問題: 問題3

第7週の問題2 で、 ボールにマウスカーソルを持って行くと、ボールの動きを止めることができるようにした。 マウスカーソルをボールから離せば、再び元の速度で動き始めるものとした(ballCatchable.pde)。

これを Ball クラスを使うように書き換えなさい。

提出ファイル名: ballCatchable_oo1.pde

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

ボールを止める = 関数 boundBall() を呼び出さない

void draw() {
  background(0, 0, 100);
  float h;                                                       // ボールの色相
  if(isNeighbor(ball0[X], ball0[Y], mouseX, mouseY, d / 2)) {    // マウスカーソルの位置がボールの内部なら
    h = 0;
  }
  else {
    h = 180.0;
    boundBall(ball0);
  }
  fill(h, 100, 100);
  ellipse(ball0[X], ball0[Y], d, d);
}

/**
 *  点1(x1, y1)、点2(x2, y2) の距離が distance より近いかを調べる
 *  @param x1 点1のx座標
 *  @param y1 点1のy座標
 *  @param x2 点2のx座標
 *  @param y2 点2のy座標
 *  @return 点1(x1, y1)、点2(x2, y2) の距離が distance より近いか否か
 */
boolean isNeighbor(float x1, float y1, float x2, float y2, float distance) {
  float dx = x1 - x2;
  float dy = y1 - y2;
  return dx * dx + dy * dy < distance * distance;
}

演習問題: 問題4

問題3 を変更し、ボールにマウスカーソルを持って行くと、 ボールの動きが止まるだけでなく、ボールの色相が変化するようにしなさい。 マウスカーソルをボールから離すと、再び元の速度で動き始めるものとする。 また、動いているときの色相はカーソルを離した時点での色相を保持するものとする。

Ball クラスの属性(フィールド)として、色相の値を持つようにしなさい。

提出ファイル名: ballCatchable_oo2.pde

演習問題: 問題5 (Advanced)

第6週の問題7で、複数(例えば6個)のボールの初期位置と初期速度が入った 2次元配列 balls を用意した。 さらに、それぞれのボールを boundBall(balls[i]) で動作させるようにした (balls_01.pde)。

これを Ball クラスの一次元配列を使うように書き換えなさい。

提出ファイル名: balls_01_oo1.pde

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

演習問題: 問題6 (Advanced)

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

これを、物体ごとにクラスを定義し、それを利用するように書き換えなさい。

提出ファイル名: ObjectsAndMouseCursor_oo1.pde

なお、第7週の問題4とは異なる物体・動きにしてもよい。