前回(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 件のコメント:
コメントを投稿