bnn camp vol.3 ...

153
BNN CAMP vol.3  インタラクションデザインの現在 プログラミング初心者のための openFrameworks入門 - 2: 構造をつくる 2013年8月3日 田所 淳

Upload: atsushi-tadokoro

Post on 24-May-2015

3.785 views

Category:

Documents


9 download

TRANSCRIPT

Page 1: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

BNN CAMP vol.3 インタラクションデザインの現在プログラミング初心者のためのopenFrameworks入門 - 2: 構造をつくる

2013年8月3日田所 淳

Page 2: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

このセクションの内容‣ 構造をもったより複雑なプログラムへ!

‣ 関数‣ クラス - オブジェクト指向プログラミング‣ くりかえしと配列‣ パーティクルシステムをつくる‣ ベクターフィールド

Page 3: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

処理をまとめるサブルーチン ( = 関数)

Page 4: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

サブルーチン (= 関数) とは‣ プログラム中で意味や内容がまとまっている作業をひとつの手続きとしたもの

‣ openFrameworks (つまり C++) では、サブルーチンのことを「関数 (function)」と呼ぶのが一般的

‣ 関数を使用する利点‣ 繰り返し現れる作業をまとめることができる‣ プログラムの可読性の向上‣ 保守性を高く保つ

Page 5: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数:引数と返り値‣ 関数への入出力‣ 引数 (ひきすう, argument) - 関数に渡す値‣ 返り値 (return value) - 関数が返す値

関数

引数1 引数2 引数3

戻り値

Page 6: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

C++ での関数の書きかた‣ C++での関数の書き方

‣ 例えば、int型の数の二乗を計算する関数

‣ もし戻り値がない関数の場合、戻り値の型は「void」にする

戻り値の型 名前空間::関数名(引数1, 引数2, 引数3...){ 関数の処理の内容}

int testApp::poweroftwo(int a){! return a * a;}

Page 7: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ 2つの地点を直線移動する座標を計算する関数をつくってみる‣ 現在の位置は、終了点を1とした割合(0.0~1.0)で表現

startPos(0.0)

currentPos(0.0~1.0の間)

endPos(1.0)

Page 8: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ 開始点(startPos)と終了点(endPos)をまず決める

startPos(0.0)

endPos(1.0)

Page 9: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ 経過した地点の割合 pct (0.0~1.0)を与えると、現在の地点の座標を計算して返す

startPos(0.0)

endPos(1.0)0.2

Page 10: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ 経過した地点の割合 pct (0.0~1.0)を与えると、現在の地点の座標を計算して返す

startPos(0.0)

endPos(1.0)

0.5

Page 11: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ 経過した地点の割合 pct (0.0~1.0)を与えると、現在の地点の座標を計算して返す

startPos(0.0)

endPos(1.0)

0.8

Page 12: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

補足:ofPointで座標を指定する‣ これ以降、座標の点を表現する際には、X座標、Y座標ではなくそれをまとめた、ofPoint() を使用する

‣ X, Y座標をまとめて1つの変数で扱うことのできるもの(クラス)

posx y

Page 13: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

補足:ofPointで座標を指定する‣ ofPointは、[変数名].x [変数名].y と指定しすることで複数の座標を一括して管理できる

‣ 例:(10.0, 20.0)の座標を表現する場合

float x;float y;

x = 10.0;y = 20.0

複数のfloat型

ofPoint pos;pos.x = 10.0;pos.y = 20.0;

ofPoint型

Page 14: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ 関数をつかって、定義してみる‣ 関数名:interpolateByPct

‣ 引数 :‣ float pct → 現在の二点間を補完する際の割合(0.0 ~ 1.0)

‣ 返り値 :‣ ofPoint pos → 割合から算出された座標

ofPoint interpolateByPct(float pct);

Page 15: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ 関数をtestAppに追加する場合‣ まずヘッダファイル(レシピ!)に、関数の概要を追加する‣ 料理の手順を工程表に追加するイメージ‣ 同時に必要となる変数 (材料) も全て追加しておく

ヘッダファイル = レシピ

interpolateByPct()

ofPoint startPos;ofPoint endPos;ofPoint currentPos;float pct;

Page 16: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ testApp.h に関数(手順)と変数(材料)を追加#pragma once#include "ofMain.h"

class testApp : public ofBaseApp{!public:! void setup();! void update();! void draw();

...《中略》...!! ofPoint interpolateByPct(float pct);!! ofPoint startPos;! ofPoint endPos;! ofPoint currentPos;! float pct;!};

追加

Page 17: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ 実装ファイルに手順を記述‣ testApp.cppに、testApp::interpolateByPct() { ... } というブロックを用意して処理内容を全て書いていく

interpolateByPct( )

位置を割合で指定すると現在の位置の座標を返す

Page 18: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ testApp.cpp に関数(手順)の内容を記述#include "testApp.h"

//--------------------------------------------------------------void testApp::setup(){! ofBackground(0, 0, 0);! ofSetFrameRate(60);! ofSetVerticalSync(true);}

《中略》...//--------------------------------------------------------------ofPoint testApp::interpolateByPct(float _pct){!! ofPoint pos;! pos.x = (1.0 - _pct) * startPos.x + (_pct) * endPos.x;! pos.y = (1.0 - _pct) * startPos.y + (_pct) * endPos.y;!! return pos;!}

追加

Page 19: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ 実際に座標を計算してみる‣ 2段階の手順が必要

‣ setup() でまず開始位置と終了位置を決定

‣ update() で割合(pct)を継続して入力すると、現在の位置を計算して返す

startPosendPos

interpolateByPct( )pct currentPos

interpolateByPct( )

Page 20: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ testApp.cpp に処理を追加#include "testApp.h"

//--------------------------------------------------------------void testApp::setup(){

! ofBackground(0, 0, 0);! ofSetFrameRate(60);! ofSetVerticalSync(true);

! startPos = ofPoint(10, 100);! endPos = ofPoint(1000, 600);! pct = 0;

}

