yoppa.org


immediate bitwave

人工言語入門 A 2010

Processingでオブジェクト指向プログラミング (2)

Processingでオブジェクト指向プログラミング (2)

前回の復習

  • オブジェクト指向プログラミング (= OOP)のポイント

オブジェクト指向プログラムのポイント:その1

  • 「もの (= オブジェクト)」という単位でプログラムを構成する
  • オブジェクトは、プロパティー(性質)とメソッド(動作・ふるまい)から構成

オブジェクト指向プログラムのポイント:その2

  • オブジェクト同士がメッセージを送りあう

オブジェクト指向プログラムのポイント:その3

  • オブジェクトはメッセージを受け取り、それに応じた処理を行う
  • メッセージの処理方法は、オブジェクト自身が知っていて、その処理はオブジェクトによって異なる (ポリモーフィズム)

オブジェクト指向プログラムのポイント:その4

  • 必要のない情報は隠す (カプセル化)
  • プログラムの実装全てを知る必要はない
  • 必要なインターフェイス(接点)だけ見せて、あとは隠す

オブジェクト指向プログラムのポイント:その5

  • オブジェクトから新たなオブジェクトを派生させることができる (継承)

オブジェクト指向プログラムのポイント:その6

  • クラスとは:オブジェクトの「型紙」
  • クラスをインスタンス化 (実体化) することでインスタンス(オブジェクト)となる

先週の内容の確認

  • 円を描くクラス Spot を作成
  • クラスを宣言、クラスをインスタンス化
  • 円のプロパティを定義 – x, y, diameter
  • 円を描画するメソッドを定義 – display()
  • コンストラクタを定義 – Spot(float x, float y, float diameter)
  • 動きを追加する – move();
  • 複数のインスタンスの生成 – sp1, sp2, sp3 …
  • インスタンスの配列を生成 – Spot[] spots

  • 今日の授業は先週のつづきから始めます
  • 先週の最終的なプログラムをダウンロード
int numSpots = 400;

Spot[] spots = new Spot[numSpots];

void setup() {
  size(800, 600);
  noStroke();
  smooth();
  frameRate(60);
  for (int i = 0; i < spots.length; i++) {
    spots[i] = new Spot(random(0,width), height/2, random(5,40), random(-4,4));
  }
  background(0);
}

void draw() {
  fill(0,0,0,10);
  rect(0, 0, width, height);
  fill(255);
  for (int i = 0; i < spots.length; i++) {
    spots[i].move();
    spots[i].display();
  }
}

class Spot {
  float x, y; 
  float diameter;
  float speed;

  //コンストラクター
  Spot(float _x, float _y, float _diameter, float _speed) {
    x = _x;
    y = _y;
    diameter = _diameter;
    speed = _speed;
  }

  void move() {
    y += speed;
    if ((y > (height - diameter / 2)) || (y < diameter / 2)) {
      speed *= -1;
    }
  }

  void display() {
    fill(31,127,255,63);
    ellipse(x, y, diameter, diameter);
  }
}

より複雑な動きを作成する

  • Spotクラスの再設計
  • 円は上下だけでなく、左右にも移動するように変更

  • Spotクラスの再設計
  • 必要となる属性
    • x座標、y座標 → float x, y;
    • x方向の速度、y方向の速度 → float vx, vy;
    • 大きさ → float diameter
  • 必要となるメソッド
    • コンストラクタ → Spot
    • 座標の更新 → update
    • 画面に表示 → display
  • Spotクラス、クラス図を作成

– 設計したクラスをもとにプログラムを作成

int numSpots = 400;

Spot[] spots = new Spot[numSpots];

void setup() {
  size(800, 600);
  noStroke();
  smooth();
  frameRate(60);
  for (int i = 0; i < spots.length; i++) {
    color col = color(random(255),random(255),random(255),63);
    spots[i] = new Spot(random(0,width), height/2, random(5,40), random(-4,4),col);
  }
  background(0);
}

void draw() {
  fill(0,0,0,10);
  rect(0, 0, width, height);
  fill(255);
  for (int i = 0; i < spots.length; i++) {
    spots[i].move();
    spots[i].display();
  }
}

