[work 24] Box2d study – Stretch a net –

[work 24] Box2d study – Stretch a net –

Movie

Source code

about

  • 円をジョイントでつないで、オブジェクトを捕獲するネット状のものを作成する

file

  • 上部にあるファイル名が表示されているボタンを押すと、表示されるファイルが切り替わります
  • 別ウィンドウ表示したい時や行番号などが無いRawMode表示したい時は、コード内右上のボタンを押してください(ボタンはマウスオーバーすると表示されます)
#include "ofMain.h"
#include "ofApp.h"

//================================
int main( ){

    // 4K:4096x2160
    // 2K:2048x1080
    // FullHD:1920x1080
    // HD:1440x1080
    // HD720p:1280x720
    // DVD:720x480
    // setup the GL context
	ofSetupOpenGL(1280,720, OF_WINDOW);

	// this kicks off the running of my app
	// can be OF_WINDOW or OF_FULLSCREEN
	// pass in width and height too:
	ofRunApp( new ofApp());

}
#pragma once

#include "ofMain.h"


#include "Pair.hpp"
#include "Bridge.hpp"
#include "ofxBox2d.h"


class ofApp : public ofBaseApp{
	public:
    ofApp();
    ~ofApp();
    
		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 mouseEntered(int x, int y);
		void mouseExited(int x, int y);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);
    
private:
    ofxBox2d                              box2d;
    vector <shared_ptr<Pair>>  pairs;
    shared_ptr<Bridge> bridge;
};
#include "ofApp.h"


ofApp::ofApp(){
    
}

ofApp::~ofApp(){
}

//--------------------------------------------------------------
void ofApp::setup(){
    double fps = 30;
    
    ofSetFrameRate(fps);
    ofBackground(115,180,167);
    ofSetBackgroundAuto(true);
    
    // Box2d
    box2d.init();
    box2d.setGravity(0, 10);
    box2d.createGround();
    box2d.setFPS(30.0);
    box2d.registerGrabbing();   // grab object
    
    bridge = std::make_shared<Bridge>();
    bridge.get()->setup(box2d.getWorld());
}