//--------------------------------------------------------------void testApp::update(){

! pct = pct + 0.01;! currentPos = interpolateByPct(pct);

}

追加

追加

Page 21: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ testApp.cpp に処理を追加//--------------------------------------------------------------void testApp::draw(){

! ofSetColor(31, 127, 255);! ofCircle(currentPos.x, currentPos.y, 20);

}

//--------------------------------------------------------------ofPoint testApp::interpolateByPct(float _pct){!! ofPoint pos;! pos.x = (1.0 - _pct) * startPos.x + (_pct) * endPos.x;! pos.y = (1.0 - _pct) * startPos.y + (_pct) * endPos.y;!! return pos;!}

追加

Page 22: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ 実行結果:設定した座標間を直線運動する

Page 23: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ もう少し工夫‣ 0.0から1.0に到達したら、また0.0に戻る(リセット)するように‣ 条件をつかえば簡単に実現可能‣ 「もし、pct の値が1.0を越えたら、0.0に戻れ」

‣ 「もし○○なら、××せよ」→ if分を用いる

Page 24: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ 選択 - 何らかの条件が成立したとき文の並びを実行する‣ 「もし○○なら××せよ、そうでなければ△△せよ」

処理 A 処理 B

条件?

Yes

No

Page 25: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ if~else文を使うif (【条件式】) { 【条件式が正しい時の処理 (真文)】} else { 【条件式が正しくない時の処理 (偽文)】}

Page 26: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ testApp.cpp - update() に処理を追加//--------------------------------------------------------------void testApp::update(){! pct = pct + 0.01;!! if (pct > 1.0) {! ! pct = 0.0;! }!! currentPos = interpolateByPct(pct);}

追加

Page 27: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

関数によるアニメーション:補完‣ 実行結果:動きがループするようになったはず!

Page 28: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

高度な補完:加速と減速‣ 補完の動きに、表情をつける‣ %による補完を、単純な加算ではなく、指数で指定してみる‣ 指数の値によって、時間と距離の曲線はどうなるか?

‣ OSX付属のGrapher.appをつかって、確かめてみる

Page 29: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

高度な補完:加速と減速y = x

Page 30: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

高度な補完:加速と減速y = x^2

Page 31: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

高度な補完:加速と減速y = x^0.5

Page 32: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

高度な補完:加速と減速‣ C++で指数計算をするには、powerf() 関数を使用する‣ 例:10の2乗

‣ interpolateByPct 関数に、引数 shaper を追加‣ pctを、shaperで指定した指数で乗算していく

powf(10.0, 2.0);

ofPoint testApp::interpolateByPct(float _pct, float _shaper){! ofPoint pos;! float shapedPct = powf(_pct, _shaper);

! pos.x = (1.0 - shapedPct) * startPos.x + shapedPct * endPos.x;! pos.y = (1.0 - shapedPct) * startPos.y + shapedPct * endPos.y;

! return pos;}

Page 33: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

高度な補完:加速と減速‣ testApp.h :追加と修正#pragma once#include "ofMain.h"

class testApp : public ofBaseApp{!public:! void setup();! void update();! void draw();

...《中略》...

! ofPoint interpolateByPct(float pct, float shaper);!! ofPoint startPos;! ofPoint endPos;! ofPoint currentPos;! float pct;! float shaper;!};

修正

追加

Page 34: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

高度な補完:加速と減速‣ testApp.cpp:追加と修正#include "testApp.h"

//--------------------------------------------------------------void testApp::setup(){! ofBackground(0, 0, 0);! ofSetFrameRate(60);! ofSetVerticalSync(true);

! startPos = ofPoint(10, 100);! endPos = ofPoint(1000, 600);! pct = 0;! shaper = 2.0;}

//--------------------------------------------------------------void testApp::update(){! pct = pct + 0.01;! if (pct > 1.0) {! ! pct = 0.0;! }! currentPos = interpolateByPct(pct, shaper);}

修正

追加

Page 35: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

高度な補完:加速と減速‣ testApp.cpp:追加と修正//--------------------------------------------------------------ofPoint testApp::interpolateByPct(float _pct, float _shaper){!! ofPoint pos;! float shapedPct = powf(_pct, _shaper);!! pos.x = (1.0 - shapedPct) * startPos.x + shapedPct * endPos.x;! pos.y = (1.0 - shapedPct) * startPos.y + shapedPct * endPos.y;!! return pos;!}

修正

Page 36: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

高度な補完:加速と減速‣ 実行結果

Page 37: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

高度な補完:加速と減速‣ shaperの値をいろいろ変化させて、動きを観察してみる

shaper = 4.0 shaper = 0.5

Page 38: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

オブジェクト指向プログラミング

Page 39: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ オブジェクト指向プログラミング

‣ Object Oriented Programming (OOP)‣ オブジェクト指向でProcessingのプログラムを作る‣ そもそもオブジェクト指向とは?

‣ 簡単なプログラムを、オブジェクト指向で書いてみる‣ クラスの定義‣ クラスの呼びだし

オブジェクト指向プログラミングとは?

Page 40: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ オブジェクト指向プログラミング言語のイメージ

プログラミング・パラダイムの変遷

オブジェクト

オブジェクト

オブジェクト

オブジェクト

Page 41: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ OOPの特徴

‣ 相互にメッセージを送り合う「オブジェクト」の集まりとしてプログラムを構成

‣ オブジェクトは、プロパティとメソッドから構成される‣ カプセル化 - 必要のない情報は隠す‣ インヘリタンス(継承) - あるオブジェクトが他のオブジェクトの特性を引き継ぐ

‣ ポリモーフィズム(多態性・多様性) - プログラミング言語の各要素が複数の型に属することを許す

オブジェクト指向プログラミングの概念

Page 42: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ オブジェクト‣ プロパティとメソッド‣ カプセル化‣ 継承 (インヘリタンス)‣ 多態性、多相性 (ポリモーフィズム)

OOP、5つのポイント

