2種リング
今まで円の描画はofDrawCircleを使って行っていましたが、この方法では「1つの円の中で複数の色を使う」ことができないので、ほかの方法で円を書いてみることにしました。
色の変わる方向を交互にしたのでこの題名に。
2種リング
— ごつちやん (@gotutiyan_kapi) 2018年4月11日
クリックしたら色変わりますね#openframeworks
コードとその解説は以下から。(今回は詳しめな仕上がりです)https://t.co/3D8bsuo6Gv pic.twitter.com/yjdi7fSdPI
円は、点を打つことでも描くことができます。三角関数で学んだ「単位円」がその代表で、sin^2*cos*2=1を利用して円を描くことができています。この単位円上に点を打っていくことによって、円が完成します。openframeworksは「点を打つ」ことができないので、今回はごく小さな円を描くことで対応しました。クリックすることで色がランダムに変化します。
円1つをクラスで作成し、このインスタンスを2次元に並べています。以下はそのクラスの処理の説明です。
今回は1つの円につき色を2色使っていますが、色の境目がよくわかるように補色にしています。補色は、ある色情報のRGBが(x,y,z)の時、(255-x,255-y,255-z)で表せます。全て255から引くだけです。
また、円をたくさん並べていることから、大きな円を構成するための小さな円があり、もちろんx,y座標の情報を持っています。この小さな円それぞれが持つy座標の値と、大きな円それぞれが持つ色の境目のy座標を示す変数posを比べて、その大小で色を塗り分けます。
三角関数の中身に書いているDEG_TO_RADは、「度数法(degree)からラジアン(radian)に変換する」という意味があるので、for文のループ変数0~359が、0~359度の1周分になっていて、それがラジアンに変換されることで三角関数がうまく働きます。
#include "ofApp.h" #define rep(i,j,k) for(int i=j;i<k;i++) float radius=50; class PIC{ int r,g,b; int x,y; int pos,speed; public : //初期化関数 void init(int i,int j){ x=radius/2+radius*i*2; y=radius/2+radius*j*2; r=ofRandom(255); g=ofRandom(255); b=ofRandom(255); if((i+j)%2){ //色の変化の方向を互い違いにするため、iとjの和の偶奇で分ける pos=radius; speed=-1; }else { pos=-radius; speed=1; } } void move(){ pos+=speed; if(pos<-radius || pos>radius) speed*=-1; rep(i,0,360){ ofPushMatrix(); ofTranslate(x+radius/2,y+radius/2); //DEG_TO_RADで度数法からラジアンへ float x=cos((i)*DEG_TO_RAD)*radius; float y=sin((i)*DEG_TO_RAD)*radius; if(y<pos)ofSetColor(r,g,b); else ofSetColor(255-r,255-g,255-b); //補色を作る ofDrawCircle(x,y,2,2); ofPopMatrix(); } } }; vector<vector<PIC>> v; void ofApp::setup(){ ofSetFrameRate(60); ofSetBackgroundColor(0); ofSetColor(255); ofSetCircleResolution(32); ofFill(); int num=ofGetWidth()/(radius*2); //numは円を書く個数 // vectorをリサイズして使うことで、画面幅や半径が変わっても対応できる(はず) v.resize(num,vector<PIC>(num)); rep(i,0,num) rep(j,0,num) v[i][j].init(i,j); //初期化をします } void ofApp::update(){ } void ofApp::draw(){ int num=ofGetWidth()/(radius*2); rep(i,0,num){ rep(j,0,num){ v[i][j].move(); } } } //クリックしたらinit()を発動させることで色をランダムに変化させる void ofApp::mousePressed(int x, int y, int button){ int num=ofGetWidth()/(radius*2); rep(i,0,num)rep(j,0,num)v[i][j].init(i,j); }