//--------------------------------------------------------------
void ofApp::update(){
    if ((int)ofRandom(10) == 0) {
        pairs.push_back(std::make_shared<Pair>(ofVec2f(ofRandomWidth(), ofRandomHeight()/4)));
        pairs.back().get()->setup(box2d.getWorld());
    }
    
    box2d.update();
    
    auto itr = pairs.begin();
    while (itr != pairs.end()) {
        if ((*itr)->isDead()) {
            itr = pairs.erase(itr);
        } else {
            ++itr;
        }
        
        if (pairs.empty()) {
            break;
        }
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    bridge.get()->display();
    
    for (shared_ptr<Pair> &p : pairs) {
        p->display();
    }
}
#ifndef Pair_hpp
#define Pair_hpp

#include <stdio.h>
#include "ofMain.h"
#include "ofxBox2d.h"


class Pair {
public:
    Pair(ofVec2f org);
    ~Pair();
    void setup(b2World * b2dworld);
    bool isDead();
    void display();
private:
    ofVec2f origin;
    float distance;
    std::shared_ptr<ofxBox2dCircle> p1;
    std::shared_ptr<ofxBox2dCircle> p2;
    std::shared_ptr<ofxBox2dJoint> joint;
};
#endif /* Pair_hpp */
#include "Pair.hpp"



Pair::Pair(ofVec2f org)
{
    origin = org;
    distance = ofRandom(15, 25);
    
    std::cout << "Create pair" << std::endl;
}


Pair::~Pair()
{
    std::cout << "Delete pair" << std::endl;
}


void Pair::setup(b2World * b2dworld)
{
    ofVec2f dir = ofVec2f(ofRandom(1), ofRandom(1));
    dir.normalize();
    ofVec2f loc = origin + (dir * distance);
    p1 = make_shared<ofxBox2dCircle>();
    p1.get()->setPhysics(0.3, 0.3, 0.3);
    p1.get()->setup(b2dworld, origin.x, origin.y, 10);
    p2 = make_shared<ofxBox2dCircle>();
    p2.get()->setPhysics(0.3, 0.3, 0.3);
    p2.get()->setup(b2dworld, loc.x, loc.y, 10);
    
    joint = std::make_shared<ofxBox2dJoint>();
    joint.get()->setup(b2dworld, p1.get()->body, p2.get()->body);
    joint.get()->setLength(distance);
}


bool Pair::isDead()
{
    ofRectangle rect = ofRectangle(0, 0, ofGetWidth(), ofGetHeight());
    
    return !(rect.inside(p1.get()->getPosition()) && rect.inside(p2.get()->getPosition()));
}


void Pair::display()
{
    ofFill();
    ofSetColor(242,249,2);
    p1.get()->draw();
    p2.get()->draw();
    ofSetColor(0);
    joint.get()->draw();
}
#ifndef Bridge_hpp
#define Bridge_hpp

#include <stdio.h>
#include "ofMain.h"
#include "ofxBox2d.h"


class Bridge {
public:
    Bridge();
    ~Bridge();
    void setup(b2World * b2dworld);
    void display();
private:
    std::vector<ofVec2f> anchorLoc;
    std::vector<std::shared_ptr<ofxBox2dRect>> anchor;
    std::vector<std::shared_ptr<ofxBox2dCircle>> log;
    std::vector<std::shared_ptr<ofxBox2dJoint>> joints;
};
#endif /* Bridge_hpp */
#include "Bridge.hpp"


Bridge::Bridge()
{
    anchorLoc.push_back(ofVec2f(10, ofGetHeight()/2));
    anchorLoc.push_back(ofVec2f(ofGetWidth()/2, ofGetHeight()/2));
    anchorLoc.push_back(ofVec2f(ofGetWidth()-10, ofGetHeight()/2));
}


Bridge::~Bridge()
{
    
}


void Bridge::setup(b2World * b2dworld)
{
    for (ofVec2f p : anchorLoc) {
        anchor.push_back(make_shared<ofxBox2dRect>());
        anchor.back().get()->setPhysics(0.0, 0.1, 0.1);
        anchor.back().get()->setup(b2dworld, p.x, p.y, 10, 10);
    }
    
    for (int i = 0; i < anchor.size() - 1; i++) {
        int dist = 10;
        float dump = 0.5;
        float freq = 0;
        int max_idx = (int)(((anchor[i+1]->getPosition().x - anchor[i]->getPosition().x) / dist) - 1);
        ofVec2f p = ofVec2f(anchor[i]->getPosition().x + dist, anchor[i]->getPosition().y);
        
        for (int j = 0; j < max_idx; j++) {
            log.push_back(make_shared<ofxBox2dCircle>());
            log.back().get()->setPhysics(0.5, 0.1, 0.1);
            log.back().get()->setup(b2dworld, p.x, p.y, dist/2);
            p.x += dist;
            
            joints.push_back(std::make_shared<ofxBox2dJoint>());
            if (j == 0) {
                joints.back().get()->setup(b2dworld, anchor[i]->body, log[(max_idx * i) + j]->body);
            } else {
                joints.back().get()->setup(b2dworld, log[(max_idx * i) + j-1]->body, log[(max_idx * i) + j]->body);
            }
            joints.back().get()->setLength(dist);
            joints.back().get()->setDamping(dump);
            joints.back().get()->setFrequency(freq);
        }
        joints.push_back(std::make_shared<ofxBox2dJoint>());
        joints.back().get()->setup(b2dworld, log.back().get()->body, anchor[i+1]->body);
        joints.back().get()->setLength(dist);
        joints.back().get()->setDamping(dump);
        joints.back().get()->setFrequency(freq);
    }
}


void Bridge::display()
{
    for (std::shared_ptr<ofxBox2dJoint> &j : joints) {
        ofFill();
        ofSetColor(243, 54, 153);
        j->draw();
    }
    
    for (std::shared_ptr<ofxBox2dRect> &a : anchor) {
        ofFill();
        ofSetColor(243, 54, 153);
        a->draw();
    }
    
    for (std::shared_ptr<ofxBox2dCircle> &l : log) {
        ofFill();
        ofSetColor(255, 255, 255);
        l->draw();
    }
}

Link to the reference page

ソースコードで使用したAPIの中から要点になりそうなものをいくつか選んでリストアップしました。

categoryAPI/Lib
openframeworksofxBox2d

Development environment

  • openframeworks 0.10.1
  • c++
  • macOS
  • Xcode