前回(Three.js)と前々回(box2dweb)につづいてLeapMotionネタです。
今回はmacアプリ。つくるのは前回みたいなシューティングゲームっぽいもの。
openFrameworksを使って
そこにLeapMotionを繋いでみます。
3次元に表示にするのでopenFrameworksアドオンのofxBt を使います。
そして初めてのC++。
参考サイト
- yoppa.org
- superuser -Where do I set DYLD_LIBRARY_PATH on Mac OS X, and is it a good idea?-
- 秘密研究所 -【openFrameworks】C++でLeapMotion-
openFrameworks のプロジェクトにLeapMotionを入れる
入れるところからソースの修正から情報取得まで↑の秘密研究所さんの記事が分かりやすい。
秘密研究所さんありがとう!
僕の場合は
Library not loaded: @loader_path/libLeap.dylib
なんていうエラーが出てしまったので
superuserを参考に「Edit Scheme」から「DYLD_LIBRARY_PATH」を追加。
作るクラス
- testApp.cpp, .h
- openFrameowrksのプロジェクトに最初からあるやつ
- LeapMotion.cpp, .h
- 秘密研究所さんの記事からのコピペ
- Typical.cpp, .h
- 的クラス
- Bullet.cpp, .h
- 弾丸クラス
的 Typical
#include <iostream> #include "ofxBt.h" #include <vector> using namespace std; class Typical{ // property ============================= private: ofxBt::RigidBody body; // method =============================== private: Typical(); static void onDeleteTypical(Typical* typical); static void deleteTypical(Typical* typical); void update_(); void draw_(); ofxBt::RigidBody getBody(); public: static void createTypical(); static void setup(ofxBt::World* world_); static void update(); static void draw(); ~Typical(); }; // 以下、cpp #include "Typical.h" // static =================================== static ofxBt::World* world; static vector<Typical*> typicalList; static vector<Typical*> destroyList; static int insNum; void Typical::createTypical(){ Typical* typical = new Typical(); typicalList.push_back(typical); }; void Typical::setup(ofxBt::World* world_){ world = world_; }; void Typical::update(){ destroyList.clear(); for(int i=0,max=typicalList.size();i<max;i++){ typicalList[i]->update_(); } for(int i=0,max=destroyList.size();i<max;i++){ Typical::deleteTypical(destroyList[i]); } }; void Typical::draw(){ for(int i=0,max=typicalList.size();i<max;i++){ typicalList[i]->update_(); } }; void Typical::onDeleteTypical(Typical* typical){ destroyList.push_back(typical); } void Typical::deleteTypical(Typical* typical){ for(int i=0,max=typicalList.size();i<max;i++){ if(typicalList[i] == typical){ typicalList.erase(typicalList.begin()+i); break; } } world->removeRegidBody(typical->getBody()); // 破棄 delete typical; } // instance =================================== Typical::Typical(){ ofVec3f size = ofVec3f(ofRandom(5, 15), ofRandom(5, 15), ofRandom(5, 15)); ofVec3f pos = ofVec3f(ofRandom(-100, 100), ofRandom(-100, 100), 2000); ofVec2f rot = ofVec2f(ofRandom(0, 90), ofRandom(0, 90)); body = world->addBox(size, pos, rot); body.setMass(0.1); ofLog() << "insNum:" << insNum << ", Typical.construct"; insNum++; }; Typical::~Typical(){ ofLog() << "insNum:" << insNum << ", Typical.destruct"; insNum--; } void Typical::update_(){ body.applyForce(ofVec3f(0, 0, -15)); // 加速 ofVec3f position = body.getPosition(); // 吹っ飛んだら消す if(position.z < 0 || abs(position.z) > 2000 || abs(position.x) > 1000 || abs(position.y) > 1000){ Typical::onDeleteTypical(this); } }; void Typical::draw_(){ }; ofxBt::RigidBody Typical::getBody(){ return body; }
ずっとガベージコレクションのある言語やってたので、delete が新鮮。
メモリリーク起こさないか不安。
弾丸 Bullet
的とほぼいっしょ。
#include <iostream> #include "ofxBt.h" #include <vector> using namespace std; class Bullet{ // property ============================= private: ofxBt::RigidBody body; // method =============================== private: Bullet(int x, int y, ofVec3f direction); static void onDeleteBullet(Bullet* bullet); static void deleteBullet(Bullet* bullet); void update_(); void draw_(); ofxBt::RigidBody getBody(); public: static void createBullet(int x, int y, ofVec3f direction); static void setup(ofxBt::World* world_); static void update(); static void draw(); ~Bullet(); }; // 以下、cpp #include "Bullet.h" // static =================================== static ofxBt::World* world; static vector<Bullet*> bulletList; static vector<Bullet*> destroyList; static int insNum; // 確認用 void Bullet::createBullet(int x, int y, ofVec3f direction){ Bullet* bullet = new Bullet(x, y, direction); bulletList.push_back(bullet); }; void Bullet::setup(ofxBt::World* world_){ world = world_; }; void Bullet::update(){ destroyList.clear(); for(int i=0,max=bulletList.size();i<max;i++){ bulletList[i]->update_(); } for(int i=0,max=destroyList.size();i<max;i++){ Bullet::deleteBullet(destroyList[i]); } }; void Bullet::draw(){ for(int i=0,max=bulletList.size();i<max;i++){ bulletList[i]->update_(); } }; void Bullet::onDeleteBullet(Bullet* bullet){ destroyList.push_back(bullet); } void Bullet::deleteBullet(Bullet* bullet){ for(int i=0,max=bulletList.size();i<max;i++){ if(bulletList[i] == bullet){ bulletList.erase(bulletList.begin()+i); break; } } world->removeRegidBody(bullet->getBody()); // 破棄 delete bullet; } // instance =================================== static int INIT_SPEED = 100000; Bullet::Bullet(int x, int y, ofVec3f direction){ body = world->addSphere(10, ofVec3f(x, y, 0)); body.applyForce(ofVec3f(INIT_SPEED*direction.x, INIT_SPEED * direction.y, INIT_SPEED*direction.z)); insNum++; ofLog() << "insNum:" << insNum << ", Bullet.construct"; }; void Bullet::update_(){ body.applyForce(ofVec3f(0, -300, 0)); ofVec3f position = body.getPosition(); // 吹っ飛んだら消す if(abs(position.z) > 2000 || abs(position.x) > 1000 || abs(position.y) > 1000){ Bullet::onDeleteBullet(this); } }; ofxBt::RigidBody Bullet::getBody(){ return body; } void Bullet::draw_(){ }; // destruct Bullet::~Bullet(){ insNum--; ofLog() << "insNum:" << insNum << ",Bullet.destruct"; }
メイン testApp
#include "ofMain.h" #include "ofxBt.h" #include "Typical.h" #include "Bullet.h" #include <iostream> #include "Leap.h" #include "LeapMotion.h" class testApp : public ofBaseApp{ private: LeapMotion* leapMotion; Leap::Controller* leapController; ofxBt::World* world; ofCamera* cam; 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(int x, int y, int button); void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); }; // 以下、cpp #include "testApp.h" int typicalTiming; //-------------------------------------------------------------- void testApp::setup(){ ofSetFrameRate(60); ofSetVerticalSync(true); ofBackground(30); // 3次元世界 world = new ofxBt::World(); world->setup(ofVec3f(0, 0, 0)); world->setGravity(ofVec3f(0, 0, 0)); // カメラ設定 cam = new ofCamera(); cam->setPosition(0, 0, 0); cam->lookAt(ofVec3f(0, 0, 1)); // leap情報 leapController = new Leap::Controller(); leapMotion = new LeapMotion(); leapController->addListener(*leapMotion); // 物体セットアップ Typical::setup(world); Bullet::setup(world); } //-------------------------------------------------------------- void testApp::update(){ typicalTiming++; // 的生成 if(typicalTiming == 30){ Typical::createTypical(); typicalTiming = 0; } // 弾丸生成 if(typicalTiming % 5 == 0){ // http://taishoh-lab.net/blog/?p=203 より vector<Leap::FingerList> fingers = leapMotion->getFingers(); if(!fingers.empty()){ for(int cnt = 0; cnt < fingers.size();cnt++){ for(int fingerNum=0; fingerNum < fingers[cnt].count();fingerNum++){ Leap::Finger finger = fingers[cnt][fingerNum]; Leap::Vector pt = finger.tipPosition(); Leap::Vector direction = finger.direction(); //なんとなく*2 pt.x = pt.x*2 * -1; pt.y = (pt.y - 200)*2; Bullet::createBullet(pt.x, pt.y, ofVec3f(-direction.x, direction.y, -direction.z)); } } } } Typical::update(); Bullet::update(); world->update(); } //-------------------------------------------------------------- void testApp::draw(){ cam->begin(); world->draw(); cam->end(); }
openFrameworks シンプルでいいなー。
openFrameworksまとめ
初めて使ったけどいい感じ。
直接書いていく感じが分かりやすい。AS3の時にBitmapに書いてた感じと似てる気がする。
アドオンも充実してて、box2dやOpenCVなんかもある。
なんとなくの知識でけっこう高度なことができそうな気がする。
そしてiphoneアプリでも使える!
C++まとめ
生成と破棄のタイミングが分からない。コピーってなんだ
vector<Typical> typicalList; void Typical::createTypical(){ Typical typical(); // ここで生成して typicalList.push_back(typical); // コピーされる // typicalはここのスコープを抜けた時に破棄される }
とするとTypicalが二回生成されてしまう。
そして、コピーされるときに呼ばれるのがコピーコンストラクタっていうやつ。
良く分からん。。
int とか float とかのプリミティブの扱いと一緒なのかな。
※をつける
vector<Typical*> typicalList; void Typical::createTypical(){ Typical* typical = new Typical(currentId++); typicalList.push_back(typical); };
とすると、いつもの感じでいける。
結論:良くわからないけど、とりあえず※つけとこう
vectorからの削除ってどうするんだ
for(int i=0,max=bulletList.size();i<max;i++){ if(bulletList[i] == bullet){ bulletList.erase(bulletList.begin()+i); break; } } delete bullet;
ググっても分からなかった。
削除はこれであってるのかな。
0 件のコメント:
コメントを投稿