Processingでクレヨンスクラッチもどきをつくる
先日テレビでクレヨンスクラッチをやっていたので、processingで実装してみました。
実際のクレヨンスクラッチは、
1.適当に色つきクレヨンで塗る
2.その上から黒のクレヨンで全体をぬりつぶす
3.クギなどでひっかく
という手順ですが、
Processingでは、
0.「スケッチ」メニュー→ライブラリをインポート→「geomerative」を探す
1.マスクをつくる
2.マスクの中に位置・色ともにランダムに円を描く
という手順になります。
マスクは「geomerative」というライブラリを使いました。重いですが、現状マスクが使える+Illustratorで編集可能なPDFに書き出せるのはこの方法しかないので・・・
こちらはマスクをリング状にしたもの。
こちらはマスクを円形にしたもの。
import geomerative.*; void setup() { size(600,600,P2D); background(0); RG.init(this); noLoop(); } void draw() { //色クレヨンで描いた上から黒クレヨンを塗りつぶす background(0); //引っ掻く回数 for (int i=0; i<50; i++) { //マスクの形 makeCircle(int(random(width)),int(random(height)),int(random(10,200))); } } void makeCircle(int x, int y, int r) { //リング形のマスク、r-は太さ(ここだとstroke(10)と同じ)、引っ掻いた形 RShape mask = RShape.createRing(x, y, r,r-10); /* //円形のマスクにする場合は、createRingではなくcreateCircleを使う RShape mask = RShape.createCircle(x, y, r); */ //画面サイズの半分だとだいたい画面が埋め尽くされる for (int i=0; i<300; i++) { //色クレヨンの色 fill(random(255),random(255),random(255)); //色クレヨンで描いた柄 RShape strip = RShape.createCircle(random(width),random(height),random(10,200)); RShape masked = strip.intersection(mask); masked.setStroke(false); RG.shape(masked); } } //マウスを押すと再描画 void mousePressed() { redraw(); }
Processingで円が重ならないようにランダムに描く
Processingで円が重ならないようにランダムに描きます。
2点間の距離を出す「dist」を使って、2つの円の半径の合計が2点間の距離より小さくなればOKです。
つまり、cとpの2点間の距離 > cの半径+pの半径の場合に描画されます。
processing本家の掲示板にお世話になりました。
//配列準備 ArrayList <PVector> circles; void setup() { background(0); size(600, 600); //色相・彩度・明度で指定 colorMode(HSB, 360, 100, 100); smooth(); noLoop(); } void draw() { background(0); circles = new ArrayList <PVector>(); addCircle(); for (int i=0; i<circles.size(); i++) { PVector p = circles.get(i); noStroke(); fill(int(random(0,360)),100,100); ellipse(p.x, p.y, p.z, p.z); } } void addCircle() { //10は個数 while (circles.size() < 10) { //大きさが10から100の間 float diameter = random(10, 100); PVector c = new PVector(random(width), random(height), diameter); boolean overlapping = false; for (PVector p : circles) { /* distは2点間の距離を出す dist(x1, y1, x2, y2) この場合は、cとpの2点間の距離 > cの半径+pの半径の場合に描画される cとpの2点間の距離 < cの半径+pの半径の場合は重なってしまう */ if (dist(c.x, c.y, p.x, p.y) < (c.z + p.z)) { overlapping = true; break; } } if (!overlapping) { //配列の要素を追加 circles.add(c); } } } //マウスを押すと再描画 void mousePressed() { redraw(); }
Processingで図形の色を特定の色の中からランダムに変える
今回はメモ程度。
例えば、赤・緑・青・黄色の中から1色ランダムに選びます。
条件分岐のswitchと配列を使います。
マウスクリックで色を変更します。
//色ランダム int colrd; void setup() { size(600, 600); background(255); smooth(); noLoop(); } void draw() { background(255); noStroke(); colorRandom(); ellipse(100,100,70,70); } void colorRandom() { color[] c = new color[4]; c[0] = color(15,217,255); c[1] = color(73,232,171); c[2] = color(254,142,167); c[3] = color(255,186,56); colrd = int(random(0, 3)); switch(colrd) { case 0: fill(c[0]); break; case 1: fill(c[1]); break; case 2: fill(c[2]); break; case 3: fill(c[3]); break; } } void mousePressed() { redraw(); }
Processingでランダムに記号を描く2
形と色がランダムに変わるようにしました。
ストライプに関してはforで書いていたのですが、色がうまいこといかなかったので、ひとまずは力技の汚いコードです。
//グリッドのサイズ int gridSize = 50; //ランダムの値 int rd1; //色ランダム int colrd; //繰り返し描画用 int i,j; void setup() { size(400,400); background(0); noLoop(); } void draw() { background(0); for(j = 0; j < height/gridSize+1; j++){ for (i = 0; i < width/gridSize+1; i++) { rd1 = int(random(14)); shapeParts(); /* グリッド線を引きたい場合は下記 noFill(); strokeWeight(1); stroke(0); rect(gridSize * i, gridSize * j, gridSize, gridSize); */ } } strokeWeight(5); fill(0); stroke(255,186,56); rect(gridSize * 4, gridSize * 3, gridSize * 5, gridSize *2); strokeWeight(2); rect(gridSize * 4+9, gridSize * 3+9, gridSize * 5-20, gridSize *2-20); } void shapeParts() { switch(rd1) { case 0: //三角 noStroke(); colorRandom(); triangle(gridSize * i,gridSize * j,gridSize * i,gridSize * j+gridSize,gridSize * i+gridSize,gridSize * j); break; case 1: //リボン noStroke(); colorRandom(); triangle(gridSize * i,gridSize * j,gridSize * i,gridSize * j+gridSize,gridSize * i+gridSize,gridSize * j); triangle(gridSize * i,gridSize * j,gridSize * i+gridSize,gridSize * j+gridSize,gridSize * i+gridSize,gridSize * j); break; case 2: //三角ふたつ1 noStroke(); colorRandom(); triangle(gridSize * i,gridSize * j,gridSize * i+25,gridSize * j+25,gridSize * i+gridSize,gridSize * j); triangle(gridSize * i+25,gridSize * j+25,gridSize * i,gridSize * j+gridSize,gridSize * i+gridSize,gridSize * j+gridSize); break; case 3: //三角ふたつ2 noStroke(); colorRandom(); triangle(gridSize * i,gridSize * j,gridSize * i,gridSize * j+gridSize,gridSize * i+25,gridSize * j+25); triangle(gridSize * i+gridSize,gridSize * j,gridSize * i+25,gridSize * j+25,gridSize * i+gridSize,gridSize * j+gridSize); break; case 4: //円 noStroke(); ellipseMode(CORNER); colorRandom(); ellipse(gridSize * i, gridSize * j, gridSize, gridSize); break; case 5: //円輪郭のみ noStroke(); ellipseMode(CORNER); colorRandom(); ellipse(gridSize * i, gridSize * j, gridSize, gridSize); fill(0); ellipse(gridSize * i+10, gridSize * j+10, gridSize-20, gridSize-20); break; case 6: //四角+円 noStroke(); colorRandom(); rect(gridSize * i, gridSize * j, gridSize, gridSize); fill(0); ellipse(gridSize * i+10, gridSize * j+10, gridSize-20, gridSize-20); break; case 7: //四角輪郭のみ noStroke(); colorRandom(); rect(gridSize * i, gridSize * j, gridSize, gridSize); fill(0); rect(gridSize * i+10, gridSize * j+10, gridSize-20, gridSize-20); break; case 8: //階段 noStroke(); colorRandom(); rect(gridSize * i,gridSize * j+34,17,16); rect(gridSize * i+16,gridSize *+ j+18,17,32); rect(gridSize * i+32,gridSize * j,18,50); break; case 9: //階段 noStroke(); colorRandom(); rect(gridSize * i,gridSize * j+34,16,17); rect(gridSize * i,gridSize * j+17,32,17); rect(gridSize * i,gridSize * j,50,17); break; case 10: //ダイヤ noStroke(); colorRandom(); quad(gridSize * i+25, gridSize * j, gridSize * i, gridSize * j+25, gridSize * i+25, gridSize * j+50, gridSize * i+50, gridSize * j+25); break; case 11: //ストライプ縦 noStroke(); fill(255,186,56); rect(gridSize * i,gridSize * j,10,50); fill(0); rect(gridSize * i+10,gridSize * j,10,50); fill(255,186,56); rect(gridSize * i+20,gridSize * j,10,50); fill(0); rect(gridSize * i+30,gridSize * j,10,50); fill(255,186,56); rect(gridSize * i+40,gridSize * j,10,50); break; case 12: //ストライプ横 noStroke(); fill(255,186,56); rect(gridSize * i,gridSize * j,50,10); fill(0); rect(gridSize * i,gridSize * j+10,50,10); fill(255,186,56); rect(gridSize * i,gridSize * j+20,50,10); fill(0); rect(gridSize * i,gridSize * j+30,50,10); fill(255,186,56); rect(gridSize * i,gridSize * j+40,50,10); break; case 13: noFill(); noStroke(); break; } } void colorRandom() { color[] c = new color[4]; /* c[0] = color(225,211,86); c[1] = color(113,217,254); c[2] = color(49,210,187); c[3] = color(200,120,181); */ c[0] = color(15,217,255); c[1] = color(73,232,171); c[2] = color(254,142,167); c[3] = color(255,186,56); colrd = int(random(0, 3)); switch(colrd) { case 0: fill(c[0]); break; case 1: fill(c[1]); break; case 2: fill(c[2]); break; case 3: fill(c[3]); break; } } //マウスを押して再描画 void mousePressed() { redraw(); }
Pressingで水玉模様を描く
水玉とチェック柄をまとめてみました。書き方は同じで、rect/ellipseを変えるだけです。
水玉模様
//水玉ひとつのサイズ int rSize = 60; int rnum = 600 / rSize; void setup() { size(600, 600); background(255); smooth(); noLoop(); noStroke(); } void draw() { for(int i = 0; i < rnum+1; i++){ for(int j = 0; j < rnum+1; j++){ if ((i + j) % 2 == 0) { noStroke(); noFill(); } else { fill(230,16,16); } ellipse(rSize * j, rSize * i, rSize, rSize); } } }
チェック柄
//チェックひとつのサイズ int rSize = 60; int rnum = 600 / rSize; void setup() { size(600, 600); background(255); smooth(); noLoop(); noStroke(); } void draw() { for(int i = 0; i < rnum+1; i++){ for(int j = 0; j < rnum+1; j++){ if ((i + j) % 2 == 0) { noStroke(); //色あり→赤→色あり→赤のチェックにする場合はここをfill()に変える noFill(); } else { fill(230,16,16); } rect(rSize * j, rSize * i, rSize, rSize); } } }
Processingでランダムに記号を描く
マウスをクリックすると4つの図形と非表示がランダムに切り替わります。
ellipseModeやrectModeを調整するのがちと大変かもですが、さほど難しくありません。
forの使い方をお勉強するのにいいかもしれません。
//グリッドのサイズ int gridSize = 60; //ランダムの値 int rd1; //繰り返し描画用 int i,j; void setup() { size(400,400); background(255); noLoop(); } void draw() { background(255); for(j = 0; j < height/gridSize+1; j++){ for (i = 0; i < width/gridSize+1; i++) { rd1 = int(random(5)); shapeParts(); /* グリッド線を引きたい場合は下記 noFill(); strokeWeight(1); stroke(0); rect(gridSize * i, gridSize * j, gridSize, gridSize); */ } } } void shapeParts() { switch(rd1) { case 0: ellipseMode(CORNER); noStroke(); fill(134,169,251); ellipse(gridSize * i, gridSize * j, gridSize, gridSize); break; case 1: ellipseMode(CORNER); noFill(); strokeWeight(2); stroke(134,169,251); ellipse(gridSize * i, gridSize * j, gridSize, gridSize); break; case 2: noStroke(); fill(134,169,251); rect(gridSize * i, gridSize * j, gridSize, gridSize); break; case 3: noFill(); strokeWeight(2); stroke(134,169,251); rect(gridSize * i, gridSize * j, gridSize, gridSize); break; case 4: noFill(); noStroke(); break; } } //マウスを押して再描画 void mousePressed() { redraw(); }
Processingでハコをランダムに複数描く2
前回は色は固定で表示/非表示の切り替えをランダムに行っていましたが、今回は色の切り替えと表示/非表示がランダムに切り替わるようにしました。
色はfill()の色だけでなく、チェック柄も使えます。
模様を色として使う場合、ハコのそれぞれの面の形にマスクをする必要があります。
方法としては、こちらのリンク
Proce55ing.walker,blog » Blog Archive » マスクを使ってPGraphicsの内容をくりぬいて使用する
のようにPGraphicsを強引に使うパターンと、マスクができるライブラリ「geomerative」のRShapeを使うパターンです。
参考にさせて頂きました。ありがとうございます。
geomerativeをやってみたのですが、どうも平行四辺形が作れないっぽいので諦めました(たぶん方法はあると思うのですが、重かったこともあり今回はパス)。
PGraphicsを使ってマスクをした場合、PDF書き出ししたときに画像扱いになってしまうので、ちょっと要注意かもです。
ま、Illustratorでライブトレスすれば良いのですが・・・それだとなんだか負けた感。
geomerativeに関しては問題なし。
ひとまずPGraphicsでやってみました。マウスボタンをクリックすると、ランダムに色や模様が変わります。
べた塗り・チェック柄・非表示・縦のストライプ、合計4種類です。
ストライプはこちら
Processing : だらっと学習帳
を参照させて頂きました。ありがとうございます。
輪郭線ありはこんな感じで、
なしはこんな感じ。輪郭線をなしにする場合は、hexagonStroke()とvoid hexagonStroke()〜を消します。
びみょーに柄がはみ出したりしてるので、マスクのサイズを微調整する必要がありますね。
たぶんサイズの問題だと思うのですが、水玉模様にするとなぜか重なって表示されてしまう不具合が出たので、水玉は使いませんでした。
//pg1が左側面、pg2が右側面、pg3がフタ PGraphics pg1,pg2,pg3; //mask1はpg1の形のマスク、mask2はpg2の形のマスク、mask3はpg3の形のマスク PGraphics mask1,mask2,mask3; //チェック柄の設定、チェックひとつのサイズ int RECT_SIZE = 5; //400はsetup()のsizeの設定 int rnum = 400 / RECT_SIZE; //ストライプ柄の設定 int rect_w = 5; int rect_h = 400; int num2 = 400 / rect_w; //2色のストライプ color[] c = new color[2]; //どれくらいの間隔でハコを描くか(現在はぴったり隣同士) int x1,y1; //ランダムに色や模様を変える int rd1,rd2,rd3; void setup() { size(400, 400); smooth(); background(255); noLoop(); //ストライプの色の設定 c[0] = color(0); c[1] = color(255); } void draw() { for (y1 = 0; y1 < 500; y1 += 90) { for (x1 = 0; x1 <= 500; x1 += 80) { rd1 = int(random(6)); rd2 = int(random(6)); rd3 = int(random(6)); //マスクと色の設定 quadMask(); image(pg1.get(), 0, 0); image(pg2.get(), 0, 0); image(pg3.get(), 0, 0); //六角形の輪郭 hexagonStroke(); } } } void quadMask() { mask1 = createGraphics(width, height); mask2 = createGraphics(width, height); mask3 = createGraphics(width, height); mask1.beginDraw(); mask2.beginDraw(); mask3.beginDraw(); mask1.smooth(); mask2.smooth(); mask3.smooth(); mask1.noStroke(); mask2.noStroke(); mask3.noStroke(); mask1.fill(255); mask2.fill(255); mask3.fill(255); //ここを変えると大きさが変わる。変えた場合はx1とy1の調整が必要 mask1.quad(x1, y1, x1, y1+50, x1+40,y1+70, x1+40, y1+20); mask2.quad(x1+40, y1+20, x1+40, y1+70, x1+80,y1+50, x1+80, y1); mask3.quad(x1+40, y1-20, x1, y1, x1+40,y1+20, x1+80, y1); mask1.endDraw(); mask2.endDraw(); mask3.endDraw(); pg1 = createGraphics(width, height); pg2 = createGraphics(width, height); pg3 = createGraphics(width, height); pg1.beginDraw(); pg2.beginDraw(); pg3.beginDraw(); pg1.smooth(); pg2.smooth(); pg3.smooth(); pg1.background(255); pg2.background(255); pg3.background(255); switch(rd1) { case 0: //べた塗り pg1.noStroke(); pg1.fill(251,247,16); pg1.rect(0, 0, 400,400); pg1.mask(mask1.get()); pg1.endDraw(); break; case 1: //べた塗り pg1.noStroke(); pg1.fill(37,61,159); pg1.rect(0, 0, 400,400); pg1.mask(mask1.get()); pg1.endDraw(); break; case 2: //非表示 pg1.noFill(); pg1.noStroke(); pg1.mask(mask1.get()); pg1.endDraw(); break; case 3: //チェック柄 dots1(); pg1.mask(mask1.get()); pg1.endDraw(); break; case 4: //ストライプ dots2(); pg1.mask(mask1.get()); pg1.endDraw(); break; //べた塗り case 5: pg1.noStroke(); pg1.fill(0); pg1.rect(0, 0, 400,400); pg1.mask(mask1.get()); pg1.endDraw(); break; } switch(rd2) { case 0: pg2.noStroke(); pg2.fill(251,247,16); pg2.rect(0, 0, 400,400); pg2.mask(mask2.get()); pg2.endDraw(); break; case 1: pg2.noStroke(); pg2.fill(37,61,159); pg2.rect(0, 0, 400,400); pg2.mask(mask2.get()); pg2.endDraw(); break; case 2: pg2.noFill(); pg2.noStroke(); pg2.mask(mask2.get()); pg2.endDraw(); break; case 3: dots1(); pg2.mask(mask2.get()); pg2.endDraw(); break; case 4: dots2(); pg2.mask(mask2.get()); pg2.endDraw(); break; case 5: pg2.noStroke(); pg2.fill(0); pg2.rect(0, 0, 400,400); pg2.mask(mask2.get()); pg2.endDraw(); break; } switch(rd3) { case 0: pg3.noStroke(); pg3.fill(251,247,16); pg3.rect(0, 0, 400,400); pg3.mask(mask3.get()); pg3.endDraw(); break; case 1: pg3.noStroke(); pg3.fill(37,61,159); pg3.rect(0, 0, 400,400); pg3.mask(mask3.get()); pg3.endDraw(); break; case 2: pg3.noFill(); pg3.noStroke(); pg3.mask(mask3.get()); pg3.endDraw(); break; case 3: dots1(); pg3.mask(mask3.get()); pg3.endDraw(); break; case 4: dots2(); pg3.mask(mask3.get()); pg3.endDraw(); break; case 5: pg3.noStroke(); pg3.fill(0); pg3.rect(0, 0, 400,400); pg3.mask(mask3.get()); pg3.endDraw(); break; } } //チェック柄 void dots1() { pg1.noStroke(); pg2.noStroke(); pg3.noStroke(); for (int y = 0; y < rnum+1; y ++) { for (int x = 0; x < rnum+1; x ++) { if ((y + x) % 2 == 0) { pg1.fill(255); pg2.fill(255); pg3.fill(255); } else { pg1.fill(230,16,16); pg2.fill(230,16,16); pg3.fill(230,16,16); } pg1.rect(RECT_SIZE * x, RECT_SIZE * y, RECT_SIZE, RECT_SIZE); pg2.rect(RECT_SIZE * x, RECT_SIZE * y, RECT_SIZE, RECT_SIZE); pg3.rect(RECT_SIZE * x, RECT_SIZE * y, RECT_SIZE, RECT_SIZE); } } } //ストライプ void dots2() { pg1.noStroke(); pg2.noStroke(); pg3.noStroke(); for (int n = 0; n < num2;n++) { pg1.fill(c[n%c.length]); pg2.fill(c[n%c.length]); pg3.fill(c[n%c.length]); pg1.rect(n*rect_w, 0, rect_w, rect_h); pg2.rect(n*rect_w, 0, rect_w, rect_h); pg3.rect(n*rect_w, 0, rect_w, rect_h); } } //六角形の輪郭線 void hexagonStroke() { noFill(); stroke(34,24,22); strokeWeight(2); line(x1+40,y1-20,x1,y1); line(x1,y1,x1,y1+50); line(x1,y1+50,x1+40,y1+70); line(x1+40,y1+70,x1+80,y1+50); line(x1+80,y1+50,x1+80,y1); line(x1+80,y1,x1+40,y1-20); } //マウスを押して再描画 void mousePressed() { redraw(); }
【追記】
dots1()は下記のように書き換えができますが、なぜか重くなります。
【追記の追記】
原因が分かりましたので、書き直しました。現在上に表示されているのが、訂正した書き方になります。
forの最大数を打ち間違えてました・・・