前橋工科大学 - デザイン演習 II 2020
「家具の映像」制作チュートリアル (1)
制作に必要なもの
- ノートPC
- Processing
- もし持っていなければ下記からインストール
- https://processing.org/
「家具の映像」をどう実現するか
- 再生方法 → フルスクリーンで
- 方法は直接レクチャー
- 生活を遮らないもの
- ゆっくりとした変化
- 絶えず変化しつづける
- 同じパターンの繰り返しは避ける → ランダム
- 色合いの工夫 : HSBによる指定
Processingの基本の確認
- setup() 初期設定 : 最初に1度だけ実行される
- draw() 描画 : 一定間隔でくりかえし実行、繰り返す速さ : fps (frame per second)
code_01 : シンプルなアニメーションのサンプル
//変数
float x, y;
void setup(){
size(1920, 1080);
frameRate(30);
//変数の初期化
x = 0;
y = height/2;
}
void draw(){
background(0);
fill(31, 127, 255);
ellipse(x, y, 100, 100);
//変数を更新してアニメーション
x = x + 5;
}

ランダム
- ランダム : 規則性の無い数、範囲を指定して使用する
- random(100) : 0 ~ 100のランダムな数
- random(100, 200) : 100 ~ 200のランダムな数
code_02 : ランダムな場所にランダムな大きさの円を描く
void setup(){
size(1920, 1080);
frameRate(30);
//最初に背景を1度だけ塗る
background(0);
}
void draw(){
//ランダムな座標と大きさを生成
float x = random(width);
float y = random(height);
float diameter = random(20, 200);
//円を描く
noStroke();
fill(31, 127, 255, 128);
ellipse(x, y, diameter, diameter);
}

色彩について
- RGBで色彩をコントロールするのは難しい
code_03 : RGBのランダム
void setup(){
size(1920, 1080);
frameRate(30);
//最初に背景を1度だけ塗る
background(0);
}
void draw(){
//ランダムな座標と大きさを生成
float x = random(width);
float y = random(height);
float diameter = random(20, 200);
//円を描く
noStroke();
//RGBのランダム
fill(random(256), random(256), random(256), 128);
ellipse(x, y, diameter, diameter);
}

- RGBではなくHSBカラーモードを使用する、HSB = Hue(色相)、Saturation(彩度)、Brightness(明度)
code_04 : HSBのランダム
void setup(){
size(1920, 1080);
frameRate(30);
//カラーをHSBモードに
colorMode(HSB, 360, 100, 100, 100);
//最初に背景を1度だけ塗る
background(0);
}
void draw(){
//ランダムな座標と大きさを生成
float x = random(width);
float y = random(height);
float diameter = random(20, 200);
//円を描く
noStroke();
//HSBでランダムな色彩を生成
fill(random(100, 200), 80, 90, 70);
ellipse(x, y, diameter, diameter);
}

物体の数を制限する : 繰り返しとリスト
- 現状では永遠に円が増殖してしまう
- 一定の数で制限することはできないだろうか?
- 繰り返し (for文) とリストを利用する
- x, y, diameter をそれぞれリスト(floatList)に
- 指定した数を超えたらリストの先頭の要素を消去する
code_05 : リストと繰り返しで最大数を制限
FloatList x;
FloatList y;
FloatList diameter;
FloatList hue;
void setup() {
size(1920, 1080);
frameRate(30);
//カラーをHSBモードに
colorMode(HSB, 360, 100, 100, 100);
//リストを初期化
x = new FloatList();
y = new FloatList();
diameter = new FloatList();
hue = new FloatList();
}
void draw() {
background(0);
//ランダムな値をリストに追加
x.append(random(width));
y.append(random(height));
diameter.append(random(100, 400));
hue.append(random(100, 200));
//最大数を100に限定
if(x.size() > 100){
//先頭の要素を消去
x.remove(0);
y.remove(0);
diameter.remove(0);
hue.remove(0);
}
//リストの数だけ繰り返し
for (int i = 0; i < x.size(); i++) {
//円を描く
noStroke();
//HSBでランダムな色彩を生成
fill(hue.get(i), 80, 90, 50);
ellipse(x.get(i), y.get(i), diameter.get(i), diameter.get(i));
}
}