Page 43: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ オブジェクト指向プログラムのポイント:その1‣ オブジェクトの集まりとしてプログラムを構成‣ オブジェクト同士がメッセージを送りあう

OOP:ポイントその1

Page 44: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ オブジェクト指向プログラムのポイント:その2‣ オブジェクトは、プロパティ(性質、状態)と、メソッド(動作、ふるまい) から構成される

状態1状態2状態3

オブジェクト

メソッド1 メソッド2

メソッド3メソッド4

OOP:ポイントその2

Page 45: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ 例:「りんご」をオブジェクトとして考える

赤5.0甘い

ふじ

実がなる

成長する

落ちる腐る

青4.0

すっぱい

青リンゴ実がなる

成長する

落ちる腐る

OOP:ポイントその2

Page 46: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ オブジェクト指向プログラムのポイント:その3‣ 必要のない情報は隠す (カプセル化)‣ プログラムの実装全てを知る必要はない‣ 必要なインターフェイス(接点)だけ見せて、あとは隠す

It’s this resemblance to real things that gives objects much of their power and appeal. They can notonly model components of real systems, but equally as well fulfill assigned roles as components insoftware systems.

Interface and Implementation

To invent programs, you need to be able to capture abstractions and express them in the programdesign. It’s the job of a programming language to help you do this. The language should facilitate theprocess of invention and design by letting you encode abstractions that reveal the way things work.It should let you make your ideas concrete in the code you write. Surface details shouldn’t obscurethe architecture of your program.

All programming languages provide devices that help express abstractions. In essence, these devicesare ways of grouping implementation details, hiding them, and giving them, at least to some extent,a common interface—much as a mechanical object separates its interface from its implementation, asillustrated in “Interface and Implementation” .

Figure 2-1 Inte rfa ce a nd Im ple m e nta tion

910

11

87 6

implementationinterface

Looking at such a unit from the inside, as the implementor, you’d be concerned with what it’scomposed of and how it works. Looking at it from the outside, as the user, you’re concerned onlywith what it is and what it does. You can look past the details and think solely in terms of the rolethat the unit plays at a higher level.

The principal units of abstraction in the C language are structures and functions . Both, in differentways, hide elements of the implementation:

� On the data side of the world, C structures group data elements into larger units which can thenbe handled as single entities. While some code must delve inside the structure and manipulatethe fields separately, much of the program can regard it as a single thing—not as a collection ofelements, but as what those elements taken together represent. One structure can include others,so a complex arrangement of information can be built from simpler layers.

14 Inte rfa ce a nd Im ple m e nta tion2007-12-11 | © 2007 Apple Inc. All Rights Reserved.

C H A P T E R 2

O bje ct-O rie nte d P rogra m m ing

インターフェイス 実装

OOP:ポイントその3

Page 47: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ オブジェクト指向プログラムのポイント:その4‣ インヘリタンス(継承)‣ オブジェクトから新たなオブジェクトを派生させる

植物

生物

動物

果物 穀物

りんご

ふじ 紅玉 デリシャス

バナナ マンゴー

OOP:ポイントその4

Page 48: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ オブジェクト指向プログラムのポイント:その5‣ ポリモーイズム(多態性、多様性)‣ オブジェクトはメッセージを受け取りそれに応じた処理を行う‣ メッセージの処理方法は、オブジェクト自身が知っていて、その処理はオブジェクトによって異なる

getName()

オブジェクトA:人間

「田所 淳」

getName()

オブジェクトB:車

「トヨタカローラ」

OOP:ポイントその5

Page 49: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

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

色重さ(g)味

リンゴ(クラス)

実がなる

成長する

落ちる腐る

赤5.0甘い

ふじ(インスタンスオブジェクト)

実がなる

成長する

落ちる腐る

青4.0

すっぱい

青リンゴ(インスタンスオブジェクト)

実がなる

成長する

落ちる腐る

インスタンス化

クラス

Page 50: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ いままで扱ってきた、testApp も一つのクラス‣ メソッド - setup(), update(), draw() ...etc.‣ プロパティ - testApp全体で使用する変数

testAppもクラス

クラス変数

setup() update()

draw()exit()

testApp

Page 51: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ これまでのようにtestAppにどんどん機能を追加すると、様々な弊害が

‣ 可読性の低下、機能ごとに再利用できない、拡張が困難 ..etc.

testApp単体の限界

testApp testApp肥大化

Page 52: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ 機能ごとにオブジェクトを分けてプロジェクトを構成する‣ オブジェクトが相互に連携

testApp単体の限界

testApp

Rectangle

Particle

ControlPanel

Page 53: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

OOP実践編クラスを作る

Page 54: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ 前半にやった、アニメーションする円をクラス化してみる‣ まずは円を表示するところまで

‣ クラス名:MoveCircle

‣ プロパティ (状態、変数):‣ ofPoint startPos : 円の初期位置

‣ メソッド (ふるまい、関数):‣ draw( ) : 円を描く

Page 55: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ こんな図にかく場合も‣ UMLクラス図

+ draw():void

+ currentPos:ofPoint

MoveCircle

Page 56: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ こんな図にかく場合も‣ UMLクラス図

+ draw():void

+ currentPos:ofPoint

MoveCircle

プロパティ (状態)メソッド(ふるまい)

Page 57: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

XCodeプロジェクトにクラスを追加する‣ ファイルのリストの「src」フォルダを右クリック‣ リストから「New File (新規ファイル)」を選択

Page 58: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

XCodeプロジェクトにクラスを追加する‣ Mac OS X > C and C++ > C++ File を選択

Page 59: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

XCodeプロジェクトにクラスを追加する‣ 名前をつけて、「src」フォルダに保存

Page 60: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

XCodeプロジェクトにクラスを追加する‣ 再度、リストから「New File (新規ファイル)」を選択

Page 61: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

XCodeプロジェクトにクラスを追加する‣ Mac OS X > C and C++ > Header File を選択

Page 62: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

XCodeプロジェクトにクラスを追加する‣ 名前をつけて、「src」フォルダに保存

