物理エンジン Box2D
提供:kuhalaboWiki
(版間での差分)
(→動的配列でマウスクリックで生成) |
(→動的配列で動的に生成) |
||
74行: | 74行: | ||
'''setPhysics()'''で力学属性を設定するが、これを省略すると、場所が固定された障壁のような働きをする。 | '''setPhysics()'''で力学属性を設定するが、これを省略すると、場所が固定された障壁のような働きをする。 | ||
− | == | + | == 動的配列で生成 == |
;ofApp.h | ;ofApp.h | ||
* Box2Dでは、動的配列に'''vector'''ではなく、'''vector <ofPtr >'''を使う | * Box2Dでは、動的配列に'''vector'''ではなく、'''vector <ofPtr >'''を使う | ||
106行: | 106行: | ||
box.setPhysics(2.0, 0.9, 1.5); // 四角の物理パラメータを設定 (重さ、反発係数、摩擦係数) | box.setPhysics(2.0, 0.9, 1.5); // 四角の物理パラメータを設定 (重さ、反発係数、摩擦係数) | ||
box.setup(box2d.getWorld(), ofGetWidth() / 3.0, 200, 100, 40); // 四角を物理世界に追く | box.setup(box2d.getWorld(), ofGetWidth() / 3.0, 200, 100, 40); // 四角を物理世界に追く | ||
− | + | wall.setup(box2d.getWorld(), ofGetWidth() / 2.0, 500, 300, 10); // 壁を物理世界に追く。物理パラメータはない | |
} | } | ||
158行: | 158行: | ||
} | } | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | == 互いに万有引力で引き付け合う == | ||
+ | ;ofApp.h | ||
+ | * すべての個体同士は、addAttractivePointで引き合う。 | ||
+ | <pre> | ||
+ | #pragma once | ||
+ | |||
+ | #include "ofMain.h" | ||
+ | #include "ofxBox2d.h" | ||
+ | |||
+ | class ofApp : public ofBaseApp{ | ||
+ | |||
+ | 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); | ||
+ | |||
+ | ofxBox2d box2d; // Box2Dの世界 | ||
+ | |||
+ | vector <ofPtr <ofxBox2dCircle> > circles; // Box2d円の動的配列 | ||
+ | vector <ofPtr <ofxBox2dRect> > boxes; // Box2d四角の動的配列 | ||
+ | }; | ||
+ | </pre> | ||
+ | |||
+ | ;ofApp.cpp | ||
+ | <pre> | ||
+ | //-------------------------------------------------------------- | ||
+ | void ofApp::setup(){ | ||
+ | |||
+ | ofSetFrameRate(60); | ||
+ | ofSetCircleResolution(64); | ||
+ | ofBackground(0); | ||
+ | |||
+ | // Box2Dの世界の設定 | ||
+ | box2d.init(); // 初期化 | ||
+ | box2d.setGravity(0, 0); // 重力 (方向、強さ) | ||
+ | box2d.createBounds(); // 画面の周囲に壁を作成 | ||
+ | box2d.setFPS(30.0); // box2Dの世界でのFPS | ||
+ | box2d.registerGrabbing(); // 物体をつかめるようにする | ||
+ | } | ||
+ | |||
+ | //-------------------------------------------------------------- | ||
+ | void ofApp::update(){ | ||
+ | box2d.update(); // box2Dの更新 | ||
+ | int cn = circles.size(); | ||
+ | int bn = boxes.size(); | ||
+ | |||
+ | for( int i = 0; i < cn; i++){ | ||
+ | circles[i].get()->update(); | ||
+ | for(int j = 0; j < i; j++){ | ||
+ | circles[i].get()->addAttractionPoint(circles[j].get()->getPosition(), 0.1); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | for( int i = 0; i < bn; i++){ | ||
+ | boxes[i].get()->update(); | ||
+ | for(int j = 0; j < i; j++){ | ||
+ | boxes[i].get()->addAttractionPoint(boxes[j].get()->getPosition(), 0.1); | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | //-------------------------------------------------------------- | ||
+ | void ofApp::draw(){ | ||
+ | ofSetColor(127, 255, 0); | ||
+ | for(int i=0; i<circles.size(); i++){ | ||
+ | ofFill(); | ||
+ | ofSetColor(0, 127, 255); | ||
+ | circles[i].get()->draw(); // 円の描画 | ||
+ | } | ||
+ | for(int i=0; i<boxes.size(); i++){ | ||
+ | ofFill(); | ||
+ | ofSetColor(255, 127, 0); | ||
+ | boxes[i].get()->draw(); // 円の描画 | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //-------------------------------------------------------------- | ||
+ | void ofApp::keyPressed(int key){ | ||
+ | } | ||
+ | |||
+ | //-------------------------------------------------------------- | ||
+ | void ofApp::keyReleased(int key){ | ||
+ | if( key == 'c' ){ // キーcを押すと、円が生成される | ||
+ | float r = ofRandom(3,10); | ||
+ | circles.push_back(ofPtr<ofxBox2dCircle>(new ofxBox2dCircle)); | ||
+ | circles.back().get()->setPhysics(r * r, 0.7, 0.2); | ||
+ | circles.back().get()->setup(box2d.getWorld(), ofRandom(ofGetWidth()), ofRandom(ofGetHeight()), r); | ||
+ | circles.back().get()->setVelocity(ofRandom(-5,5),ofRandom(-5,5)); //初期速度の設定 | ||
+ | } | ||
+ | if( key == 'b' ){// キーbを押すと、四角が生成される | ||
+ | float w = ofRandom(3,10); | ||
+ | float h = ofRandom(3,10); | ||
+ | boxes.push_back(ofPtr<ofxBox2dRect>(new ofxBox2dRect)); | ||
+ | boxes.back().get()->setPhysics(w * h, 0.7, 0.2); | ||
+ | boxes.back().get()->setup(box2d.getWorld(), ofRandom(ofGetWidth()), ofRandom(ofGetHeight()), w, h); | ||
+ | boxes.back().get()->setVelocity(ofRandom(-5,5),ofRandom(-5,5));//初期速度の設定 | ||
+ | } | ||
+ | } | ||
+ | |||
</pre> | </pre> | ||
2014年11月25日 (火) 06:23時点における版
目次 |
入手
https://github.com/vanderlin/ofxBox2d
- zipボタンをクリックし、ファイル一式をダンロード
- 作成された「ofxBox2D-master」フォルダーを「ofxBox2D」に名称変更し、addonsフォルダーに移動する。
- projectGeneratorでBox2Dアドオンを選択する。
エラー対策
Visual Studioのバージョンによっては、Box2Dのコンパイル時に以下のエラーの出ることがあります。
エラー 4 error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. f:\of_v0.8.4_vs_release\addons\ofxbox2d\libs\triangle\triangle_impl.hpp
そんなときは、以下の設定変更で解決します。
- プロジェクトのプロパティ
- 構成プロパティ―「C/C++」―「すべてのオプション」-「SDLチェック」を「いいえ」にする。
単体の円と四角
- ofApp.h
ヘッダーの初めにBox2Dのヘッダーをインクルードする。
#include "ofxBox2d.h"
Box2dの変数を宣言する。
ofxBox2d box2d; // Box2Dの世界 ofxBox2dCircle circle; // 円 ofxBox2dRect box; // 四角 ofxBox2dRect wall; // 壁
- ofApp.cpp
void ofApp::setup(){ ofSetFrameRate(60); ofBackground(0); // Box2Dの世界の設定 box2d.init(); // 初期化 box2d.setGravity(0, 1); // 重力 (方向、強さ) box2d.createBounds(); // 画面の周囲に壁を作成 box2d.setFPS(30.0); // box2Dの世界でのFPS box2d.registerGrabbing(); // 物体をつかめるようにする circle.setPhysics(2.0, 0.9, 1.5); // 円の物理パラメータを設定 (重さ、反発係数、摩擦係数) circle.setup(box2d.getWorld(), ofGetWidth() / 2.0, 100, 40); // 円を物理世界に追く box.setPhysics(2.0, 0.9, 1.5); // 四角の物理パラメータを設定 (重さ、反発係数、摩擦係数) box.setup(box2d.getWorld(), ofGetWidth() / 3.0, 200, 100, 40); // 四角を物理世界に追く wall.setup(box2d.getWorld(), ofGetWidth() / 2.0, 500, 300, 10); // 壁を物理世界に追く。物理パラメータはない } //-------------------------------------------------------------- void ofApp::update(){ box2d.update(); // box2Dの更新 } //-------------------------------------------------------------- void ofApp::draw(){ ofSetColor(0, 127, 255); circle.draw(); // 円の描画 ofSetColor(255, 127, 0); box.draw(); // 四角の描画 ofSetColor(127, 255, 0); wall.draw(); // 壁の描画 }
setPhysics()で力学属性を設定するが、これを省略すると、場所が固定された障壁のような働きをする。
動的配列で生成
- ofApp.h
- Box2Dでは、動的配列にvectorではなく、vector <ofPtr >を使う
- キーcを押すと、円が生成され、キーbを押すと、四角が生成される。
ofxBox2d box2d; // Box2Dの世界 ofxBox2dCircle circle; // 円 ofxBox2dRect box; // 四角 ofxBox2dRect wall; // 壁 vector <ofPtr <ofxBox2dCircle> > circles; // Box2d円の動的配列 vector <ofPtr <ofxBox2dRect> > boxes; // Box2d四角の動的配列
- ofApp.cpp
void ofApp::setup(){ ofSetFrameRate(60); ofBackground(0); // Box2Dの世界の設定 box2d.init(); // 初期化 box2d.setGravity(0, 1); // 重力 (方向、強さ) box2d.createBounds(); // 画面の周囲に壁を作成 box2d.setFPS(30.0); // box2Dの世界でのFPS box2d.registerGrabbing(); // 物体をつかめるようにする circle.setPhysics(2.0, 0.9, 1.5); // 円の物理パラメータを設定 (重さ、反発係数、摩擦係数) circle.setup(box2d.getWorld(), ofGetWidth() / 2.0, 100, 40); // 円を物理世界に追く box.setPhysics(2.0, 0.9, 1.5); // 四角の物理パラメータを設定 (重さ、反発係数、摩擦係数) box.setup(box2d.getWorld(), ofGetWidth() / 3.0, 200, 100, 40); // 四角を物理世界に追く wall.setup(box2d.getWorld(), ofGetWidth() / 2.0, 500, 300, 10); // 壁を物理世界に追く。物理パラメータはない } //-------------------------------------------------------------- void ofApp::update(){ box2d.update(); // box2Dの更新 } //-------------------------------------------------------------- void ofApp::draw(){ ofSetColor(0, 127, 255); circle.draw(); // 円の描画 ofSetColor(255, 127, 0); box.draw(); // 四角の描画 ofSetColor(127, 255, 0); wall.draw(); // 壁の描画 for(int i=0; i<circles.size(); i++){ ofFill(); ofSetColor(0, 127, 255); circles[i].get()->draw(); // 円の描画 } for(int i=0; i<boxes.size(); i++){ ofFill(); ofSetColor(255, 127, 0); boxes[i].get()->draw(); // 円の描画 } } //-------------------------------------------------------------- void ofApp::keyPressed(int key){ } //-------------------------------------------------------------- void ofApp::keyReleased(int key){ if( key == 'c' ){ // キーcを押すと、円が生成される float r = ofRandom(10,30); circles.push_back(ofPtr<ofxBox2dCircle>(new ofxBox2dCircle)); circles.back().get()->setPhysics(3.0, 0.99, 0.1); circles.back().get()->setup(box2d.getWorld(), ofRandom(ofGetWidth()), ofRandom(ofGetHeight()), r); circles.back().get()->setVelocity(ofRandom(-5,5),ofRandom(-5,5)); //初期速度の設定 } if( key == 'b' ){// キーbを押すと、四角が生成される float w = ofRandom(10,30); float h = ofRandom(10,30); boxes.push_back(ofPtr<ofxBox2dRect>(new ofxBox2dRect)); boxes.back().get()->setPhysics(3.0, 0.99, 0.1); boxes.back().get()->setup(box2d.getWorld(), ofRandom(ofGetWidth()), ofRandom(ofGetHeight()), w, h); boxes.back().get()->setVelocity(ofRandom(-5,5),ofRandom(-5,5));//初期速度の設定 } }
互いに万有引力で引き付け合う
- ofApp.h
- すべての個体同士は、addAttractivePointで引き合う。
#pragma once #include "ofMain.h" #include "ofxBox2d.h" class ofApp : public ofBaseApp{ 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); ofxBox2d box2d; // Box2Dの世界 vector <ofPtr <ofxBox2dCircle> > circles; // Box2d円の動的配列 vector <ofPtr <ofxBox2dRect> > boxes; // Box2d四角の動的配列 };
- ofApp.cpp
//-------------------------------------------------------------- void ofApp::setup(){ ofSetFrameRate(60); ofSetCircleResolution(64); ofBackground(0); // Box2Dの世界の設定 box2d.init(); // 初期化 box2d.setGravity(0, 0); // 重力 (方向、強さ) box2d.createBounds(); // 画面の周囲に壁を作成 box2d.setFPS(30.0); // box2Dの世界でのFPS box2d.registerGrabbing(); // 物体をつかめるようにする } //-------------------------------------------------------------- void ofApp::update(){ box2d.update(); // box2Dの更新 int cn = circles.size(); int bn = boxes.size(); for( int i = 0; i < cn; i++){ circles[i].get()->update(); for(int j = 0; j < i; j++){ circles[i].get()->addAttractionPoint(circles[j].get()->getPosition(), 0.1); } } for( int i = 0; i < bn; i++){ boxes[i].get()->update(); for(int j = 0; j < i; j++){ boxes[i].get()->addAttractionPoint(boxes[j].get()->getPosition(), 0.1); } } } //-------------------------------------------------------------- void ofApp::draw(){ ofSetColor(127, 255, 0); for(int i=0; i<circles.size(); i++){ ofFill(); ofSetColor(0, 127, 255); circles[i].get()->draw(); // 円の描画 } for(int i=0; i<boxes.size(); i++){ ofFill(); ofSetColor(255, 127, 0); boxes[i].get()->draw(); // 円の描画 } } //-------------------------------------------------------------- void ofApp::keyPressed(int key){ } //-------------------------------------------------------------- void ofApp::keyReleased(int key){ if( key == 'c' ){ // キーcを押すと、円が生成される float r = ofRandom(3,10); circles.push_back(ofPtr<ofxBox2dCircle>(new ofxBox2dCircle)); circles.back().get()->setPhysics(r * r, 0.7, 0.2); circles.back().get()->setup(box2d.getWorld(), ofRandom(ofGetWidth()), ofRandom(ofGetHeight()), r); circles.back().get()->setVelocity(ofRandom(-5,5),ofRandom(-5,5)); //初期速度の設定 } if( key == 'b' ){// キーbを押すと、四角が生成される float w = ofRandom(3,10); float h = ofRandom(3,10); boxes.push_back(ofPtr<ofxBox2dRect>(new ofxBox2dRect)); boxes.back().get()->setPhysics(w * h, 0.7, 0.2); boxes.back().get()->setup(box2d.getWorld(), ofRandom(ofGetWidth()), ofRandom(ofGetHeight()), w, h); boxes.back().get()->setVelocity(ofRandom(-5,5),ofRandom(-5,5));//初期速度の設定 } }