class Spot {
  float x, y; 
  float diameter;
  float speed;
  color col;

  Spot(float _x, float _y, float _diameter, float _speed, color _col) {
    x = _x;
    y = _y;
    diameter = _diameter;
    speed = _speed;
    col = _col;
  }

  void move() {
    y += speed;
    if ((y > (height - diameter / 2)) || (y < diameter / 2)) {
      speed *= -1;
    }
  }

  void display() {
    fill(col);
    ellipse(x, y, diameter, diameter);
  }
}
  • 完成した動き

クラスの継承:重力を付加

  • さらにリアルな動きを追求してみる
  • 重力の概念を適用してみる
  • 移動中は、常に重力の影響を受けつづける

  • Spotクラスはそのままで、継承を使用してクラスを拡張する
  • 親クラスの性質を引き継いで、別の性質を付加した子クラスを生成
  • Spotクラス (親クラス)
    • 上下左右に移動する円
    • 画面の端でバウンドする
  • GravitySpot (子クラス)
    • Spotクラスを継承
    • つねに一定の重力の影響を受け続ける – 重力 → float gravity
  • クラスを継承する際の、クラス定義のやりかた
    • 何のクラスを継承したかを記述する
    • class 子クラス extends 親クラス {….}
    • 例:GravitySpotクラスが、Spotクラスを継承する場合
      • class GravitySpot extends Spot {…}
  • 子クラスから、親クラスのコンストラクタを呼びだす方法
    • super(引数1, 引数2, 引数3…);
    • 例:GravitySpotからSpotのコンストラクタを設定
      • super(_x, _y, _vx, _vy, _diameter);
  • 子クラスから親クラスのメソッドを呼び出す
    • super.メソッド名(引数1, 引数2, 引数3…);
    • 例:GravitySpotからSpotのmove()を呼び出す
      • super.move();

  • 設計したクラスをもとにプログラムを作成
int numSpots = 400;

GravitySpot[] spots = new GravitySpot[numSpots];

void setup() {
  size(800, 600);
  noStroke();
  smooth();
  frameRate(60);
  for (int i = 0; i < spots.length; i++) {
    spots[i] = new GravitySpot(width/2,height/4,random(-4,4),random(-4,4),random(2,20));
  }
  background(0);
}

void draw() {
  fill(0,0,0,10);
  rect(0, 0, width, height);
  fill(51,127,255,63);
  for (int i = 0; i < spots.length; i++) {
    spots[i].move();
    spots[i].display();
  }
}

class Spot {
  float x, y; 
  float diameter;
  float vx;
  float vy;

  Spot(float _x, float _y, float _vx, float _vy, float _diameter) {
    x = _x;
    y = _y;
    vx = _vx;
    vy = _vy;
    diameter = _diameter;
  }

  void move() {
    x += vx;
    if ((x > (width - diameter / 2)) || (x < diameter / 2)) {
      vx *= -1;
    }
    x = constrain(x, diameter/2, width - diameter/2);
    
    y += vy;
    if ((y > (height - diameter / 2)) || (y < diameter / 2)) {
      vy *= -1;
    }
    y = constrain(y, diameter/2, height - diameter/2);
    
  }

  void display() {
    ellipse(x, y, diameter, diameter);
  }
}

class GravitySpot extends Spot{
  float gravity = 0.1;
  GravitySpot(float _x, float _y, float _vx, float _vy, float _diameter){
    super(_x, _y, _vx, _vy, _diameter);
  }
  
  void move(){
    vy += gravity;
    super.move();
  }
  
  void display(){
    super.display();
  }
}

クラスの継承2:摩擦力を付加

  • 重力の概念に加えて、摩擦力の概念を加える
    • 摩擦 → 移動方向と反対方向にかかる力、空気抵抗など
    • 移動中は、重力に加えて常に摩擦力が働くようにする

  • 改良版、GravitySpot
    • 重力 (gravity) に加えて、摩擦力 (friction) を付加
    • x, y方向のスピードそれぞれに一定の値をかけ算する
    • frictoin ≦ 1.0;
    • frictionが1.0のときは摩擦なし
    • 値が小さくなるほど、大きな摩擦力が働く
  • 摩擦(friction)をGravitySpotのプロパティに追加

  • 設計したクラスをもとにプログラムを作成