Page 63: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

XCodeプロジェクトにクラスを追加する‣ ファイルリストは以下のようになるはず‣ あとは、それぞれのファイルにコーディングしていく

Page 64: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの記述‣ まずはヘッダーファイル (MoveCircle.h) から‣ レシピの材料と手順の一覧!

‣ 材料 → 状態、性質 → つまり、プロパティ(変数)‣ 手順 → ふるまい、動作 → つまり、メソッド(関数)

‣ そのクラスのプロパティとメソッドを記述‣ 外部から参照するものは、public: 以下に書く

Page 65: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ MoveCircle.h - 円を描く際のレシピ!#pragma once

#include "ofMain.h"

class MoveCircle {!public:!! void draw();

! ofPoint currentPos;!};

Page 66: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ MoveCircle.h - 円を描く際のレシピ!#pragma once

#include "ofMain.h"

class MoveCircle {!public:!! void draw();

! ofPoint currentPos;!};

インクルードガードBuildの際に複数回読みこまれないためのしくみ

Page 67: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ MoveCircle.h - 円を描く際のレシピ!#pragma once

#include "ofMain.h"

class MoveCircle {!public:!! void draw();!! ofPoint currentPos;!};

oFの機能を使うためのライブラリを必ず読み込む

Page 68: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ MoveCircle.h - 円を描く際のレシピ!#pragma once

#include "ofMain.h"

class MoveCircle {!public:!! void draw();!! ofPoint currentPos;!};

クラス名

Page 69: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ MoveCircle.h - 円を描く際のレシピ!#pragma once

#include "ofMain.h"

class MoveCircle {!public:!! void draw();!! ofPoint currentPos;!};

public: 以下は外部に公開される

Page 70: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ MoveCircle.h - 円を描く際のレシピ!#pragma once

#include "ofMain.h"

class MoveCircle {!public:!! void draw();!! ofPoint currentPos;!};

メソッド:draw() - 円を描く

Page 71: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ MoveCircle.h - 円を描く際のレシピ!#pragma once

#include "ofMain.h"

class MoveCircle {!public:!! void draw();!! ofPoint currentPos;!};

プロパティ:currentPos - 初期位置

Page 72: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ MoveCircle.h - 円を描く際のレシピ!#pragma once

#include "ofMain.h"

class MoveCircle {!public:!! void draw();!! ofPoint currentPos;!}; 最後に必ずセミコロンをつける

Page 73: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの記述‣ つぎに実装ファイル(MoveCircle.cpp)を書く‣ 円を描くための全ての手続きを記述していく

‣ 現在は、draw() 関数のみ

Page 74: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの記述‣ MoveCircle.cpp - 円を実際に描く手順#include "MoveCircle.h"

void MoveCircle::draw() {!! ofFill();! ofSetColor(31,127,255);! ofCircle(currentPos.x, currentPos.y, 20,20);!}

必ずヘッダーファイルを読み込む

Page 75: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの記述‣ MoveCircle.cpp - 円を実際に描く手順#include "MoveCircle.h"

void MoveCircle::draw() {!! ofFill();! ofSetColor(31,127,255);! ofCircle(currentPos.x, currentPos.y, 20,20);!}

戻り値 クラス名::関数名(引数)クラス名を名前空間として使用している他のクラスのdraw()関数との混同を避けている

Page 76: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの記述‣ MoveCircle.cpp - 円を実際に描く手順#include "MoveCircle.h"

void MoveCircle::draw() {!! ofFill();! ofSetColor(31,127,255);! ofCircle(currentPos.x, currentPos.y, 20,20);!}

円を描画

Page 77: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの記述‣ 最後に作成したクラスを、oFのメインクラスであるtestAppから呼び出します

‣ ヘッダーファイル testApp.h で MoveCircle を宣言

‣ これだけで、クラスが実体化(インスタンス化)される‣ クラス名:MoveCircle‣ インスタンス:myCircle

MoveCircle myCircle;

Page 78: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ testApp.h - MoveCircleをインスタンス化#pragma once

#include "ofMain.h"#include "MoveCircle.h"

class testApp : public ofBaseApp{!public:! void setup();! void update();! void draw();!...《中略》...!! MoveCircle myCircle;

};

Page 79: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ testApp.h - MoveCircleをインスタンス化#pragma once

#include "ofMain.h"#include "MoveCircle.h"

class testApp : public ofBaseApp{!public:! void setup();! void update();! void draw();!...《中略》...!! MoveCircle myCircle;

};

MovieCircleのヘッダを読み込む

Page 80: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ testApp.h - MoveCircleをインスタンス化#pragma once

#include "ofMain.h"#include "MoveCircle.h"

class testApp : public ofBaseApp{!public:! void setup();! void update();! void draw();!...《中略》...!! MoveCircle myCircle;

};

MovieCircleをインスタンス化

Page 81: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの記述‣ メインの実装ファイル、testApp.cpp で作成したインスタンスを使用して円を描かせる

‣ testApp::setup( ) で円の初期位置を指定‣ testApp::draw( ) でMyCircleのdraw( )メソッドを呼びだし

Page 82: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ testApp.cpp - MoveCircleで円を描く#include "testApp.h"

//--------------------------------------------------------------void testApp::setup(){! ofSetFrameRate(60);! ofSetVerticalSync(true);! ofEnableAlphaBlending();! ofBackground(0, 0, 0);!! myCircle.currentPos = ofPoint(400, 300);}

//--------------------------------------------------------------void testApp::update(){}

//--------------------------------------------------------------void testApp::draw(){!! myCircle.draw();!}

Page 83: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ testApp.cpp - MoveCircleで円を描く#include "testApp.h"

//--------------------------------------------------------------void testApp::setup(){! ofSetFrameRate(60);! ofSetVerticalSync(true);! ofEnableAlphaBlending();! ofBackground(0, 0, 0);!! myCircle.currentPos = ofPoint(400, 300);}

//--------------------------------------------------------------void testApp::update(){}

