75
メディア・アートII 第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション 2013年9月16日 多摩美術大学情報デザイン学科メディア芸術コース 田所淳

メディア・アートII 第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

メディア・アートII 第2回 openFrameworks基礎配列、くりかえし、乱数ベクトルを使用したアニメーション

2013年9月16日多摩美術大学情報デザイン学科メディア芸術コース田所淳

Page 2: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

本日の内容‣ openFrameworksのプログラムの基礎

‣ 今後の作品制作のための基礎体力をつけていきます!

‣ 乱数(ランダム)‣ 配列とくりかえし‣ 条件分岐‣ ベクトルを使用した運動の表現‣ 大量の物体を動かす

Page 3: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

本日の内容‣ ただ、プログラミングを書き写すだけではつまらない…‣ クイズ形式で進めてみます!

Page 4: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

準備‣ まずは、先週の復習‣ 新規プロジェクトの生成 - ProjectGeneratorの使い方

Page 5: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q1: 乱数について

Page 6: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q1: 乱数について‣ ランダム(規則性のない)場所に、静止した円を描きなさい‣ プログラムを実行するたびに、違う場所に描かれるように

‣ ヒント:‣ 円を描く - ofCircle(x, y, radius);‣ ランダムな数を生成 - ofRandom(min, max);

Page 7: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#include "testApp.h"

