gotutiyan’s blog

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

掻き分けて、円

マウスカーソルから円が逃げます。


たまにはマウス座標を使おうと思って作りましたが、案外実装が楽で終わってしまったので、移動具合によって色も変えました。numの個数を変えれば敷き詰める円の個数も変わります。

変数を闇雲に作ったのと、三項演算子バリバリのコーディングをしたので少し見にくいかもしれません。
def_x,def_yが、各円の座標の初期値です。ここからどれくらい離れたかで色を変えます。

point_diffは、マウスから逃げる円の、逃げる距離の最大値です。つまり、円はマウス位置からpoint_diffを半径とした円周上まで逃げます。

diff_x,diff_yは、マウス位置と円の中心を比べた時の、x,y座標の差です。この値を使って、point_diffと比べます。

2点間の距離を調べるときには三平方の定理を使うわけですが、一応競技プログラミング界隈の人間なので、別に気にしなくても良い誤差を気にしてsqrt()は使わず、距離の2乗で比較しています。

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

int num=10; //縦横の個数num

class Pic{
public:
    float x,y,r;
    float def_x,def_y;
    float diffx,diffy,point_diff;
    ofColor c;
    void init(float x0,float y0,float r0,float point_diff0){
        x=x0; y=y0; r=r0; point_diff=point_diff0;
        def_x=x; def_y=y;
    }
    
    void move(){
        //元の位置からの距離を測って、その距離をそのままHSBのH要素に
        c.setHsb(ofMap((x-def_x)*(x-def_x)+(y-def_y)*(y-def_y),0,5000,0,255),255,255);
        ofSetColor(c);
        ofDrawCircle(x,y,r);
        float distx=ofGetMouseX()-x, disty=ofGetMouseY()-y;
        
        //円の中心とマウスの距離がpoint_diffより小さい時(逃げるところ)
        if(distx*distx+disty*disty<point_diff*point_diff){
            x+=(distx<0)?0.5:-0.5;
            y+=(disty<0)?0.5:-0.5;
        //逃げた円が元に戻るところ
        }else {
            distx=x-def_x; disty=y-def_y;
            if(distx) x+=(distx<0)?0.2:-0.2;
            if(disty) y+=(disty<0)?0.2:-0.2;
        }
    }
};
vector<vector<Pic>> pic(num,vector<Pic>(num));

void ofApp::setup(){
    ofSetRectMode(OF_RECTMODE_CENTER);
    ofSetFrameRate(60);
    ofSetBackgroundColor(0);
    ofSetColor(255);
    ofSetCircleResolution(64);
    ofNoFill();
    
    //初期化。numの値によって自動で変わるようになっている。
    float pos=ofGetHeight()/num;
    rep(i,0,num)rep(j,0,num)pic[i][j].init(pos/2+pos*i, pos/2+pos*j, pos/2,70);
}

void ofApp::update(){
    
}

void ofApp::draw(){
    rep(i,0,num)rep(j,0,num)pic[i][j].move();
}