コンピュータプログラミングII (10)

モノをひとまとまりとして捉える (3)

このスライドの使い方

テキスト等がはみ出した場合は、フォントサイズを小さくして調整する。 「S」 キーで小さく、「B」 キーで大きくなる。また、 下記のキーボード操作が使用できる。(一部キー操作は IE のみ対応)

「←」 or 「Page Up」 前のスライドに戻る
「→」 or 「Page Down」 or「スペース」 次のスライドに進む
「Home」 and 「End」 先頭(Home)または最後(End)のスライドへ移動
「C」 or 「contents?」 をクリック スライド一覧の表示
「F11」 or 「Ctrl+Shift+F (Win)」, 「Cmd+Shift+F (Mac)」 フルスクリーン表示と通常表示の切り替え
「F」 フッタの表示と非表示の切り替え
「A」 全スライド表示に切替 (印刷時に使う)
「S」「-」/「B」「+」 フォントサイズの大(B) 小(S)

本日のゴール

復習: 変数の型

基本型
  • 整数: int, long, short, ...
  • 実数: float, double
  • 真偽値: boolean
参照型
  • 配列: int[], float[], Ball[], ...
  • クラス
    • あらかじめ定義されているもの: String, PImage, ...
    • 自分で定義するもの: Ball, Circle, ...

基本型 boolean [復習]

boolean型 (論理型)
真偽値を表す型。true(真)、false(偽)、の2値のどちらかの値を持つ。
boolean isNormal = false;     // true, false は boolean 型の定数
boolean isOtaku = true;

boolean xGTy = x > y;                          // 論理演算の結果は boolean型の値

if, while, for などの条件式で、論理演算子とともによく使われる。

if(isOtaku) {           // isOtaku の値が true なら条件を満たす
  println("君とは友だちになれそうだ");   // テキストエリアに引数の文字列と改行を表示
}

関数 println は引数の文字列と改行を表示。 関数 print は改行しない。

基本型 boolean : システム変数 [復習]

前後期「プログラミング入門」第3回の例

if (mousePressed) {
  マウスのボタンが押されているときの処理
}
else {
  マウスのボタンが押されていないときの処理
}

基本型 boolean : 引数・戻り値 [復習]

もちろん、メソッド/関数の引数や戻り値の型にも使える。

boolean isEven(int i) {    // 引数で受け取った値が偶数だったら true を返す
  boolean result;
  if(i % 2 == 0) {
    result = true;
  }
  else {
    result = false;
  }
  return result;
}

この場合、if で判定している条件式の値をそのまま返せばよい。

boolean isEven(int i) {    // 引数で受け取った値が偶数だったら true を返す
  return i % 2 == 0;
}

例: boolean型の値を返す関数 [復習]

点(x1, y1) と 点(x2, y2) の距離が d 以下であるかを判定する関数。

boolean isNeighbor(float x1, float y1, float x2, float y2, float d) {
  float dx = x1 - x2;
  float dy = y1 - y2;
  return dx * dx + dy * dy <= d * d;
}


// 使い方

if(isNeighbor(x1, y1, x2, y2, d)) {

  // 距離が d 以下だった場合の処理

}

フラグとしての利用 [復習]

boolean 型の変数は、状態を記憶しておくフラグ(flag; 旗)として利用されることが多い。

配列 a の全要素を順に表示しつつ、閾値 th よりも大きな値の要素があるかチェック。

boolean found = false;     // 初期値は旗が立っていない状態

for(int i = 0; i < a.length; i++) {
  println(a[i]);
  if(a[i] > th) {
    found = true;          // th より大きい値が見つかったので旗を立てておく
  }    
}

if(found) {                // 旗が立っているかチェック
  println("閾値より大きい要素がありました。");
}

練習: スタンプ

マウスをクリックするとスタンプが押されるというアニメーションを作成しなさい。 クラス Stamp を定義し、マウスカーソルに追随して動くインスタンスと、 ボタンがクリックされた時のみ移動するインスタンスを用意するとよい。

ファイル名: stamp.pde

基本型 char

char型 (文字型)
文字1文字を表す型。
char c1 = 'T';     // 'T' は文字定数

void printChar(char c) {
  print(c);
}

通常は文字列を使うので、char の使用機会は少ない。

クラス String

class String (String型)
文字列定数を表すクラス。文字列とは文字の連続のこと。
ただし、char型の文字が並んでいるのではなく、文字列全体で1つオブジェクト。

オブジェクトの作り方

特例として、new 演算子を使わずにオブジェクトをつくることができる。

String s1 = "This is a pen.";       // "" は文字列定数を表す
String s2 = s1 + " It's yours.";    // 演算子 + は前後の文字列を連結して新たなオブジェクトを生成

メソッド

String s1 = "This is a pen.";
println("文字数: " + s1.length());    // s1.length() は s1 の文字列の長さ(文字数)を返す

例: 3つのネオンサイン

例: 3つのネオンサイン

class NeonSign {
  String text;
  final float x = random(0, 150);
  final float y = random(150, 400);
  final float size = random(15, 150);
  final float dH = 1;
  float h = random(0, 360);
  void setText(String text) {
    this.text = text;
  }
  void draw() {
    textSize(size);
    fill(h, 100, 100);
    text(text, x, y);
    h += dH;
    if(h > 360) {
      h -= 360;
    }
  }  
}

例: 3つのネオンサイン

final int fps = 60;          // フレーム数/秒
NeonSign sign1;
NeonSign sign2;
NeonSign sign3;

void setup () {
  size(480, 480);
  frameRate(fps);
  noStroke();
  colorMode(HSB, 360, 100, 100);
  sign1 = new NeonSign();
  sign1.setText("hi,");
  sign2 = new NeonSign();
  sign2.setText("how are");
  sign3 = new NeonSign();
  sign3.setText("you?");
}

void draw() {
    background(0, 0, 100);
    sign1.draw();
    sign2.draw();
    sign3.draw();
}

復習: ボールを斜めに落とした時の動き [前回の問題2 解答例]

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

Ball クラスに move と draw のメソッドを実装しなさい (前回の問題2 ball_02_oo3.pde)。

復習: ボールを斜めに落とした時の動き (属性の決定)

/** 動くボールを表す */
class Ball {
  final float gravity = 9.8 / fps;    // 1フレームあたりの重力加速度
  final float elas = 0.98;            // 反発係数
  float d;                            // ボールの直径
  float x;                            // 中心のx座標
  float y;                            // 中心のy座標
  float vx;                           // 速度のx成分
  float vy;                           // 速度のy成分
}

復習: ボールを斜めに落とした時の動き (アクセサメソッドの用意)

  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;
  }

復習: ボールを斜めに落とした時の動き (メソッドの用意)

1フレーム分動かす

床と左右の壁で速度を反転させる。

  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;
    } else if (y < d / 2) {
      vy = - vy * elas;
      y = d / 2;
    }
  }

復習: ボールを斜めに落とした時の動き (メソッドの用意)

図形として描画する

速度で色相を変化させる例。

  void draw() {
    fill(calcHue(vx, vy), 100, 100);
    ellipse(x, y, d, d);
  }
  float calcHue(float vx, float vy) {
    return (sqrt(vx * vx + vy * vy) * 16) % hueMax;
  }

復習: ボールを斜めに落とした時の動き (グローバル変数/関数)

// 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();
}

Ball 型の変数をグローバル変数として用意し、関数 setup の中でオブジェクト生成・初期化