Particleクラス
ただのofCircleによる円描画ですが、色々と遊びの要素を入れています。
testAppクラス
メインのクラスで、oscによるメッセージを受け取ります。
今回はTouchOSCというiPhoneのフリーの
アプリからOSCで送られてくる情報をもとに、Particleクラスに対して色々とアクションを投げかけています。
Particle.h
// // Particle.h // emptyExample // // Created by jonki on 12/11/08. // Copyright (c) 2012年 jonki.net. All rights reserved. // #ifndef PARTICLE_H_ #define PARTICLE_H_ #include "ofMain.h" class Particle { public: Particle(float x, float w); void update(); void draw(); void setTargetPosition(int x, int y); void expand(); inline void setRadius(float radius) { m_radius = radius; }; inline void setAlpha(float alpha) { m_alpha = alpha; }; private: float m_x; //!< particle x position float m_y; //!< particle y position float m_expand; //!< radius expand param ofPoint m_speed; //!< particle speed float m_radius; //!< particle radius float m_alpha; //!< particle color alpha ofPoint m_targetPos; //!< destination for moving bool m_isSetTargetPos; //!< check new targetPos is set }; #endif
Particle.cpp
// // Particle.cpp // emptyExample // // Created by jonki on 12/11/08. // Copyright (c) 2012年 jonki.net. All rights reserved. // #include "Particle.h" Particle::Particle(float x, float y) : m_x(x) , m_y(y) , m_speed(ofPoint(ofRandom(-8.f, 8.f), ofRandom(-5.f, 5.f))) , m_radius(0.3f) , m_alpha(1.f) , m_targetPos(ofPoint(0.f, 0.f)) , m_isSetTargetPos(false) { } void Particle::update() { //!< 画面端に出たらバウンドするように if(m_x > (float)ofGetWidth() || m_x < 0.f) { m_speed.x *= -1; } if(m_y > (float)ofGetHeight() || m_y < 0.f) { m_speed.y *= -1; } //!< 新しい目標座標がセットされてたら if(m_isSetTargetPos) { //!< 目標座標へ1割近づく計算 m_speed.x = 0.9f * m_speed.x + 0.1f * (m_targetPos.x - m_x); m_speed.y = 0.9f * m_speed.y + 0.1f * (m_targetPos.y - m_y); //!< なんとなく遅くしてみる m_speed.x *= 0.5f; m_speed.y *= 0.5f; m_isSetTargetPos = false; } //!< 目標座標に近づける、乱数もちょっと足してばらけさせる m_x += (m_speed.x + ofRandom(-6.f, 6.f)); m_y += (m_speed.y + ofRandom(-6.f, 6.f)); //!< 5%ずつ減衰するようにする m_expand *= 0.95f; if (m_expand < 1.f) m_expand = 1.f; } void Particle::draw() { //!< 色とかの情報をこの中だけに適用する //!< 適用範囲が他のクラスなどに影響しないので、とりあえずかけておくべし ofPushStyle(); { //!< 座標に応じたシャレ乙カラーリング //!< ofMapは値を好みの範囲にマッピングした値を返す //!< ofMap(inVal, inMaxVal, inMaxVal, outMinVal, outMaxVal) int r = ofMap(m_x, 0, ofGetWidth(), 0, 255); int g = ofMap(m_y, 0, ofGetHeight(), 0, 255); int b = 100; ofSetColor(r, g, b, 255.f * m_alpha); ofPushMatrix(); //!< glPushMatrix()的な { //!< particleのポジションはofTranslateで決めるようにする //!< ofCircleのパラメタで指定しても良い ofTranslate(m_x, m_y); ofCircle(0.f, 0.f, ofRandom(20.f, 40.f) * m_radius * m_expand); } ofPopMatrix(); } ofPopStyle(); } void Particle::setTargetPosition(int x, int y) { m_targetPos.x = x; m_targetPos.y = y; m_isSetTargetPos = true; } void Particle::expand() { //!< particleの一気に半径が4.5倍になる //!< m_expandはupdate()で減衰し、最終的には1.fになる m_expand = 4.5f; }
testApp.h
#include "ofMain.h" #include "ofxOsc.h" #include "Particle.h" #include <vector> typedef std::vector<Particle*>::iterator p_itr; class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void exit(); 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(int x, int y, int button); void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); private: std::vector<Particle*> m_particles; ofxOscReceiver m_receiver; ofSoundPlayer m_se; ofSoundPlayer m_bgm; };
testApp.cpp
//-------------------------------------------------------------- void testApp::setup(){ ofSetFrameRate(60); ofBackground(0, 0, 0); ofEnableAlphaBlending(); for (int i=0; i<100; i++) { m_particles.push_back(new Particle(ofRandom(ofGetWidth()), ofRandom(ofGetHeight()))); } //!< set PORT m_receiver.setup(9000); } //-------------------------------------------------------------- void testApp::update(){ for(p_itr it = m_particles.begin(); it != m_particles.end(); ++it) { (*it)->update(); } while(m_receiver.hasWaitingMessages()) { ofxOscMessage msg; m_receiver.getNextMessage(&msg); //!< ex) addr => "/1/push3" string addr = msg.getAddress(); //!< TouchOSCのアドレスに合わせる std::vector<string>splitAddr = ofSplitString(addr, "/"); if(splitAddr.size() != 3) break; //!< "/1/push/3" => addrIndex = 1 int addrIndex = ofToInt(splitAddr[1]); //!< button address std::vector<string>splitCommand = ofSplitString(splitAddr[2], "push"); if(splitCommand.size() == 2) //!< ex) "/1/push3" { m_se.loadSound("se/" + splitCommand[1] + ".mp3"); //!< unkode m_se.play(); for(p_itr it = m_particles.begin(); it != m_particles.end(); ++it) { (*it)->expand(); } break; //!< 処理するアドレスは1個だけ } //!< fader address splitCommand = ofSplitString(splitAddr[2], "fader"); if(splitCommand.size() == 2) { int num = ofToInt(splitCommand[1]); if (num == 1) { for(p_itr it = m_particles.begin(); it != m_particles.end(); ++it) { (*it)->setAlpha(msg.getArgAsFloat(0)); } } else if (num == 2) { for(p_itr it = m_particles.begin(); it != m_particles.end(); ++it) { (*it)->setRadius(msg.getArgAsFloat(0)); } } break; //!< 処理するアドレスは1個だけ } //!< xy position address if(splitAddr[2] == "xy") { float x = msg.getArgAsFloat(1) * ofGetWidth(); float y = (1.f - msg.getArgAsFloat(0)) * ofGetHeight(); for(p_itr it = m_particles.begin(); it != m_particles.end(); ++it) { (*it)->setTargetPosition(x, y); } break; //!< 処理するアドレスは1個だけ } } } //-------------------------------------------------------------- void testApp::draw(){ for(p_itr it = m_particles.begin(); it != m_particles.end(); ++it) { (*it)->draw(); } } void testApp::exit() { for(p_itr it = m_particles.begin(); it != m_particles.end(); ++it) { delete (*it); *it = 0; } } //-------------------------------------------------------------- void testApp::keyPressed(int key){ switch ((char)key) { case 'f': ofToggleFullscreen(); break; } } //-------------------------------------------------------------- void testApp::mouseDragged(int x, int y, int button){ for(p_itr it = m_particles.begin(); it != m_particles.end(); ++it) { (*it)->setTargetPosition(x, y); } }