void testApp::setup(){ // 画面基本設定 ofSetFrameRate(60); ofBackground(63); ofSetCircleResolution(32);}

void testApp::update(){}

void testApp::draw(){ // ランダムな場所に半径40pxの円を描く ofCircle(ofRandom(ofGetWidth()), ofRandom(ofGetHeight()), 40);}

... 後略

Q1: 乱数について‣ よくある間違い - testApp.cpp‣ どうなるか、実験してみる

Page 8: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q1: 解答

Page 9: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q1: 乱数について - 解答‣ setup() であらかじめランダムな座標を生成しておく‣ 生成した座標は、グローバルな変数に格納 (testApp.hに)‣ その変数の値を参照して、draw() で円を描く

Page 10: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#pragma once

#include "ofMain.h"

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

... // 円の位置 float posX; float posY; };

Q1: 乱数について - 解答‣ testApp.h

Page 11: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#include "testApp.h"

void testApp::setup(){ // 画面基本設定 ofSetFrameRate(60); ofBackground(63); ofSetCircleResolution(32); // 画面内のランダムな場所を指定 posX = ofRandom(ofGetWidth()); posY = ofRandom(ofGetHeight());}

...

void testApp::draw(){ // 設定した場所に円を描く ofSetHexColor(0x3399cc); ofCircle(posX, posY, 20);}

...

Q1: 乱数について - 解答‣ testApp.cpp

Page 12: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q1: 乱数について - 解答‣ 実行するたびに、ランダムな場所に円が描かれる

Page 13: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q2: たくさんの図形をランダムな場所に描く

Page 14: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q2: たくさんの図形をランダムな場所に描く‣ 100個の静止した円をランダムな場所に描く‣ 半径は40pxで統一

Page 15: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q2: たくさんの図形をランダムな場所に描く‣ ヒント 1: 配列 - たくさんの値を保存する‣ 例えば、100個のposXを保存するための「箱」は以下のようにしたら準備できる

‣ この箱には、[] で囲まれた部分に連番でナンバリングされる

‣ この仕組みで、100個の、posXとposYが確保できる

float posX[100];

posX[0] posX[1]posX[2]...posX[99]

← 0から開始する

← 0~99までで100個ぶん

Page 16: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q2: たくさんの図形をランダムな場所に描く‣ ヒント 2: くりかえし ‣ for文を使用する‣ 例えば、0~99の100回くりかえす構文

‣ カウンタ変数 i を賢く利用する

for (int i = 0; i < 100; i++) { 《処理の内容》}

for (int i = 0; i < 100; i++) { posX[i] = ????; posY[i] = ????;}

Page 17: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q2: 解答

Page 18: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#pragma once

#include "ofMain.h"

class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); ... // 位置の配列を生成 float posX[100]; float posY[100];};

Q2: 解答‣ testApp.h

Page 19: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#include "testApp.h"

void testApp::setup(){ // 画面基本設定 ofSetFrameRate(60); ofBackground(63); ofSetCircleResolution(32); // 画面内のランダムな場所を円の数だけ指定 for (int i = 0; i < 100; i++) { posX[i] = ofRandom(ofGetWidth()); posY[i] = ofRandom(ofGetHeight()); }}

...

void testApp::draw(){ ofSetHexColor(0x3399cc); // 画面内のランダムな場所を円の数だけ描画 for (int i = 0; i < 100; i++) { ofCircle(posX[i], posY[i], 20); }}

Q2: 解答‣ testApp.cpp

Page 20: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q2: 解答‣ 100個の円が、ランダムな場所に描かれる

Page 21: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q2: 解答‣ 参考: ‣ 数を変更したい場合、いろいろ修正箇所あり‣ 1箇所だけを変更すると、数がすぐに変更できるようにしたい!‣ testApp.hに、クラスの定数(const)として数を指定する‣ 正式には、静的メンバ変数による定数

‣ クラスの定数は、以下のような書式になる

‣ 例: 定数「CIRCLE_NUM」を100と定義

static const int 変数名 = 値;

static const int CIRCLE_NUM = 100;

Page 22: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#pragma once

#include "ofMain.h"

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

...

// 描画する円の数を指定 static const int CIRCLE_NUM = 100; // 位置の配列を生成 float posX[CIRCLE_NUM]; float posY[CIRCLE_NUM];};

Q2: 解答‣ 定数で数を定義バージョン: testApp.h

Page 23: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#include "testApp.h"

void testApp::setup(){ // 画面基本設定 ofSetFrameRate(60); ofBackground(63); ofSetCircleResolution(32); // 画面内のランダムな場所を円の数だけ指定 for (int i = 0; i < CIRCLE_NUM; i++) { posX[i] = ofRandom(ofGetWidth()); posY[i] = ofRandom(ofGetHeight()); }}

...

void testApp::draw(){ ofSetHexColor(0x3399cc); // 画面内のランダムな場所を円の数だけ描画 for (int i = 0; i < CIRCLE_NUM; i++) { ofCircle(posX[i], posY[i], 20); }}

Q2: 解答‣ 定数で数を定義バージョン: testApp.cpp

Page 24: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q2: 解答‣ 例: 円の数を、100 → 400個に

Page 25: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q3: たくさんの図形をアニメーション

Page 26: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q3: たくさんの図形をアニメーション‣ 次に表示するプログラムを改造して、100個の円が同時に動きまわるアニメーションにする

‣ 開始位置と、円の移動速度と方向はランダムに

Page 27: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#pragma once

#include "ofMain.h"

class testApp : public ofBaseApp{ public: void setup(); void update(); void draw();... // 位置 float positionX; float positionY; // 速度 float velocityX; float velocityY;};

Q3: たくさんの図形をアニメーション‣ ヒントプログラム: testApp.h

Page 28: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#include "testApp.h"void testApp::setup(){ // 画面基本設定 ofSetFrameRate(60); ofBackground(63); ofSetCircleResolution(32); // ランダムな場所と速度を指定 positionX = ofRandom(ofGetWidth()); positionY = ofRandom(ofGetHeight()); velocityX = ofRandom(-10, 10); velocityY = ofRandom(-10, 10);}void testApp::update(){ // 円の座標を更新 positionX += velocityX; positionY += velocityY; // 画面からはみ出ないように if (positionX < 0 || positionX > ofGetWidth()) { velocityX *= -1; } if (positionY < 0 || positionY > ofGetHeight()) { velocityY *= -1; }}

Q3: たくさんの図形をアニメーション‣ ヒントプログラム: testApp.cpp

Page 29: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

void testApp::draw(){ ofSetHexColor(0x3399cc); // 円を描画 ofCircle(positionX, positionY, 20);}

Q3: たくさんの図形をアニメーション‣ ヒントプログラム: testApp.cpp

Page 30: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q3: たくさんの図形をアニメーション‣ ヒント: 位置と速度をそれぞれ配列にする‣ 定数を定義して、数はすぐに変更できるように

‣ static const int CIRCLE_NUM ‣ positionX[CIRCLE_NUM]‣ positionY[CIRCLE_NUM]‣ velocity X[CIRCLE_NUM]‣ velocityY[CIRCLE_NUM]

‣ 最初の位置と速度、座標の変更、描画、すべての処理をくりかえして100回行う → for文

Page 31: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q3: 解答

Page 32: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#pragma once

#include "ofMain.h"

class testApp : public ofBaseApp{ public:... // 描画する円の数を指定 static const int CIRCLE_NUM = 100; // 位置の配列を生成 float posX[CIRCLE_NUM]; float posY[CIRCLE_NUM]; // 速度の配列を生成 float speedX[CIRCLE_NUM]; float speedY[CIRCLE_NUM];};

Q3: 解答‣ testApp.h

Page 33: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#include "testApp.h"

void testApp::setup(){ // 画面基本設定 ofSetFrameRate(60); ofBackground(63); ofSetCircleResolution(32); // 画面内のランダムな場所と速度を円の数だけ指定 for (int i = 0; i < CIRCLE_NUM; i++) { posX[i] = ofRandom(ofGetWidth()); posY[i] = ofRandom(ofGetHeight()); speedX[i] = ofRandom(-10, 10); speedY[i] = ofRandom(-10, 10); }}

void testApp::update(){ // 円の座標を全て更新 for (int i = 0; i < CIRCLE_NUM; i++) { posX[i] += speedX[i]; posY[i] += speedY[i];

Q3: 解答‣ testApp.cpp

Page 34: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

// 画面からはみ出たらバウンドさせる if (posX[i] < 0 || posX[i] > ofGetWidth()) { speedX[i] *= -1; } if (posY[i] < 0 || posY[i] > ofGetHeight()) { speedY[i] *= -1; } }}

//--------------------------------------------------------------void testApp::draw(){ ofSetHexColor(0x3399cc); // 画面内のランダムな場所を円の数だけ描画 for (int i = 0; i < CIRCLE_NUM; i++) { ofCircle(posX[i], posY[i], 20); }}

...

Q3: 解答‣ testApp.cpp

Page 35: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q3: 解答‣ 100個の円が、同時に動く(はず!)

Page 36: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

ベクトルによる運動の表現

Page 37: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

ベクトルによる運動の表現‣ ここまでの、(x, y)座標それぞれに変数を用意する方法‣ ビギナー的表現

‣ より運動を表現するための高度な書式をマスターしたい‣ 「ベクトル (Vector)」を理解する!

Page 38: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

ベクトルによる運動の表現‣ ベクトル = 幾何学的空間における、大きさと向きを持った量

Page 39: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

ベクトルによる運動の表現‣ 例: 原点(0,0)から(2,3)の座標までのベクトル

‣ このベクトルは、OA = (2,3) と記述される→

Page 40: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

ベクトルによる運動の表現‣ ベクトルは、足し算することができる‣ 例: a = (-2,3) と b = (4,2) の2つのベクトルを足す‣ a + b = (-2+4,3+2) = (2,5)

Page 41: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

ベクトルによる運動の表現‣ ベクトルは、引き算も可能‣ 例: a = (-2, 3) , b = (4, 2)‣ a - b = (-2-4,3-2) = (-6,1)

Page 42: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

ベクトルによる運動の表現‣ 位置ベクトル‣ いままで扱ってきた2次元平面の座標 (x, y) は、原点 (0, 0) を始点としたベクトルと捉えることができる → 位置ベクトル

Page 43: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

ベクトルによる運動の表現‣ 速度ベクトル‣ 「速度 (velocity)」とは、単位時間あたりの物体の移動の変位‣ 日常的な「速さ (speed)」と「速度 (velocity)」を区分する‣ 1フレームごとの座標の変化 = 向きと大きさをもった「速度ベクトル」

位置ベクトル a

位置ベクトル b速度ベクトル

Page 44: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

ベクトルによる運動の表現‣ openFrameworksで、ベクトルを表現‣ 2次元のベクトルは「ofVec2f」を使用する

‣ 例:位置ベクトルと速度ベクトルの宣言

‣ 「ベクトル名.x」「ベクトル名.y」: ベクトルの、x方向の成分と y方向の成分をとりだす

‣ 例:位置ベクトルの(x, y)座標を設定する‣

ofVec2f position; // 位置ベクトルpositionを宣言ofVec2f velocity; // 速度ベクトルvelocityを宣言

position.x = 100; // 位置ベクトルpositionのx成分を100にposition.y = 100; // 位置ベクトルpositionのx成分を50に

Page 45: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q4: ベクトルで運動を表現する

Page 46: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q4: ベクトルで運動を表現する‣ Q3 で作成した、たくさんの図形を動かすサンプルを、ベクトル(ofVec2f)で書き直してみる

‣ ヒント:100個ぶんの位置ベクトルと速度ベクトルは以下のように宣言される

// 描画する円の数を指定static const int CIRCLE_NUM = 100; // 位置ベクトルの配列ofVec2f position[CIRCLE_NUM]; // 速度ベクトルの配列ofVec2f velocity[CIRCLE_NUM];

Page 47: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q4: 解答

Page 48: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#pragma once

#include "ofMain.h"

class testApp : public ofBaseApp{ public:

... // 描画する円の数を指定 static const int CIRCLE_NUM = 100; // 位置ベクトルの配列 ofVec2f position[CIRCLE_NUM]; // 速度ベクトルの配列 ofVec2f velocity[CIRCLE_NUM];};

Q4: 解答‣ testApp.h

Page 49: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#include "testApp.h"void testApp::setup(){ // 画面基本設定 ofSetFrameRate(60); ofBackground(63); ofSetCircleResolution(32); // 画面内のランダムな場所と速度を円の数だけ指定 for (int i = 0; i < CIRCLE_NUM; i++) { position[i].x = ofRandom(ofGetWidth()); position[i].y = ofRandom(ofGetHeight()); velocity[i].x = ofRandom(-10, 10); velocity[i].y = ofRandom(-10, 10); }}void testApp::update(){ // 円の座標を全て更新 for (int i = 0; i < CIRCLE_NUM; i++) { position[i] += velocity[i];

// 画面からはみ出たらバウンドさせる if (position[i].x < 0 || position[i].x > ofGetWidth()) { velocity[i].x *= -1; }

Q4: 解答‣ testApp.cpp

Page 50: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

if (position[i].y < 0 || position[i].y > ofGetHeight()) { velocity[i].y *= -1; } }}

void testApp::draw(){ ofSetHexColor(0x3399cc); // 画面内のランダムな場所を円の数だけ描画 for (int i = 0; i < CIRCLE_NUM; i++) { ofCircle(position[i], 20); }}

Q4: 解答‣ testApp.cpp

Page 51: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

Q4: 解答‣ おなじ運動が、とてもすっきりと記述できた!!

Page 52: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

応用: さらにリアルな運動の表現摩擦力

Page 53: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

応用: さらにリアルな運動の表現‣ 摩擦力 (Friction) を表現してみる‣ 摩擦力 = その物体の進行方向逆向きに働く力

速度ベクトル

摩擦力

Page 54: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

応用: さらにリアルな運動の表現‣ 摩擦力を加えた運動の計算アルゴリズム

円の位置と初期速度を設定

力をリセット

摩擦力を加味した力を更新

力から速度を計算、座標を更新

画面からはみ出ていないかチェック

Page 55: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

応用: さらにリアルな運動の表現‣ プログラムの可読性を高める工夫‣ 処理のかたまりを「関数 (function) 」としてまとめる

Page 56: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

応用: さらにリアルな運動の表現‣ 関数 (function)‣ 引数 (ひきすう, argument) - 関数に渡す値 (入力)‣ 返り値 (return value) - 関数が返す値 (出力)

関数

引数1 引数2 引数3

戻り値

Page 57: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

応用: さらにリアルな運動の表現‣ C++での関数の書き方

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

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

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

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

Page 58: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

応用: さらにリアルな運動の表現‣ 先程の処理の流れを以下の関数として定義

void setInit();

void resetForce();

void updateForce();

void updatePos();

void checkBounds();

Page 59: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#pragma once

#include "ofMain.h"

class testApp : public ofBaseApp{ public:

...

void setInit(); // 初期設定 void resetForce(); // 力をリセット void updateForce(); // 力を更新 void updatePos(); // 位置の更新 void checkBounds(); // 画面からはみ出たらバウンドさせる static const int CIRCLE_NUM = 100; // 描画する円の数を指定 ofVec2f position[CIRCLE_NUM]; // 位置ベクトルの配列 ofVec2f velocity[CIRCLE_NUM]; // 速度ベクトルの配列 ofVec2f force[CIRCLE_NUM]; // 力ベクトルの配列 float friction = 0.01; // 摩擦係数};

応用: さらにリアルな運動の表現‣ testApp.h

Page 60: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

...void testApp::setup(){ // 画面基本設定 ofSetFrameRate(60); ofBackground(63); ofSetCircleResolution(32); setInit(); // 円を初期化}

void testApp::update(){ resetForce(); // 力をリセット updateForce(); // 力の更新 (摩擦) updatePos(); // 円の座標を全て更新 checkBounds(); // 画面からはみ出たらバウンドさせる}

void testApp::draw(){ ofSetHexColor(0x3399cc); // 画面内のランダムな場所を円の数だけ描画 for (int i = 0; i < CIRCLE_NUM; i++) { ofCircle(position[i], 20); }}

応用: さらにリアルな運動の表現‣ testApp.cpp

Page 61: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

void testApp::setInit(){ // 画面内のランダムな場所と速度を円の数だけ指定 for (int i = 0; i < CIRCLE_NUM; i++) { position[i].x = ofGetWidth()/2; position[i].y = ofGetHeight()/2; velocity[i].set(ofRandom(-30, 30), ofRandom(-30, 30)); force[i].set(0, 0); }}

void testApp::resetForce(){ // 力をリセット for (int i = 0; i < CIRCLE_NUM; i++) { force[i].set(0, 0); }}

void testApp::updateForce(){ // 力の更新 (摩擦) for (int i = 0; i < CIRCLE_NUM; i++) { force[i] = force[i] - velocity[i] * friction; }}

応用: さらにリアルな運動の表現‣ testApp.cpp

Page 62: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

void testApp::updatePos(){ // 円の座標を全て更新 for (int i = 0; i < CIRCLE_NUM; i++) { velocity[i] += force[i]; position[i] += velocity[i]; }}

void testApp::checkBounds(){ // 画面からはみ出たらバウンドさせる for (int i = 0; i < CIRCLE_NUM; i++) { if (position[i].x < 0 || position[i].x > ofGetWidth()) { velocity[i].x *= -1; } if (position[i].y < 0 || position[i].y > ofGetHeight()) { velocity[i].y *= -1; } }}

応用: さらにリアルな運動の表現‣ testApp.cpp

Page 63: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

応用: さらにリアルな運動の表現‣ 動きの勢いが、徐々に摩擦で減速していく

Page 64: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

応用: さらにリアルな運動の表現重力

Page 65: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

応用: さらにリアルな運動の表現‣ 重力 (Gravity) を表現してみる‣ つねに下にむかって、一定の力をかけ続ける

摩擦力

重力

Page 66: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#pragma once

#include "ofMain.h"

class testApp : public ofBaseApp{ public:

... void setInit(); // 初期設定 void resetForce(); // 力をリセット void addForce(ofVec2f force); // 力を加える void updateForce(); // 力を更新 void updatePos(); // 位置の更新 // 画面からはみ出たらバウンドさせる void checkBounds(float xmin, float ymin, float xmax, float ymax); // 位置を枠内に収める void constrain(float xmin, float ymin, float xmax, float ymax); // 描画する円の数を指定 static const int CIRCLE_NUM = 100;

応用: さらにリアルな運動の表現‣ testApp.h

Page 67: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

// 位置ベクトルの配列 ofVec2f position[CIRCLE_NUM]; // 速度ベクトルの配列 ofVec2f velocity[CIRCLE_NUM]; // 力ベクトルの配列 ofVec2f force[CIRCLE_NUM]; // 摩擦係数 float friction = 0.01;}

応用: さらにリアルな運動の表現‣ testApp.h

Page 68: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

#include "testApp.h"

void testApp::setup(){ // 画面基本設定 ofSetFrameRate(60); ofBackground(63); ofSetCircleResolution(32); setInit(); // 円を初期化}

void testApp::update(){ resetForce(); // 力をリセット addForce(ofVec2f(0, 0.5)); // 重力を加える updateForce(); // 力の更新 (摩擦) updatePos(); // 円の座標を全て更新 // 画面からはみ出たらバウンドさせる checkBounds(0, 0, ofGetWidth(), ofGetHeight()); // 枠内に収める constrain(0, 0, ofGetWidth(), ofGetHeight());}

応用: さらにリアルな運動の表現‣ testApp.cpp

Page 69: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

void testApp::draw(){ ofSetHexColor(0x3399cc); // 画面内のランダムな場所を円の数だけ描画 for (int i = 0; i < CIRCLE_NUM; i++) { ofCircle(position[i], 20); }}

void testApp::setInit(){ // 画面内のランダムな場所と速度を円の数だけ指定 for (int i = 0; i < CIRCLE_NUM; i++) { position[i].x = ofGetWidth()/2; position[i].y = ofGetHeight()/2; velocity[i].set(ofRandom(-30, 30), ofRandom(-30, 30)); force[i].set(0, 0); }}

void testApp::resetForce(){ // 力をリセット for (int i = 0; i < CIRCLE_NUM; i++) { force[i].set(0, 0); }}

応用: さらにリアルな運動の表現‣ testApp.cpp

Page 70: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

void testApp::addForce(ofVec2f _force){ // 力を加える for (int i = 0; i < CIRCLE_NUM; i++) { force[i] += _force; }}

void testApp::updateForce(){ // 力の更新 (摩擦) for (int i = 0; i < CIRCLE_NUM; i++) { force[i] = force[i] - velocity[i] * friction; }}

void testApp::updatePos(){ // 円の座標を全て更新 for (int i = 0; i < CIRCLE_NUM; i++) { velocity[i] += force[i]; position[i] += velocity[i]; }}

応用: さらにリアルな運動の表現‣ testApp.cpp

Page 71: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

void testApp::constrain(float xmin, float ymin, float xmax, float ymax){ // 枠内に収める for (int i = 0; i < CIRCLE_NUM; i++) { if (position[i].x < xmin) { position[i].x = xmin; } if (position[i].y < ymin) { position[i].y = ymin; } if (position[i].x > xmax) { position[i].x = xmax; } if (position[i].y > ymax) { position[i].y = ymax; } }}

void testApp::checkBounds(float xmin, float ymin, float xmax, float ymax){ // 画面からはみ出たらバウンドさせる for (int i = 0; i < CIRCLE_NUM; i++) { if (position[i].x < xmin || position[i].x > xmax) { velocity[i].x *= -1; }

応用: さらにリアルな運動の表現‣ testApp.cpp

Page 72: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

if (position[i].y < ymin || position[i].y > ymax) { velocity[i].y *= -1; } }}

応用: さらにリアルな運動の表現‣ testApp.cpp

Page 73: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

応用: さらにリアルな運動の表現‣ リアルな運動が再現される

Page 74: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

応用: さらにリアルな運動の表現‣ 数を大量に増やしてみる!

Page 75: メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション

サンプルファイルのダウンロード‣ 今日は、ここまで!

‣ 全てのサンプルは以下からダウンロードできます‣ https://github.com/tado/tau_ma2_13