//--------------------------------------------------------------void testApp::draw(){!! myCircle.draw();!}

初期位置の指定

Page 84: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ testApp.cpp - MoveCircleで円を描く#include "testApp.h"

//--------------------------------------------------------------void testApp::setup(){! ofSetFrameRate(60);! ofSetVerticalSync(true);! ofEnableAlphaBlending();! ofBackground(0, 0, 0);!! myCircle.currentPos = ofPoint(400, 300);}

//--------------------------------------------------------------void testApp::update(){}

//--------------------------------------------------------------void testApp::draw(){!! myCircle.draw();!}

myCircleを使用して、円を描く

Page 85: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ ようやく円が描けた!!

Page 86: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ 次にMoveCircleクラスに、動きをつけてみる!‣ 関数のところで学んだ、補完する動きをクラスに組み込む

Page 87: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ クラス名:MoveCircle

‣ プロパティ:‣ ofPoint startPos - 開始位置‣ ofPoint endPos - 終了位置‣ ofPoint currentPos - 現在位置‣ float pct - 現在の位置の割合(%)‣ float shaper - 加速・減速の加減

‣ メソッド:‣ void draw(); - 四角形の描画‣ void update(); - 状態の更新‣ float interpolateByPct(float myPct); - 位置の計算

Page 88: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ クラス名:MoveCircle‣ UMLクラス図で表現すると、こんな感じ

‣ この設計図の通りに、ヘッダーファイル(MoveCircle.h)と実装ファイル(MoveCircle.cpp)を記述していく

+ draw():void+ update():void+ interpolateByPct():ofPoint

+ startPos:ofPoint+ endPos:ofPoint+ currentPos:ofPoint+ pct:float+ shaper:float

MoveCircle

Page 89: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ MoveCircle.h - 円を描く際のレシピ!#pragma once#include "ofMain.h"

class MoveCircle {!public:!! void draw();! void update();! ofPoint interpolateByPct(float pct);!! ofPoint currentPos;! ofPoint startPos;! ofPoint endPos;! float pct;! float shaper;};

Page 90: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ MoveCircle.h - 円を描く際のレシピ!#pragma once#include "ofMain.h"

class MoveCircle {!public:!! void draw();! void update();! ofPoint interpolateByPct(float pct);!! ofPoint currentPos;! ofPoint startPos;! ofPoint endPos;! float pct;! float shaper;};

メソッド

Page 91: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ MoveCircle.h - 円を描く際のレシピ!#pragma once#include "ofMain.h"

class MoveCircle {!public:!! void draw();! void update();! ofPoint interpolateByPct(float pct);!! ofPoint currentPos;! ofPoint startPos;! ofPoint endPos;! float pct;! float shaper;};

プロパティ

Page 92: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ 次に実装ファイル MoveCircle.cpp を改変

Page 93: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ MoveCircle.cpp - 円を動かす#include "MoveCircle.h"

void MoveCircle::draw() {

! ofFill();! ofSetColor(31,127,255); ofCircle(currentPos.x, currentPos.y, 20, 20);!}

void MoveCircle::update() {

! pct += 0.01f;! if (pct > 1) {! ! pct = 0;! }!! currentPos = interpolateByPct(pct);!}

Page 94: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ MoveCircle.cpp - 円を動かす

ofPoint MoveCircle::interpolateByPct(float _pct){!! float shapedPct = powf(_pct, shaper);!! ofPoint pos;! pos.x = (1 - shapedPct) * startPos.x + shapedPct * endPos.x;! pos.y = (1 - shapedPct) * startPos.y + shapedPct * endPos.y;!! return pos;!}

Page 95: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ メインクラスの実装ファイル testApp.cpp も変更が必要

Page 96: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ testApp.cpp - MoveCircleで円を動かす#include "testApp.h"

//--------------------------------------------------------------void testApp::setup(){! ofSetFrameRate(60);! ofBackground(0, 0, 0);! myCircle.startPos = ofPoint(10, 400);! myCircle.endPos = ofPoint(1000, 200);! myCircle.shaper = 2.0;}

//--------------------------------------------------------------void testApp::update(){! myCircle.update();}

//--------------------------------------------------------------void testApp::draw(){! myCircle.draw();}

...《後略》...

Page 97: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クラスの実装‣ 完成!!

Page 98: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

OOP実践編パーティクルを動かす

Page 99: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

OOP実践編:パーティクルを動かす‣ より実践的なOOPを、例を参照しながら理解する‣ パーティクル (Particles = 粒子) が空間内を飛びまわるプログラムを作成してみる

‣ 最初は1つの粒‣ 大量の粒を個別に動かすには?‣ オブジェクトの配列を利用すると便利

‣ 2種類の配列‣ 静的配列 (Array):固定長の配列‣ 動的配列 (Vector):可変長の配列

Page 100: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

パーティクルのイメージ‣ 一定方向に向けて移動する力を持つ‣ ただし、常に反対方向の抵抗(摩擦など)を受けている

物体にかかる力 (force)F = ma (力 = 質量 * 加速度)ニュートンの運動方程式

抵抗力 (damping)

Page 101: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

パーティクルクラスを設計する‣ パーティクルクラスに必要な要素

‣ クラス名:Particle

‣ プロパティ(状態)‣ 現在位置:pos (ofVec2f)‣ 速度:vel (ofVec2f)‣ 力:frc (ofVec2f)

Page 102: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

パーティクルクラスを設計する‣ パーティクルクラスに必要な要素 (つづき)

‣ メソッド (動作)‣ コンストラクタ(後述):Particle()‣ デストラクタ(後述):~Particle()‣ 力のリセット:recetForce()‣ 力を加える:addForce()‣ 抵抗力(摩擦)を加える:addDampingForce()‣ 状態の初期化:setInitialCondition()‣ 位置更新:update()‣ 描画:draw()

Page 103: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

パーティクルクラスを設計する‣ ofVec2f とは?

‣ ofPoint (x座標, y座標)に加えて、距離の算出や2点間の角度の計算など、ベクトル計算に特化したクラス

