not good but great

プログラミング、アート、映画・本の感想について書きます。

openFrameworksでクラスを作成して、個々のパーティクルに異なる大きさ、速度、色を設定する

demo


パーティクルが中心から様々な方向に動いていくものを作りました。クラスを作成する練習として作りました。

オブジェクト指向でつくる

前回のコードを修正

前回、ベクトルを使ってパーティクルを動かしました。
位置・速度ベクトルを使ってパーティクルを動かす - not good but great

個々のパーティクルの大きさや位置、色を変えてみたかったのでクラスを作成し、書き直すことにしました。

・参考
メディア・アートII 第3回 openFrameworks基礎 OOoF : オブジェクト指向 oF

クラス作成

Particle.h

#pragma once

#include "ofMain.h"
class Particle{
public:
    void setup();
    void update();
    void draw();
    
    //RGB
    int r,g,b;
    //半径
    int radius;
    
    //位置ベクトル
    ofVec2f position;
    
    //速度ベクトル
    ofVec2f velocity;
};

クラス名はParticleにしました。

Particle.cpp setup()

#include "Particle.h"

void Particle::setup(){
    //半径
    radius = ofRandom(10, 25);
    
    //円の位置
    position.x = ofGetWidth() / 2;
    position.y = ofGetHeight() / 2;
    velocity.x = ofRandom(-10, 10);
    velocity.y = ofRandom(-10, 10);
    
    //円の色
    r = (ABS(velocity.x)) * 20;
    g = (ABS(velocity.y)) * 20;
    b = (ABS(velocity.x) + ABS(velocity.x)) * 20;
}

色を速度ベクトルに基づいて定義しました。これで最初に大体同じ方向に進むパーティクルは似たような色になります。

Particle.cpp update()

void Particle::update(){
    //円の座標を更新
    position += velocity;
    
    //画面の外枠
    if(position.x - radius < 0 || position.x + radius > ofGetWidth()){
        velocity.x *= -1;
    }
    
    if(position.y  - radius < 0 || position.y + radius > ofGetHeight()){
        velocity.y *= -1;
    }
}

今回は半径も考慮した跳ね返り条件で作りました。

Particle.cpp draw()

void Particle::draw(){
    ofSetColor(r, g, b);
    //ランダムな位置に円を描画
    ofCircle(position, radius);
}

r,g,bはsetupの時に決められた定数なので、各パーティクルが異なる色となります。速度ベクトルによっては同じ色になるものもあります。

インスタンス生成

ofApp.h

static const int CIRCLE_NUM = 100;
    
//位置ベクトル
Particle particle[CIRCLE_NUM];

クラスから配列を生成します。

ofApp.cpp

void ofApp::setup(){
    //基本設定
    ofSetFrameRate(60);
    ofBackground(0xecf0f1);
    ofSetCircleResolution(32);
    
    //円の位置
    for(int i = 0;i < CIRCLE_NUM;i++){
        particle[i].setup();
    }
}

//--------------------------------------------------------------
void ofApp::update(){
    //円の座標を更新
    for(int i = 0;i < CIRCLE_NUM;i++){
        particle[i].update();
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    //ランダムな位置に円を描画
    for(int i = 0;i < CIRCLE_NUM;i++){
        particle[i].draw();
    }
}

クラスで定義しているので、記述が楽になりました。

反省

Particleクラスのメソッド名とメインクラスのメソッド名が同じなのでごっちゃになるかもしれなかったことです。