gotutiyan’s blog

競技プログラミングをやったりopenframeworksでお絵かきをしたりしています。

収縮リング

円周上に配置された四角が収縮します。題名は普通に。


四角を三角関数を使って円周上に配置しています。この円の大きさは変数radiusで設定されていて、これも三角関数で変化させています。この時sinの値は-1~1ですが、都合上マイナスの値は要らないので、1を足すことで0~2に範囲をずらしています。

また、四角の個数は変数numが持っていて、円が中心で一瞬合わさった時に5~30の範囲でランダムに変化しています。そして変化する度に360度を個数で割ることで、全ての四角が円周上で均等に配置されるように並べ直しています。

座標系の移動は、最初にofTranslate(ofGetWidth()/2,ofGetHeight()/2)で画面中央に移動させた後、各四角を円周上に並べるための円周上の点x,y座標を算出して、そこに追加でofTranslate(x,y)します。
このようにして座標系を移動させれば、原点が四角を描く位置に来るので、ofDrawRectangle(-size/2,-size/2,size,size)で四角の中心が原点に来るように描きます。

ぱっと見 簡単な動きをしていますが、いざ実装すると案外やることが多いなあという印象でした。

#include "ofApp.h"
#define rep(i,j,k) for(int i=j;i<k;i++)

int num=12; //numは四角の個数を表す

class PIC{
    float deg,x,y;
    float size,rotate;
    
    
public:
    float radius;
    //初期化関数
    void init(float edeg){
        deg=edeg;
        //sin(deg)^2+cos(deg)^2=1を利用して単位円を構成、それをradius倍して円周を作る
        float x=cos(deg*DEG_TO_RAD)*radius;
        float y=sin(deg*DEG_TO_RAD)*radius;
        rotate=0;
        radius=0;
        size=50;
    }
    
    void move(){
        rotate++;
        //radiusはフレーム数をラジアンとする三角関数で変化
        radius=(1+sin((ofGetFrameNum())*DEG_TO_RAD))*100;
        float x=cos(deg*DEG_TO_RAD)*radius;
        float y=sin(deg*DEG_TO_RAD)*radius;
        
        ofPushMatrix();
        //四角単体で回転させるためのところ
        ofTranslate(x,y);
        ofRotate(rotate);
        ofDrawRectangle(-size/2,-size/2,size,size);
        
        ofPopMatrix();
    }
};
//この配列vに、描かれる四角が格納される
vector<PIC> v(num);
void ofApp::setup(){
    ofSetFrameRate(60);
    ofSetBackgroundColor(0);
    ofSetColor(255);
    ofSetCircleResolution(32);
    ofNoFill();
    
    rep(i,0,num){
        v[i].init((360/num)*i);
    }
}

void ofApp::update(){
    
}

void ofApp::draw(){
    ofTranslate(ofGetWidth()/2,ofGetHeight()/2);
    
    //全ての四角が中心で合わさったという判定は、結局radiusが0になった時と同値
    if(v[0].radius==0){
        num=ofRandom(5,30);
        //配列の数をresizeで変更して、全て初期化
        v.resize(num);
        rep(i,0,num){
            v[i].init((360.0/num)*i);
        }
    }
    //実際に描きます
    rep(i,0,num){
        v[i].move();
    }
}