yoppa.org


人工言語入門 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

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

[code language=”java”]
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);
}
}
[/code]

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

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

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

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

[code language=”java”]
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);
}
}
[/code]

  • 完成した動き

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

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

  • 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();

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

[code language=”java”]
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();
}
}
[/code]

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

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

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

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

[code language=”java”]
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();
}
}
[/code]

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

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

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

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

[code language=”java”]
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();
}
}
[/code]

  • 色を指定したバージョン

Processing のオブジェクト指向プログラミング(Object-oriented programming) | Music Theory Workshop Japan — 14 March 2016 19:27
[…] // Example: Two Car objects Car myCar1; Car myCar2; // myCar1とmyCar2という2つのオブジェクト型変名を作る void setup() { size(200,200); // Parameters go inside the parentheses when the object is constructed. // myCar1 というオブジェクト型変名に、new Car()で今作るオブジェクトを参照させる。 // この中身の機能・設定は、クラスのプロパティ・コンストラクタ・メソッドで設定する。 myCar1 = new Car(color(255,0,0),0,100,2); myCar2 = new Car(color(0,0,255),0,10,1); } void draw() { background(255); myCar1.drive();// drive()というファンクションを発動。(メソッドをコールする) myCar1.display(); myCar2.drive(); myCar2.display(); } // 「Car」というクラス(集合)を設定していくフェイズ class Car {//「Car」というクラスを作ります color c; //カラー型のCという名前の変数を「Car」集合の中に作ります = 〜というプロパティ(属性)を持ちます float xpos; //フロート型のxposという名前の変数を「Car」集合の中に作ります = 〜というプロパティ(属性)を持ちます float ypos; float xspeed; // コンストラクタの設定 // コンストラクタとは[myCar1 = new Car(color(255,0,0),0,100,2);]等とコードを書いてオブジェクトを // 新しく作成したときに、同時にオブジェクトのプロパティの値を設定することができる機能。 Car(color tempC, float tempXpos, float tempYpos, float tempXspeed) { c = tempC; //Carクラスが持つcプロパティに、引数tempCを入れた状態で、オブジェクトを作成する。 xpos = tempXpos; //Carクラスが持つxposプロパティに、引数tempXposを入れた状態で、オブジェクトを作成する。 ypos = tempYpos; //正確に書くなら、this.xposと表すこともできる。 xspeed = tempXspeed; } void display() { 集合Carにdisplay()というfunction(機能)を持たせる。〜というmethodを持たせる。 stroke(0); fill(c); rectMode(CENTER); rect(xpos,ypos,20,10); //xposは集合Carのプロパティにあるので、それを使うことになる。正確に書くなら、this.xposと //ともできる。 } void drive() { xpos = xpos + xspeed; if (xpos > width) { xpos = 0; } } } クラス継承 http://yoppa.org/proga10/1239.html […]
links for 2010-06-11 » HTML5 - — 12 June 2010 04:03
[...] Processingでオブジェクト指向プログラミング (2) | yoppa org (tags: processing) [...]