int numSpots = 400;

GravitySpot[] spots = new GravitySpot[numSpots];

void setup() {
  size(800, 600);
  noStroke();
  smooth();
  frameRate(60);
  for (int i = 0; i < spots.length; i++) {
    spots[i] = new GravitySpot(width/2,height/4,random(-20,20),random(-20,20),random(2,20));
  }
  background(0);
}

void draw() {
  fill(0,0,0,10);
  rect(0, 0, width, height);
  fill(51,127,255,63);
  for (int i = 0; i < spots.length; i++) {
    spots[i].move();
    spots[i].display();
  }
}

class Spot {
  float x, y; 
  float diameter;
  float vx;
  float vy;

  //コンストラクター
  Spot(float _x, float _y, float _vx, float _vy, float _diameter) {
    x = _x;
    y = _y;
    vx = _vx;
    vy = _vy;
    diameter = _diameter;
  }

  void move() {
    x += vx;
    if ((x > (width - diameter / 2)) || (x < diameter / 2)) {
      vx *= -1;
    }
    x = constrain(x, diameter/2, width - diameter/2);
    
    y += vy;
    if ((y > (height - diameter / 2)) || (y < diameter / 2)) {
      vy *= -1;
    }
    y = constrain(y, diameter/2, height - diameter/2);
    
  }
  void display() {
    ellipse(x, y, diameter, diameter);
  }
}

class GravitySpot extends Spot{
  float gravity = 0.1;
  float friction = 0.995;
  GravitySpot(float _x, float _y, float _vx, float _vy, float _diameter){
    super(_x, _y, _vx, _vy, _diameter);
  }
  
  void move(){
    vy += gravity;
    vx *= friction;
    vy *= friction;
    super.move();
  }
  
  void display(){
    super.display();
  }
}

重力と摩擦力を付加した動き (摩擦力 = 0.995)

クラスの継承3:色を指定

  • さらに色を指定できるようにする
  • GravitySpotのプロパティーに色の情報を追加 → color col

  • 設計したクラスをもとにプログラムを作成
int numSpots = 400;
GravitySpot[] spots = new GravitySpot[numSpots];

void setup() {
  size(800, 600);
  colorMode(HSB, 360, 100, 100, 100);
  noStroke();
  smooth();
  frameRate(60);
  for (int i = 0; i < spots.length; i++) {
    color col = color(random(120,240),80,80,50);
    spots[i] = new GravitySpot(width/2,height/4,random(-10,10),random(-10,0),random(2,20),col);
  }
  background(0);
}

void draw() {
  fill(0,0,0,10);
  rect(0, 0, width, height);
  fill(51,127,255,63);
  for (int i = 0; i < spots.length; i++) {
    spots[i].move();
    spots[i].display();
  }
}

class Spot {
  float x, y; 
  float diameter;
  float vx;
  float vy;

  Spot(float _x, float _y, float _vx, float _vy, float _diameter) {
    x = _x;
    y = _y;
    vx = _vx;
    vy = _vy;
    diameter = _diameter;
  }

  void move() {
    x += vx;
    if ((x > (width - diameter / 2)) || (x < diameter / 2)) {
      vx *= -1;
    }
    x = constrain(x, diameter/2, width - diameter/2);
    
    y += vy;
    if ((y > (height - diameter / 2))) {
      vy *= -1;
    }
    y = constrain(y, -height, height - diameter/2);
    
  }
  void display() {
    ellipse(x, y, diameter, diameter);
  }
}

class GravitySpot extends Spot{
  float gravity = 0.1;
  float friction = 0.998;
  color col;
  GravitySpot(float _x, float _y, float _vx, float _vy, float _diameter, color _col){
    super(_x, _y, _vx, _vy, _diameter);
    col = _col;
  }
  
  void move(){
    vy += gravity;
    vx *= friction;
    vy *= friction;
    super.move();
  }
  
  void display(){
    fill(col);
    super.display();
  }
}
  • 色を指定したバージョン