[work 7] field of force

[work 7] field of force

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
	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 <random>

#include "Mover.hpp"


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:
    Mover *m[MOVER_MAX];
    ofVec2f gravity;
    ofVec2f wind;
    float repulsion;
    float tx, ty;
};
#include "ofApp.h"


ofApp::ofApp(){
    for (int i = 0; i < MOVER_MAX; i++) {
        m[i] = new Mover(ofRandom(0.5, 2), ofRandom(255), ofGetWidth() / 2, ofGetHeight() / 2);
    }
}

ofApp::~ofApp(){
    for (int i = 0; i < MOVER_MAX; i++) {
        delete m[i];
    }
}

//--------------------------------------------------------------
void ofApp::setup(){
    double fps = 30;
    
    ofSetFrameRate(fps);
    ofBackground(0,0,0);
    ofSetBackgroundAuto(true);
    
    gravity = ofVec2f(0, 0);
    wind = ofVec2f(0, 0);
    repulsion = 100;
    
    tx = 0;
    ty = 10000;
}

//--------------------------------------------------------------
void ofApp::update(){
    tx += 0.01;
    ty += 0.01;
    wind = ofVec2f(ofMap(ofSignedNoise(tx), -1, 1, -0.15, 0.15), ofMap(ofSignedNoise(ty), -1, 1, -0.05, 0.05));
    
    for (int i = 0; i < MOVER_MAX; i++) {
        
        // repulsion of wall
        ofVec2f location = m[i]->getPos();
        m[i]->applyForce(ofVec2f(repulsion / (location.x * 2.0), repulsion / (location.y * 2.0)));
        m[i]->applyForce(ofVec2f(-1 * repulsion / ((ofGetWidth() - location.x) * 2.0), -1 * repulsion / ((ofGetHeight() - location.y) * 2.0)));
        
        // gravity
        m[i]->applyForce(gravity);
        
        // wind
        m[i]->applyForce(wind);
        
        m[i]->update();
    }
}


//--------------------------------------------------------------
void ofApp::draw(){
    for (int i = 0; i < MOVER_MAX; i++) {
        m[i]->display();
    }
}
#ifndef Mover_hpp
#define Mover_hpp

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

#define MOVER_MAX (150)

class Mover {
public:
    Mover();
    Mover(float m, float h, float x, float y);
    ~Mover();
    void update();
    bool checkEdges();
    void applyForce(ofVec2f force);
    ofVec2f getPos();
    ofVec2f getVelocity();
    void display();
    
private:
    ofVec2f location;
    ofVec2f velocity;
    ofVec2f acceleration;
    float radius;
    float mass;
    float hue;
};

#endif /* Mover_hpp */
#include "Mover.hpp"


Mover::Mover()
{
    location = ofVec2f(ofGetWidth() / 2, ofGetHeight() / 2);
    velocity = ofVec2f(0, 0);
    acceleration = ofVec2f(0, 0);
    radius = 10;
    mass = 1;
}

Mover::Mover(float m, float h, float x, float y)
{
    location = ofVec2f(x, y);
    velocity = ofVec2f(0, 0);
    acceleration = ofVec2f(0, 0);
    radius = 20;
    mass = m;
    hue = h;
}


Mover::~Mover()
{
    
}


void Mover::update()
{
    velocity += acceleration;
    location += velocity;
    if (checkEdges() != false) {
        velocity += acceleration;
        location += velocity;
    }
    acceleration *= 0;
}


bool Mover::checkEdges()
{
    bool result = false;
    
    if ((int)(location.x + radius) >= ofGetWidth()) {
        location.x = ofGetWidth() - radius;
        applyForce(ofVec2f(mass * velocity.x * -2, 0));
        result = true;
    } else if ((int)(location.x - radius) <= 0) {
        location.x = radius;
        applyForce(ofVec2f(mass * velocity.x * -2, 0));
        result = true;
    }
    
    if ((int)(location.y + radius) >= ofGetHeight()) {
        location.y = ofGetHeight() - radius;
        applyForce(ofVec2f(0, mass * velocity.y * -2));
        result = true;
    } else if ((int)(location.y - radius) <= 0) {
        location.y = radius;
        applyForce(ofVec2f(0, mass * velocity.y * -2));
        result = true;
    }
    
    return result;
}


void Mover::applyForce(ofVec2f force)
{
    acceleration += force / mass;
}


ofVec2f Mover::getPos()
{
    return location;
}


ofVec2f Mover::getVelocity()
{
    return velocity;
}


void Mover::display()
{
    ofColor c;
    c.setHsb(hue, 128, 255, 128);
    ofSetColor(c);
    ofDrawCircle(location.x, location.y, mass * radius);
}

Link to the API reference page

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

categoryAPI
openframeworksofVec2f