人工言語入門 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]
- 色を指定したバージョン