‣ oF v007からは、ofVectorMathとして標準で使用可能

Page 104: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

パーティクルクラスを設計する‣ ParticleクラスのUMLクラス図

+ Particle()+ ~Particle()+ resetForce():void+ addForce(float x, float y):void+ addDumpingForce():void+ setInitialCondition(float px, float py, float vx, float vy):void+ update():void+ draw():void

+ pos:ofVec2f+ vel:ofVec2f+ frc:ofVec2f+ dumping:float

Particle

Page 105: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

コンストラクタとデストラクタ‣ コンストラクタ、デストラクタ:特殊なメソッド

‣ コンストラクタ‣ クラスがインスタンス化された際に実行される‣ つまり初期化の関数‣ 関数名はかならずクラス名と同じにする

‣ デストラクタ‣ クラスが廃棄された際に実行される‣ 終了処理‣ 関数名は「~クラス名」にする

Page 106: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

コンストラクタとデストラクタ‣ Particleクラスは完成したものをあらかじめ用意してきました‣ これを活用していきます!!

Page 107: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

Particleクラスの実装‣ ヘッダーファイル:Particle.h#pragma once#include "ofMain.h"

class Particle {public:!! ofVec2f pos;! ofVec2f vel;! ofVec2f frc;! float damping;!! Particle();! ~Particle();! void resetForce();! void addForce(float x, float y);! void addDampingForce();! void setInitialCondition(float px, float py, float vx, float vy);! void update();! void draw();!};

Page 108: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

Particleクラスの実装‣ 実装ファイル:Particle.cpp#include "Particle.h"

//コンストラクタ(初期化)Particle::Particle(){! setInitialCondition(0,0,0,0);! damping = 0.01f;}

//デストラクタ(終了処理)Particle::~Particle(){}

//力(加速度)をリセットvoid Particle::resetForce(){ frc.set(0,0);}

//力を加えるvoid Particle::addForce(float x, float y){ frc.x = frc.x + x; frc.y = frc.y + y;}

Page 109: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

Particleクラスの実装‣ 実装ファイル:Particle.cpp//抵抗力の計算void Particle::addDampingForce(){ frc.x = frc.x - vel.x * damping; frc.y = frc.y - vel.y * damping;}

//初期状態を設定void Particle::setInitialCondition(float px, float py, float vx, float vy){ pos.set(px,py);! vel.set(vx,vy);}

//更新void Particle::update(){!! vel = vel + frc;! pos = pos + vel; }

//描画void Particle::draw(){ ofCircle(pos.x, pos.y, 3);}

Page 110: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

testAppを設計‣ testAppから、Particleを呼びだしてみる‣ Particleクラスをインスタンス化、名前を「p」に

‣ testAppのsetup()内‣ Particleを初期設定:p.setInitialCondition()

‣ testAppのupdate()では…‣ Particleの力をリセット:p.restForce()‣ Particleの抵抗力を計算:p.addDampingForce()‣ Particleの位置を更新:p.update()

‣ testAppのdraw()で‣ Particleを描画:p.draw()

Page 111: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

testAppクラスの実装‣ ヘッダーファイル:testApp.h#pragma once

#include "ofMain.h"#include "Particle.h"

