メディア・アートII 第2回
openFrameworks基礎
配列、くりかえし、乱数
ベクトルを使用したアニメーション
2013年9月16日
多摩美術大学情報デザイン学科メディア芸術コース
田所淳
本日の内容
‣ openFrameworksのプログラムの基礎
‣ 今後の作品制作のための基礎体力をつけていきます!
‣ 乱数(ランダム)
‣ 配列とくりかえし
‣ 条件分岐
‣ ベクトルを使用した運動の表現
‣ 大量の物体を動かす
本日の内容
‣ ただ、プログラミングを書き写すだけではつまらない…
‣ クイズ形式で進めてみます!
準備
‣ まずは、先週の復習
‣ 新規プロジェクトの生成 - ProjectGeneratorの使い方
Q1: 乱数について
Q1: 乱数について
‣ ランダム(規則性のない)場所に、静止した円を描きなさい
‣ プログラムを実行するたびに、違う場所に描かれるように
‣ ヒント:
‣ 円を描く - ofCircle(x, y, radius);
‣ ランダムな数を生成 ...
#include "testApp.h"
void testApp::setup(){
// 画面基本設定
ofSetFrameRate(60);
ofBackground(63);
ofSetCircleResolution(32);
}
v...
Q1: 解答
Q1: 乱数について - 解答
‣ setup() であらかじめランダムな座標を生成しておく
‣ 生成した座標は、グローバルな変数に格納 (testApp.hに)
‣ その変数の値を参照して、draw() で円を描く
#pragma once
#include "ofMain.h"
class testApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
...
/...
#include "testApp.h"
void testApp::setup(){
// 画面基本設定
ofSetFrameRate(60);
ofBackground(63);
ofSetCircleResolution(32);
// ...
Q1: 乱数について - 解答
‣ 実行するたびに、ランダムな場所に円が描かれる
Q2: たくさんの図形をランダムな場所に描く
Q2: たくさんの図形をランダムな場所に描く
‣ 100個の静止した円をランダムな場所に描く
‣ 半径は40pxで統一
Q2: たくさんの図形をランダムな場所に描く
‣ ヒント 1: 配列 - たくさんの値を保存する
‣ 例えば、100個のposXを保存するための「箱」は以下のように
したら準備できる
‣ この箱には、[] で囲まれた部分に連番でナンバリングされ...
Q2: たくさんの図形をランダムな場所に描く
‣ ヒント 2: くりかえし
‣ for文を使用する
‣ 例えば、0∼99の100回くりかえす構文
‣ カウンタ変数 i を賢く利用する
for (int i = 0; i < 100; i++) ...
Q2: 解答
#pragma once
#include "ofMain.h"
class testApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
...
/...
#include "testApp.h"
void testApp::setup(){
// 画面基本設定
ofSetFrameRate(60);
ofBackground(63);
ofSetCircleResolution(32);
// ...
Q2: 解答
‣ 100個の円が、ランダムな場所に描かれる
Q2: 解答
‣ 参考:
‣ 数を変更したい場合、いろいろ修正箇所あり
‣ 1箇所だけを変更すると、数がすぐに変更できるようにしたい!
‣ testApp.hに、クラスの定数(const)として数を指定する
‣ 正式には、静的メンバ変数による定...
#pragma once
#include "ofMain.h"
class testApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
...
/...
#include "testApp.h"
void testApp::setup(){
// 画面基本設定
ofSetFrameRate(60);
ofBackground(63);
ofSetCircleResolution(32);
// ...
Q2: 解答
‣ 例: 円の数を、100 → 400個に
Q3: たくさんの図形をアニメーション
Q3: たくさんの図形をアニメーション
‣ 次に表示するプログラムを改造して、100個の円が同時に動き
まわるアニメーションにする
‣ 開始位置と、円の移動速度と方向はランダムに
#pragma once
#include "ofMain.h"
class testApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
...
/...
#include "testApp.h"
void testApp::setup(){
// 画面基本設定
ofSetFrameRate(60);
ofBackground(63);
ofSetCircleResolution(32);
// ...
void testApp::draw(){
ofSetHexColor(0x3399cc);
// 円を描画
ofCircle(positionX, positionY, 20);
}
Q3: たくさんの図形をアニメーション
‣ ヒントプログラ...
Q3: たくさんの図形をアニメーション
‣ ヒント: 位置と速度をそれぞれ配列にする
‣ 定数を定義して、数はすぐに変更できるように
‣ static const int CIRCLE_NUM
‣ positionX[CIRCLE_NUM]
‣...
Q3: 解答
#pragma once
#include "ofMain.h"
class testApp : public ofBaseApp{
public:
...
// 描画する円の数を指定
static const int CIRCLE_NUM =...
#include "testApp.h"
void testApp::setup(){
// 画面基本設定
ofSetFrameRate(60);
ofBackground(63);
ofSetCircleResolution(32);
// ...
// 画面からはみ出たらバウンドさせる
if (posX[i] < 0 || posX[i] > ofGetWidth()) {
speedX[i] *= -1;
}
if (posY[i] < 0 || posY[i] > ofGetHeig...
Q3: 解答
‣ 100個の円が、同時に動く(はず!)
ベクトルによる運動の表現
ベクトルによる運動の表現
‣ ここまでの、(x, y)座標それぞれに変数を用意する方法
‣ ビギナー的表現
‣ より運動を表現するための高度な書式をマスターしたい
‣ 「ベクトル (Vector)」を理解する!
ベクトルによる運動の表現
‣ ベクトル = 幾何学的空間における、大きさと向きを持った量
ベクトルによる運動の表現
‣ 例: 原点(0,0)から(2,3)の座標までのベクトル
‣ このベクトルは、OA = (2,3) と記述される
→
ベクトルによる運動の表現
‣ ベクトルは、足し算することができる
‣ 例: a = (-2,3) と b = (4,2) の2つのベクトルを足す
‣ a + b = (-2+4,3+2) = (2,5)
ベクトルによる運動の表現
‣ ベクトルは、引き算も可能
‣ 例: a = (-2, 3) , b = (4, 2)
‣ a - b = (-2-4,3-2) = (-6,1)
ベクトルによる運動の表現
‣ 位置ベクトル
‣ いままで扱ってきた2次元平面の座標 (x, y) は、原点 (0, 0) を始
点としたベクトルと捉えることができる → 位置ベクトル
ベクトルによる運動の表現
‣ 速度ベクトル
‣ 「速度 (velocity)」とは、単位時間あたりの物体の移動の変位
‣ 日常的な「速さ (speed)」と「速度 (velocity)」を区分する
‣ 1フレームごとの座標の変化 = 向きと大き...
ベクトルによる運動の表現
‣ openFrameworksで、ベクトルを表現
‣ 2次元のベクトルは「ofVec2f」を使用する
‣ 例:位置ベクトルと速度ベクトルの宣言
‣ 「ベクトル名.x」「ベクトル名.y」: ベクトルの、x方向の成分
と...
Q4: ベクトルで運動を表現する
Q4: ベクトルで運動を表現する
‣ Q3 で作成した、たくさんの図形を動かすサンプルを、ベクト
ル(ofVec2f)で書き直してみる
‣ ヒント:100個ぶんの位置ベクトルと速度ベクトルは以下のよ
うに宣言される
// 描画する円の数を指定
...
Q4: 解答
#pragma once
#include "ofMain.h"
class testApp : public ofBaseApp{
public:
...
// 描画する円の数を指定
static const int CIRCLE_NUM =...
#include "testApp.h"
void testApp::setup(){
// 画面基本設定
ofSetFrameRate(60);
ofBackground(63);
ofSetCircleResolution(32);
// ...
if (position[i].y < 0 || position[i].y > ofGetHeight()) {
velocity[i].y *= -1;
}
}
}
void testApp::draw(){
ofSetHexColor(0...
Q4: 解答
‣ おなじ運動が、とてもすっきりと記述できた!!
応用: さらにリアルな運動の表現
摩擦力
応用: さらにリアルな運動の表現
‣ 摩擦力 (Friction) を表現してみる
‣ 摩擦力 = その物体の進行方向逆向きに働く力
速度ベクトル
摩擦力
応用: さらにリアルな運動の表現
‣ 摩擦力を加えた運動の計算アルゴリズム
円の位置と初期速度を設定
力をリセット
摩擦力を加味した力を更新
力から速度を計算、座標を更新
画面からはみ出ていないかチェック
応用: さらにリアルな運動の表現
‣ プログラムの可読性を高める工夫
‣ 処理のかたまりを「関数 (function) 」としてまとめる
応用: さらにリアルな運動の表現
‣ 関数 (function)
‣ 引数 (ひきすう, argument) - 関数に渡す値 (入力)
‣ 返り値 (return value) - 関数が返す値 (出力)
関数
引数1 引数2 引数3
戻り値
応用: さらにリアルな運動の表現
‣ C++での関数の書き方
‣ 例えば、int型の数の二乗を計算する関数
‣ もし戻り値がない関数の場合、戻り値の型は「void」にする
戻り値の型 名前空間::関数名(引数1, 引数2, 引数3...){
関...
応用: さらにリアルな運動の表現
‣ 先程の処理の流れを以下の関数として定義
void setInit();
void resetForce();
void updateForce();
void updatePos();
void check...
#pragma once
#include "ofMain.h"
class testApp : public ofBaseApp{
public:
...
void setInit(); // 初期設定
void resetForce(); ...
...
void testApp::setup(){
// 画面基本設定
ofSetFrameRate(60);
ofBackground(63);
ofSetCircleResolution(32);
setInit(); // 円を初期化
...
void testApp::setInit(){
// 画面内のランダムな場所と速度を円の数だけ指定
for (int i = 0; i < CIRCLE_NUM; i++) {
position[i].x = ofGetWidth()/2;
...
void testApp::updatePos(){
// 円の座標を全て更新
for (int i = 0; i < CIRCLE_NUM; i++) {
velocity[i] += force[i];
position[i] += vel...
応用: さらにリアルな運動の表現
‣ 動きの勢いが、徐々に摩擦で減速していく
応用: さらにリアルな運動の表現
重力
応用: さらにリアルな運動の表現
‣ 重力 (Gravity) を表現してみる
‣ つねに下にむかって、一定の力をかけ続ける
摩擦力
重力
#pragma once
#include "ofMain.h"
class testApp : public ofBaseApp{
public:
...
void setInit(); // 初期設定
void resetForce(); ...
// 位置ベクトルの配列
ofVec2f position[CIRCLE_NUM];
// 速度ベクトルの配列
ofVec2f velocity[CIRCLE_NUM];
// 力ベクトルの配列
ofVec2f force[CIRCLE_NUM...
#include "testApp.h"
void testApp::setup(){
// 画面基本設定
ofSetFrameRate(60);
ofBackground(63);
ofSetCircleResolution(32);
set...
void testApp::draw(){
ofSetHexColor(0x3399cc);
// 画面内のランダムな場所を円の数だけ描画
for (int i = 0; i < CIRCLE_NUM; i++) {
ofCircle(posi...
void testApp::addForce(ofVec2f _force){
// 力を加える
for (int i = 0; i < CIRCLE_NUM; i++) {
force[i] += _force;
}
}
void testA...
void testApp::constrain(float xmin, float ymin, float xmax, float ymax){
// 枠内に収める
for (int i = 0; i < CIRCLE_NUM; i++) {
...
if (position[i].y < ymin || position[i].y > ymax) {
velocity[i].y *= -1;
}
}
}
応用: さらにリアルな運動の表現
‣ testApp.cpp
応用: さらにリアルな運動の表現
‣ リアルな運動が再現される
応用: さらにリアルな運動の表現
‣ 数を大量に増やしてみる!
サンプルファイルのダウンロード
‣ 今日は、ここまで!
‣ 全てのサンプルは以下からダウンロードできます
‣ https://github.com/tado/tau_ma2_13
Upcoming SlideShare
Loading in...5
×

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

7,683

Published on

0 Comments
15 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
7,683
On Slideshare
0
From Embeds
0
Number of Embeds
10
Actions
Shares
0
Downloads
77
Comments
0
Likes
15
Embeds 0
No embeds

No notes for slide

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

  1. 1. メディア・アートII 第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション 2013年9月16日 多摩美術大学情報デザイン学科メディア芸術コース 田所淳
  2. 2. 本日の内容 ‣ openFrameworksのプログラムの基礎 ‣ 今後の作品制作のための基礎体力をつけていきます! ‣ 乱数(ランダム) ‣ 配列とくりかえし ‣ 条件分岐 ‣ ベクトルを使用した運動の表現 ‣ 大量の物体を動かす
  3. 3. 本日の内容 ‣ ただ、プログラミングを書き写すだけではつまらない… ‣ クイズ形式で進めてみます!
  4. 4. 準備 ‣ まずは、先週の復習 ‣ 新規プロジェクトの生成 - ProjectGeneratorの使い方
  5. 5. Q1: 乱数について
  6. 6. Q1: 乱数について ‣ ランダム(規則性のない)場所に、静止した円を描きなさい ‣ プログラムを実行するたびに、違う場所に描かれるように ‣ ヒント: ‣ 円を描く - ofCircle(x, y, radius); ‣ ランダムな数を生成 - ofRandom(min, max);
  7. 7. #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 ‣ どうなるか、実験してみる
  8. 8. Q1: 解答
  9. 9. Q1: 乱数について - 解答 ‣ setup() であらかじめランダムな座標を生成しておく ‣ 生成した座標は、グローバルな変数に格納 (testApp.hに) ‣ その変数の値を参照して、draw() で円を描く
  10. 10. #pragma once #include "ofMain.h" class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); ... // 円の位置 float posX; float posY; }; Q1: 乱数について - 解答 ‣ testApp.h
  11. 11. #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
  12. 12. Q1: 乱数について - 解答 ‣ 実行するたびに、ランダムな場所に円が描かれる
  13. 13. Q2: たくさんの図形をランダムな場所に描く
  14. 14. Q2: たくさんの図形をランダムな場所に描く ‣ 100個の静止した円をランダムな場所に描く ‣ 半径は40pxで統一
  15. 15. Q2: たくさんの図形をランダムな場所に描く ‣ ヒント 1: 配列 - たくさんの値を保存する ‣ 例えば、100個のposXを保存するための「箱」は以下のように したら準備できる ‣ この箱には、[] で囲まれた部分に連番でナンバリングされる ‣ この仕組みで、100個の、posXとposYが確保できる float posX[100]; posX[0] posX[1] posX[2] ... posX[99] ← 0から開始する ← 0∼99までで100個ぶん
  16. 16. 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] = ????; }
  17. 17. Q2: 解答
  18. 18. #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
  19. 19. #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
  20. 20. Q2: 解答 ‣ 100個の円が、ランダムな場所に描かれる
  21. 21. Q2: 解答 ‣ 参考: ‣ 数を変更したい場合、いろいろ修正箇所あり ‣ 1箇所だけを変更すると、数がすぐに変更できるようにしたい! ‣ testApp.hに、クラスの定数(const)として数を指定する ‣ 正式には、静的メンバ変数による定数 ‣ クラスの定数は、以下のような書式になる ‣ 例: 定数「CIRCLE_NUM」を100と定義 static const int 変数名 = 値; static const int CIRCLE_NUM = 100;
  22. 22. #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
  23. 23. #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
  24. 24. Q2: 解答 ‣ 例: 円の数を、100 → 400個に
  25. 25. Q3: たくさんの図形をアニメーション
  26. 26. Q3: たくさんの図形をアニメーション ‣ 次に表示するプログラムを改造して、100個の円が同時に動き まわるアニメーションにする ‣ 開始位置と、円の移動速度と方向はランダムに
  27. 27. #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
  28. 28. #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
  29. 29. void testApp::draw(){ ofSetHexColor(0x3399cc); // 円を描画 ofCircle(positionX, positionY, 20); } Q3: たくさんの図形をアニメーション ‣ ヒントプログラム: testApp.cpp
  30. 30. Q3: たくさんの図形をアニメーション ‣ ヒント: 位置と速度をそれぞれ配列にする ‣ 定数を定義して、数はすぐに変更できるように ‣ static const int CIRCLE_NUM ‣ positionX[CIRCLE_NUM] ‣ positionY[CIRCLE_NUM] ‣ velocity X[CIRCLE_NUM] ‣ velocityY[CIRCLE_NUM] ‣ 最初の位置と速度、座標の変更、描画、すべての処理をくりか えして100回行う → for文
  31. 31. Q3: 解答
  32. 32. #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
  33. 33. #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
  34. 34. // 画面からはみ出たらバウンドさせる 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
  35. 35. Q3: 解答 ‣ 100個の円が、同時に動く(はず!)
  36. 36. ベクトルによる運動の表現
  37. 37. ベクトルによる運動の表現 ‣ ここまでの、(x, y)座標それぞれに変数を用意する方法 ‣ ビギナー的表現 ‣ より運動を表現するための高度な書式をマスターしたい ‣ 「ベクトル (Vector)」を理解する!
  38. 38. ベクトルによる運動の表現 ‣ ベクトル = 幾何学的空間における、大きさと向きを持った量
  39. 39. ベクトルによる運動の表現 ‣ 例: 原点(0,0)から(2,3)の座標までのベクトル ‣ このベクトルは、OA = (2,3) と記述される →
  40. 40. ベクトルによる運動の表現 ‣ ベクトルは、足し算することができる ‣ 例: a = (-2,3) と b = (4,2) の2つのベクトルを足す ‣ a + b = (-2+4,3+2) = (2,5)
  41. 41. ベクトルによる運動の表現 ‣ ベクトルは、引き算も可能 ‣ 例: a = (-2, 3) , b = (4, 2) ‣ a - b = (-2-4,3-2) = (-6,1)
  42. 42. ベクトルによる運動の表現 ‣ 位置ベクトル ‣ いままで扱ってきた2次元平面の座標 (x, y) は、原点 (0, 0) を始 点としたベクトルと捉えることができる → 位置ベクトル
  43. 43. ベクトルによる運動の表現 ‣ 速度ベクトル ‣ 「速度 (velocity)」とは、単位時間あたりの物体の移動の変位 ‣ 日常的な「速さ (speed)」と「速度 (velocity)」を区分する ‣ 1フレームごとの座標の変化 = 向きと大きさをもった「速度ベ クトル」 位置ベクトル a 位置ベクトル b 速度ベクトル
  44. 44. ベクトルによる運動の表現 ‣ 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に
  45. 45. Q4: ベクトルで運動を表現する
  46. 46. Q4: ベクトルで運動を表現する ‣ Q3 で作成した、たくさんの図形を動かすサンプルを、ベクト ル(ofVec2f)で書き直してみる ‣ ヒント:100個ぶんの位置ベクトルと速度ベクトルは以下のよ うに宣言される // 描画する円の数を指定 static const int CIRCLE_NUM = 100; // 位置ベクトルの配列 ofVec2f position[CIRCLE_NUM]; // 速度ベクトルの配列 ofVec2f velocity[CIRCLE_NUM];
  47. 47. Q4: 解答
  48. 48. #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
  49. 49. #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
  50. 50. 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
  51. 51. Q4: 解答 ‣ おなじ運動が、とてもすっきりと記述できた!!
  52. 52. 応用: さらにリアルな運動の表現 摩擦力
  53. 53. 応用: さらにリアルな運動の表現 ‣ 摩擦力 (Friction) を表現してみる ‣ 摩擦力 = その物体の進行方向逆向きに働く力 速度ベクトル 摩擦力
  54. 54. 応用: さらにリアルな運動の表現 ‣ 摩擦力を加えた運動の計算アルゴリズム 円の位置と初期速度を設定 力をリセット 摩擦力を加味した力を更新 力から速度を計算、座標を更新 画面からはみ出ていないかチェック
  55. 55. 応用: さらにリアルな運動の表現 ‣ プログラムの可読性を高める工夫 ‣ 処理のかたまりを「関数 (function) 」としてまとめる
  56. 56. 応用: さらにリアルな運動の表現 ‣ 関数 (function) ‣ 引数 (ひきすう, argument) - 関数に渡す値 (入力) ‣ 返り値 (return value) - 関数が返す値 (出力) 関数 引数1 引数2 引数3 戻り値
  57. 57. 応用: さらにリアルな運動の表現 ‣ C++での関数の書き方 ‣ 例えば、int型の数の二乗を計算する関数 ‣ もし戻り値がない関数の場合、戻り値の型は「void」にする 戻り値の型 名前空間::関数名(引数1, 引数2, 引数3...){ 関数の処理の内容 } int testApp::poweroftwo(int a){ ! return a * a; }
  58. 58. 応用: さらにリアルな運動の表現 ‣ 先程の処理の流れを以下の関数として定義 void setInit(); void resetForce(); void updateForce(); void updatePos(); void checkBounds();
  59. 59. #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
  60. 60. ... 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
  61. 61. 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
  62. 62. 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
  63. 63. 応用: さらにリアルな運動の表現 ‣ 動きの勢いが、徐々に摩擦で減速していく
  64. 64. 応用: さらにリアルな運動の表現 重力
  65. 65. 応用: さらにリアルな運動の表現 ‣ 重力 (Gravity) を表現してみる ‣ つねに下にむかって、一定の力をかけ続ける 摩擦力 重力
  66. 66. #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
  67. 67. // 位置ベクトルの配列 ofVec2f position[CIRCLE_NUM]; // 速度ベクトルの配列 ofVec2f velocity[CIRCLE_NUM]; // 力ベクトルの配列 ofVec2f force[CIRCLE_NUM]; // 摩擦係数 float friction = 0.01; } 応用: さらにリアルな運動の表現 ‣ testApp.h
  68. 68. #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
  69. 69. 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
  70. 70. 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
  71. 71. 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
  72. 72. if (position[i].y < ymin || position[i].y > ymax) { velocity[i].y *= -1; } } } 応用: さらにリアルな運動の表現 ‣ testApp.cpp
  73. 73. 応用: さらにリアルな運動の表現 ‣ リアルな運動が再現される
  74. 74. 応用: さらにリアルな運動の表現 ‣ 数を大量に増やしてみる!
  75. 75. サンプルファイルのダウンロード ‣ 今日は、ここまで! ‣ 全てのサンプルは以下からダウンロードできます ‣ https://github.com/tado/tau_ma2_13
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×