要素をクラスへ
- だいぶプログラムが煩雑になってきた
- パラメータ毎にリストがあるのはちょっと煩雑
- 「ランダムな円」という要素を独立したプログラムへ → クラス
code_06 : クラス化した増殖する円
ArrayList<Dot> dots = new ArrayList<Dot>();
void setup() {
size(1920, 1080);
frameRate(60);
//カラーをHSBモードに
colorMode(HSB, 360, 100, 100, 100);
}
void draw() {
background(0);
//1秒に1回追加
if(frameCount % 60 == 0){
//Dotをリストに追加
dots.add(new Dot());
}
//最大数を100に限定
if(dots.size() > 100){
//先頭の要素を消去
dots.remove(0);
}
//リストの数だけ繰り返し
for (int i = 0; i < dots.size(); i++) {
//円を描く
dots.get(i).draw();
}
}
class Dot {
float x, y, diameter, hue;
Dot(){
x = random(width);
y = random(height);
diameter = random(100, 400);
hue = random(100, 200);
}
void draw(){
noStroke();
fill(hue, 80, 90, 50);
ellipse(x, y, diameter, diameter);
}
}
個別のオブジェクトを動かす
- 円をクラス化すれば、個別にアニメーションさせることも簡単にできる
- 例えばゆっくりと膨張しながら薄くなっていく円
code_07 : 膨張しながらフェードアウトする円
ArrayList<Dot> dots = new ArrayList<Dot>();
void setup() {
size(1920, 1080);
frameRate(60);
//カラーをHSBモードに
colorMode(HSB, 360, 100, 100, 100);
}
void draw() {
background(0);
//1秒に1回追加
if (frameCount % 60 == 0) {
//Dotをリストに追加
dots.add(new Dot());
}
//リストの数だけ繰り返し
for (int i = 0; i < dots.size(); i++) {
//もし透明度が0より小さかったら消去
if (dots.get(i).alpha < 0) {
dots.remove(i);
}
//円を描く
dots.get(i).draw();
}
}
class Dot {
float x, y, diameter, speed, hue, alpha, alphaSpeed;
Dot() {
x = random(width);
y = random(height);
diameter = 0;
hue = random(100, 200);
alpha = 100;
speed = random(0.2, 0.8);
alphaSpeed = random(0.05, 0.1);
}
void draw() {
noStroke();
fill(hue, 80, 90, alpha);
ellipse(x, y, diameter, diameter);
diameter += speed;
alpha -= alphaSpeed;
}
}

応用1 : 色相をシフトさせる
- それぞれの円の色相を少しずつ変化させてみる
code_08 : 色相のシフト
ArrayList<Dot> dots = new ArrayList<Dot>();
void setup() {
size(1920, 1080);
frameRate(60);
//カラーをHSBモードに
colorMode(HSB, 360, 100, 100, 100);
}
void draw() {
background(0);
//4秒に1回追加
if (frameCount % 240 == 0) {
//Dotをリストに追加
dots.add(new Dot());
}
//リストの数だけ繰り返し
for (int i = 0; i < dots.size(); i++) {
//もし透明度が0より小さかったら消去
if (dots.get(i).alpha < 0) {
dots.remove(i);
}
//円を描く
dots.get(i).draw();
}
}
class Dot {
float x, y, diameter, speed, hue, alpha, alphaSpeed, hueBase;
Dot() {
x = random(width);
y = random(height);
diameter = 0;
hue = (random(100, 200) + (frameCount / 60.0)) % 360;
alpha = 100;
speed = random(0.1, 0.4);
alphaSpeed = random(0.01, 0.03);
}
void draw() {
noStroke();
fill(hue, 80, 90, alpha);
ellipse(x, y, diameter, diameter);
diameter += speed;
alpha -= alphaSpeed;
}
}

応用2 形を変化させる
code_09 : 円から矩形に
ArrayList<Dot> dots = new ArrayList<Dot>();
void setup() {
size(1920, 1080, P2D);
frameRate(60);
//カラーをHSBモードに
colorMode(HSB, 360, 100, 100, 100);
}
void draw() {
background(0);
//4秒に1回追加
if (frameCount % 240 == 0) {
//Dotをリストに追加
dots.add(new Dot());
}
//リストの数だけ繰り返し
for (int i = 0; i < dots.size(); i++) {
//もし透明度が0より小さかったら消去
if (dots.get(i).alpha < 0) {
dots.remove(i);
}
//円を描く
dots.get(i).draw();
}
}
class Dot {
float x, y, diameter, speed, hue, alpha, alphaSpeed, hueBase;
Dot() {
x = random(width);
y = random(height);
diameter = 0;
hue = (random(100, 200) + (frameCount / 60.0)) % 360;
alpha = 100;
speed = random(0.1, 0.4);
alphaSpeed = random(0.01, 0.03);
}
void draw() {
noStroke();
fill(hue, 60, 100, alpha);
rectMode(CENTER);
rect(x, y, diameter, diameter);
diameter += speed;
alpha -= alphaSpeed;
}
}

応用3 違う動きに
- 高さを画面いっぱいにした矩形を左右に動かす
- 左右の辺に到達したら折り返す
- アルファの値を変化させて色の重なりを楽しむ
code_10 : 重なる矩形
ArrayList<Rect> rects = new ArrayList<Rect>();
void setup() {
size(1920, 1080);
frameRate(60);
//カラーをHSBモードに
colorMode(HSB, 360, 100, 100, 100);
}
void draw() {
background(0, 0, 70);
//4秒に1回追加
if (frameCount % 240 == 0) {
//Dotをリストに追加
rects.add(new Rect());
}
//リストの数だけ繰り返し
for (int i = 0; i < rects.size(); i++) {
//矩形を描く
rects.get(i).draw();
//もし透明度が0より小さかったら消去
if (rects.get(i).alpha < 0) {
rects.remove(i);
}
}
}
class Rect {
float x, w, speed, hue, alpha, alphaSpeed;
Rect() {
//初期値を設定
w = random(500, 1000);
x = random(-w, width);
speed = random(-0.5, 0.5);
hue = random(360);
alpha = 0;
alphaSpeed = 0.2;
}
void draw() {
noStroke();
fill(hue, 60, 100, alpha);
rect(x, 0, w, height);
x += speed;
//両端で跳ね返り
if (x < -width || x > width) {
speed *= -1;
}
//フェードイン
if(alpha > 100){
alphaSpeed *= 1;
alpha = 100;
}
alpha += alphaSpeed;
}
}