class testApp : public ofSimpleApp{!public: void setup(); void update(); void draw(); void keyPressed (int key); void keyReleased (int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(); //クラスParticleをインスタンス化 Particle p;};

Page 112: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

testAppクラスの実装‣ 実装ファイル:testApp.cpp#include "testApp.h"

void testApp::setup(){!! ofSetVerticalSync(true);! ofSetFrameRate(60);! ofBackground(0, 0, 0);! p.setInitialCondition(ofGetWidth()/2, ofGetHeight()/2, ofRandom(-10,10), ofRandom(-10,10));}

void testApp::update(){! p.resetForce();! p.addDampingForce();! p.update(); }

void testApp::draw(){! ofSetColor(255, 255, 255);! p.draw();}

...《後略》...

Page 113: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

testAppクラスの実装‣ 完成

Page 114: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

インタラクションを追加‣ マウスをクリックすると、クリックした位置からパーティクルを放出するように改造

‣ 参考:testAppのマウスに関するインタラクション‣ void mouseMoved(int x, int y );‣ マウスを移動

‣ void mouseDragged(int x, int y, int button);‣ マウスをドラッグ

‣ void mousePressed(int x, int y, int button);‣ マウスのボタンを押した瞬間

‣ void mouseReleased();‣ マウスの押していたボタンを離した瞬間

Page 115: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

testAppクラスの実装‣ testApp.cppに、下記の処理を追加するvoid testApp::mousePressed(int x, int y, int button){! p.setInitialCondition(x,y,ofRandom(-10,10), ofRandom(-10,10));}

Page 116: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

testAppクラスの実装‣ 完成:マウスを画面上でクリックしてみる

Page 117: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

クイズ:重力を追加する‣ testAppを少しだけ変更して、パーティクルに重力を適用してみる

‣ 重量とは、常にパーティクルに一定に係りつづける力‣ Particleには既に力を加える関数addForce()を実装済み

重力 (Velocity)

Page 118: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを同時に動かす静的配列(Array)と、動的配列(Vector)

Page 119: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを同時に動かす‣ 複数のパーティクルを同時に動かすようにする‣ パーティクルのオブジェクトを格納するやりかたに工夫が必要‣ 複数のオブジェクトを格納するには、配列を利用‣ 配列 = 値を格納するロッカーのようなもの

p[0]

p[1]

p[2]...

配列

NUM個

Page 120: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

静的(固定長)配列と、動的(可変長)配列‣ 要素の数が固定された配列と、必要に応じて自由に長さをかえることのできる配列がある

‣ 静的配列:Array - 配列の数をあらかじめ指定する必要‣ 例:Particleクラスのオブジェクトpを100個格納

‣ 動的配列列:Vector - 配列の数を指定する必要はない‣ 例:Particleクラスのオブジェクトpを動的配列に

Particle p[100];

vector <Particle> p;

Page 121: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを同時に動かす(Array版)‣ まずは静的配列(Array)で実装してみる‣ Particleクラス(Particle.hとParticle.cpp)はそのまま変更なしに使用可能

p[0]

p[1]

p[2]...

Particle p[NUM]

NUM個

p[NUM]

Page 122: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを同時に動かす(Array版)‣ 配列(Array)に格納した、大量のパラメータを使用して、同時にパーティクルを動かすには?

‣ くりかえしの構文を使用する

‣ C++ では for文を使うと便利!!

Page 123: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

‣ for文の書きかた

‣ 初期化式:初期化の際の条件式‣ 継続条件式:繰り返しを継続する条件式‣ 再初期化式:繰り返されるたびに実行される式

繰り返し

for (初期化式; 継続条件式; 再初期化式) { 文;}

Page 124: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

/* 100回「+」の文字を出力する */

for (int i = 0; i < 100; i++) {

! cout << "+";

}

‣ for分を用いた、繰り返しの例 1

繰り返し

Page 125: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを同時に動かす(Array版)‣ パーティクルの位置の更新 (update) と 描画 (draw) を複数同時に動くように書き換える

‣ 配列と for文がポイント

Page 126: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

void testApp::update(){! p.resetForce();! p.addForce(0, 0.1);! p.addDampingForce();! p.update();}

複数のパーティクルを同時に動かす(Array版)‣ update() の部分は、配列とfor文でこうなる

void testApp::update(){! for (int i = 0; i < NUM; i++) {! ! p[i].resetForce();! ! p[i].addForce(0, 0.1);! ! p[i].addDampingForce();! ! p[i].update();! }}

Page 127: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

void testApp::draw(){! ofSetColor(255, 255, 255);! p.draw();}

複数のパーティクルを同時に動かす(Array版)‣ draw() も同様に

void testApp::draw(){! ofSetColor(255, 255, 255);! for (int i = 0; i < NUM; i++) {! ! p[i].draw();! }}

Page 128: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを同時に動かす(Array版)‣ ヘッダーファイル:testApp.h#pragma once

#include "ofMain.h"#include "Particle.h"

#define NUM 100

class testApp : public ofSimpleApp{!public: void setup(); void update(); void draw(); void keyPressed (int key); void keyReleased (int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(); //クラスParticleの配列 (NUM個) Particle p[NUM];};

Page 129: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを同時に動かす(Array版)‣ 実装ファイル:testApp.cpp#include "testApp.h"

void testApp::setup(){!! ofSetVerticalSync(true);! ofSetFrameRate(60);! ofBackground(0, 0, 0);}

void testApp::update(){ for (int i = 0; i < NUM; i++) { p[i].resetForce(); p[i].addForce(0, 0.1); p[i].addDampingForce(); p[i].update(); }}

void testApp::draw(){! ofSetColor(255, 255, 255); for (int i = 0; i < NUM; i++) { p[i].draw(); }}

Page 130: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを同時に動かす(Array版)‣ 実装ファイル:testApp.cpp

...《中略》...

void testApp::mousePressed(int x, int y, int button){ for (int i = 0; i < NUM; i++) { p[i].setInitialCondition(x, y, ofRandom(-10,10), ofRandom(-10,10)); }}

Page 131: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを同時に動かす(Array版)‣ 完成:画面上でマウスクリック!

Page 132: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを動かす(vector版)‣ 同じ動きを、動的配列(Vector)で置き換える

particles[0]

particles[1]

particles[2]...

Vector <Particle> particles

数は可変

Page 133: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを動かす(vector版)‣ Vectorの配列要素の操作

‣ 配列の末尾に要素を追加 → push_back()‣ 例:Particleのオブジェクトpを、particlesに追加

‣ 配列の末尾に要素を削除 → pop_back()

‣ 配列の全ての要素をクリア → clear()

particles.push_back(p);

particles.clear();

particles.pop_back();

Page 134: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを動かす(vector版)‣ ヘッダーファイル:testApp.h#pragma once#include "ofMain.h"#include "Particle.h"

#define NUM 100

class testApp : public ofSimpleApp{!public: void setup(); void update(); void draw(); void keyPressed (int key); void keyReleased (int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(); //クラスParticleの動的配列particles vector <Particle> particles;};

Page 135: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを動かす(vector版)‣ 実装ファイル:testApp.cpp#include "testApp.h"

void testApp::setup(){!! ofSetVerticalSync(true);! ofSetFrameRate(60);! ofBackground(0, 0, 0);}

void testApp::update(){ for (int i = 0; i < particles.size(); i++) { particles[i].resetForce(); particles[i].addForce(0, 0.1); particles[i].addDampingForce(); particles[i].update(); }}

void testApp::draw(){! ofSetColor(255, 255, 255); for (int i = 0; i < particles.size(); i++) { particles[i].draw(); }}

Page 136: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを動かす(vector版)‣ 実装ファイル:testApp.cpp...《中略》...

void testApp::mousePressed(int x, int y, int button){ particles.clear(); for (int i = 0; i < NUM; i++) { //Particleをインスタンス化 → myParticle Particle myParticle; //初期化 float vx = ofRandom(-10, 10); float vy = ofRandom(-10, 10); myParticle.setInitialCondition(x, y, vx, vy); //作成したオブジェクトを配列の末尾に追加 particles.push_back(myParticle); }}

Page 137: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

複数のパーティクルを動かす(vector版)‣ 完成:画面上でマウスクリック!

Page 138: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

応用編:パーティクルをどんどん追加‣ 動的配列の利点を活用‣ 最大数の制限なく、どんどんパーティクルを追加していく

‣ ユーザからのインタラクション:‣ マウスをドラッグすると、パーティクルを1つ追加‣ ドラッグしつづけると、どんどん増えていく‣ キーボードで「c」キーを入力すると、全部消去

‣ 今回もParticleクラスは一切変更の必要なし

Page 139: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

応用編:パーティクルをどんどん追加‣ ヘッダーファイル:testApp.h#pragma once

#include "ofMain.h"#include "Particle.h"

class testApp : public ofSimpleApp{!public: void setup(); void update(); void draw(); void keyPressed (int key); void keyReleased (int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(); //クラスParticleの動的配列particles vector <Particle> particles;};

Page 140: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

応用編:パーティクルをどんどん追加‣ 実装ファイル:testApp.cpp#include "testApp.h"

void testApp::setup(){!! ofSetVerticalSync(true);! ofSetFrameRate(60);! ofBackground(0, 0, 0);}

void testApp::update(){ for (int i = 0; i < particles.size(); i++) { particles[i].resetForce(); particles[i].addDampingForce(); particles[i].update(); }}

void testApp::draw(){! ofSetColor(255, 255, 255);! //画面左上にメッセージを表示! string message = "current particle num = " + ofToString(particles.size(),0);! ofDrawBitmapString(message, 20, 20);

for (int i = 0; i < particles.size(); i++) { particles[i].draw(); }}

Page 141: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

応用編:パーティクルをどんどん追加‣ 実装ファイル:testApp.cpp (つづき)void testApp::keyPressed (int key){! //'c'キーでパーティクルを全部消去! if (key == 'c') {! ! particles.clear();! }! //'f'キーでフルスクリーン表示! if (key == 'f') {! ! ofToggleFullscreen();! }}

...《中略》...

void testApp::mouseDragged(int x, int y, int button){! //マウスをドラッグするとパーティクルが追加される! Particle myParticle;! float vx = ofRandom(-3, 3);! float vy = ofRandom(-3, 3);! myParticle.setInitialCondition(x, y, vx, vy);! particles.push_back(myParticle);}

...《後略》...

Page 142: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

応用編:パーティクルをどんどん追加‣ 完成:画面上をドラッグしてパーティクルを追加

Page 143: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

実習:パーティクルをつかって表現‣ Particleクラスと動的配列をつかって、表現してみる

‣ Patricleクラス自体を自由にカスタマイズしてもOK‣ Particleの位置情報を活用‣ 入力の方法を工夫する‣ Particleの動きを変更‣ 色や形を工夫‣ ...etc

Page 144: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

実習:パーティクルをつかって表現‣ 応用例その1:

‣ Particleの位置に点を描くのではなく、それぞれの点を結ぶカーブを描く

‣ ofCarbeVertex() をつかう‣ testApp.cpp の draw()を書き換える

Page 145: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

実習:パーティクルをつかって表現‣ 実装ファイル:testApp.cpp (drawのみ書き換え)...《中略》...

void testApp::draw(){! ofSetColor(255, 255, 255);! //画面左上にメッセージを表示! string message = "current particle num = " ! + ofToString(particles.size(),0);! ofDrawBitmapString(message, 20, 20);!! ofNoFill();! ofBeginShape();! for (int i = 0; i < particles.size(); i++){! ! ofCurveVertex(particles[i].pos.x, particles[i].pos.y);! }! ofEndShape();}

...《後略》...

Page 146: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

実習:パーティクルをつかって表現‣ 完成:画面上をドラッグして線を描く

Page 147: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

実習:パーティクルをつかって表現‣ 応用例その2:

‣ ビットマップ画像でパーティクルを描く‣ ofImageを使うと、外部画像ファイルを読みこんで表示可能‣ ofImageの詳細の解説は、また別途行う予定

‣ パーテイクルの位置に、ビットマップ画像を配置していく‣ X座標 → particles[i].pos.x;‣ Y座標 → particles[i].pos.y;

Page 148: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

実習:パーティクルをつかって表現‣ ヘッダーファイル:testApp.h#pragma once

#include "ofMain.h"#include "Particle.h"

class testApp : public ofSimpleApp{!public: void setup(); void update(); void draw(); void keyPressed (int key); void keyReleased (int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(); //クラスParticleの動的配列particles vector <Particle> particles;! //ビットマップ画像! ofImage img;};

Page 149: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

実習:パーティクルをつかって表現‣ 実装ファイル:testApp.cpp (1 / 3)#include "testApp.h"

void testApp::setup(){!! ofSetVerticalSync(true);! ofSetFrameRate(60);! ofBackground(0, 0, 0);! ofEnableBlendMode(OF_BLENDMODE_ADD);

! //イメージファイルを読込み! img.loadImage("particle32.png");}

void testApp::update(){ for (int i = 0; i < particles.size(); i++) { particles[i].resetForce(); particles[i].addDampingForce(); particles[i].update(); }}

Page 150: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

実習:パーティクルをつかって表現‣ 実装ファイル:testApp.cpp (2 / 3)void testApp::draw(){! //画面左上にメッセージを表示! ofSetColor(255, 255, 255);! string message = "current particle num = " + ofToString(particles.size(),0);! ofDrawBitmapString(message, 20, 20);

! //パーティクルの位置に画像を表示! for (int i = 0; i < particles.size(); i++){! ! float posx = particles[i].pos.x - 16;! ! float posy = particles[i].pos.y - 16;! ! img.draw(posx, posy);! }}

void testApp::keyPressed (int key){! //'c'キーでパーティクルを全部消去! if (key == 'c') {! ! particles.clear();! }! //'f'キーでフルスクリーン表示! if (key == 'f') {! ! ofToggleFullscreen();! }}

Page 151: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

実習:パーティクルをつかって表現‣ 実装ファイル:testApp.cpp (3 / 3)

【中略】

void testApp::mouseDragged(int x, int y, int button){! //マウスをドラッグするとパーティクルが追加される! Particle myParticle;! float vx = ofRandom(-1, 1);! float vy = ofRandom(-1, 1);! myParticle.setInitialCondition(x, y, vx, vy);! particles.push_back(myParticle);}

【後略】

Page 152: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

実習:パーティクルをつかって表現‣ 完成:画面上をドラッグすると画像が表示される

Page 153: BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 2

休憩