Processingで作るハッカーっぽい画面のまとめ

 今まで書いてきた"ハッカーっぽい画面を作る"のタブのまとめです。これまでの技術を組み合わせると↓のような映像が作れます。


 難しい技術は使っていないのでどうにかできると思います。また、コードを添付しますが自分が分かればいいと思って適当に書いてたので汚いです。ゲーミングPCで動かすことを想定して作ったので、処理が重いです。変数もグローバルで乱立させてしまっているので、わかりにくかったらtwitterかコメントで聞いてください。なるべく丁寧に解説します。

 今回使用したコードはDropBoxに入れておきます。Readmeにも書いてありますが、今回使ったフォントを利用する場合はこちら(https://www.keshikan.net/fonts.html)のサイトのフォントを使用してください。

Processingでグリッチエフェクトを作る

 有名な画面効果にグリッチエフェクトというものがあります。今回はそれをProcessingで描画した図形にかける方法です。

 今回使用したのはPImageという機能で、これによって画像を表示したりそれにエフェクトを足したりすることができます。今回は前回(http://blog.livedoor.jp/chisato_tofu/archives/25967168.html)の7セグマトリクスにエフェクトをかけたいため、Processingの画面をPImageで扱える形に変更する必要があります。そのために今回はget()関数を利用しています。
 get()関数はget(x,y,dx,dy)とすることで、(x,y)から(dx,dy)分の色を取得できます。今回はこれをランダムに決められた値分移動させることで、それっぽいエフェクトにしています。今回は自分の趣味でrandom関数を使用しましたが、noise関数を利用することでより連続的なノイズを作ることができるとおもいます。

 今回作ったエフェクトは↓のようなものです。元の図形は緑色の正方形が連続しているものです。

 以下コードです。get()で取得した範囲は真っ黒のrectで埋めることで、ずらして描画した際の重なりをなくしています。
  1. import java.util.Random;

  2. PImage img;
  3. int[] glitch = new int[4];
  4. Random random = new Random();


  5. void setup() {
  6.   size(1920, 1080);
  7.   img = createImage(width, height, ARGB);
  8.   colorMode(HSB, 360, 255, 255, 255);
  9.   noStroke();
  10. }

  11. void draw() {
  12.   background(0);
  13.   fill(156, 137, 172, 255);
  14.   for (int i=0; i<9; i++) {
  15.     for (int j=0; j<16; j++) {
  16.       if ((i + j) % 2 == 0) {
  17.         rect(120 * j, 120 * i, 120, 120);
  18.       }
  19.     }
  20.   }

  21.   glitch();
  22. }


  23. void glitch() {
  24.   if (random.nextInt(10) >= 9) {
  25.     if (random.nextInt(2) > 0) {
  26.       glitch[0] = random.nextInt(1080);//y
  27.       glitch[1] = random.nextInt(60);//dx
  28.       glitch[2] = random.nextInt(100);//dy
  29.       glitch[3] = random.nextInt(2) * 2 + 1;//n
  30.     } else {
  31.       glitch[0] = 0;
  32.       glitch[1] = 0;
  33.       glitch[2] = 0;
  34.       glitch[3] = 0;
  35.     }
  36.   }

  37.   switch(glitch[3]) {
  38.   case 1:
  39.     img = get(0, glitch[0], width, glitch[2]);
  40.     fill(0, 0, 0);
  41.     rect(0, glitch[0], width, glitch[2]);
  42.     image(img, 30 - glitch[1], glitch[0]);
  43.     if (glitch[1] > 30) {
  44.       image(img, 30 - glitch[1] + width, glitch[0]);
  45.     } else {
  46.       image(img, 30 - glitch[1] - width, glitch[0]);
  47.     }
  48.     break;

  49.   case 3:
  50.     img = get(0, glitch[0], width, glitch[2]);
  51.     fill(0, 0, 0);
  52.     rect(0, glitch[0], width, glitch[2]);
  53.     image(img, 30 - glitch[1], glitch[0]);
  54.     if (glitch[1] > 30) {
  55.       image(img, 30 - glitch[1] + width, glitch[0]);
  56.     } else {
  57.       image(img, 30 - glitch[1] - width, glitch[0]);
  58.     }
  59.     img = get(0, glitch[0] - glitch[2] / 2, width, glitch[2] / 2);
  60.     fill(0, 0, 0);
  61.     rect(0, glitch[0] - glitch[2] / 2, width, glitch[2] / 2);
  62.     image(img, -30 + glitch[1], glitch[0] - glitch[2] / 2);
  63.     if (glitch[1] > 30) {
  64.       image(img, -30 + glitch[1] + width, glitch[0] - glitch[2] / 2);
  65.     } else {
  66.       image(img, -30 + glitch[1] - width, glitch[0] - glitch[2] / 2);
  67.     }
  68.     img = get(0, glitch[0] + glitch[2] / 2, width, glitch[2] / 2);
  69.     fill(0, 0, 0);
  70.     rect(0, glitch[0] + glitch[2] / 2, width, glitch[2] / 2);
  71.     image(img, -30 + glitch[1], glitch[0] + glitch[2] / 2);
  72.     if (glitch[1] > 30) {
  73.       image(img, -30 + glitch[1] + width, glitch[0] + glitch[2] / 2);
  74.     } else {
  75.       image(img, -30 + glitch[1] - width, glitch[0] + glitch[2] / 2);
  76.     }
  77.     break;

  78.   case 5:
  79.     img = get(0, glitch[0], width, glitch[2]);
  80.     fill(0, 0, 0);
  81.     rect(0, glitch[0], width, glitch[2]);
  82.     image(img, 30 - glitch[1], glitch[0]);
  83.     if (glitch[1] > 30) {
  84.       image(img, 30 - glitch[1] + width, glitch[0]);
  85.     } else {
  86.       image(img, 30 - glitch[1] - width, glitch[0]);
  87.     }
  88.     img = get(0, glitch[0] - glitch[2] / 2, width, glitch[2] / 2);
  89.     fill(0, 0, 0);
  90.     rect(0, glitch[0] - glitch[2] / 2, width, glitch[2] / 2);
  91.     image(img, -30 + glitch[1], glitch[0] - glitch[2] / 2);
  92.     if (glitch[1] > 30) {
  93.       image(img, -30 + glitch[1] + width, glitch[0] - glitch[2] / 2);
  94.     } else {
  95.       image(img, -30 + glitch[1] - width, glitch[0] - glitch[2] / 2);
  96.     }
  97.     img = get(0, glitch[0] + glitch[2] / 2, width, glitch[2] / 2);
  98.     fill(0, 0, 0);
  99.     rect(0, glitch[0] + glitch[2] / 2, width, glitch[2] / 2);
  100.     image(img, -30 + glitch[1], glitch[0] + glitch[2] / 2);
  101.     if (glitch[1] > 30) {
  102.       image(img, -30 + glitch[1] + width, glitch[0] + glitch[2] / 2);
  103.     } else {
  104.       image(img, -30 + glitch[1] - width, glitch[0] + glitch[2] / 2);
  105.     }
  106.     img = get(0, glitch[0] - glitch[2], width, glitch[2]);
  107.     fill(0, 0, 0);
  108.     rect(0, glitch[0] - glitch[2], width, glitch[2]);
  109.     image(img, -30 + glitch[1], glitch[0] - glitch[2]);
  110.     if (glitch[1] > 30) {
  111.       image(img, -30 + glitch[1] + width, glitch[0] - glitch[2]);
  112.     } else {
  113.       image(img, -30 + glitch[1] - width, glitch[0] - glitch[2]);
  114.     }
  115.     img = get(0, glitch[0] + glitch[2], width, glitch[2]);
  116.     fill(0, 0, 0);
  117.     rect(0, glitch[0] + glitch[2], width, glitch[2]);
  118.     image(img, -30 + glitch[1], glitch[0] + glitch[2]);
  119.     if (glitch[1] > 30) {
  120.       image(img, -30 + glitch[1] + width, glitch[0] + glitch[2]);
  121.     } else {
  122.       image(img, -30 + glitch[1] - width, glitch[0] + glitch[2]);
  123.     }
  124.     break;
  125.   }
  126. }

Processingで7セグマトリクスを作る

 もうそろそろこのシリーズも終盤に差し掛かってきました。今回は↓の映像のような7セグマトリクスを作っていきたいと思います。
 これはあらかじめ決められた40*18の升目にランダムな数字を表示し、その明るさが徐々に表示していくというものです。それなので今回は、
  1. ランダムに抽出された場所にランダムな数字を表示する部分
  2. その表示をだんだん暗くさせていく部分
に分けて作成しました。最後にプログラムを載せていますが、randomnum()がランダムな場所の数字を抽選し透過率を0にする関数、matrix()がマトリクスを表示させつつ透過率を上げていく関数です。

  1. import java.util.Random;

  2. Random random = new Random();
  3. char[] mode = new char[2];
  4. int[][] txt = new int[40][18];
  5. int[][] Br = new int[40][18];
  6. PFont D7;

  7. void setup() {
  8.   size(1920, 1080);
  9.   D7 = createFont("DSEG7ClassicMini-Regular.ttf", 60);
  10.   colorMode(HSB, 360, 255, 255, 255);
  11.   textAlign(CENTER, CENTER);
  12.   textFont(D7);
  13. }

  14. void draw() {
  15.   background(0);
  16.   randomnum();
  17.   matrix();
  18. }

  19. void keyPressed() {
  20.   mode[0] = key;
  21. }

  22. void randomnum() {
  23.   for (int i=0; i<24; i++) {//ランダムな24ますにランダムな数字を入れ、透過率を0にする
  24.     int c = random.nextInt(40);//ランダムなx座標
  25.     int d = random.nextInt(18);//ランダムなy座標
  26.     txt[c][d]=random.nextInt(10);//0~9のランダムな数字
  27.     Br[c][d]=255;//透過率最大
  28.   }
  29. }

  30. void matrix() {//マトリクスを表示し、各マス目の透過率を下げる。
  31.   for (int i=0; i<40; i++) {
  32.     for (int j=0; j<18; j++) {
  33.       fill(180, 255, 255, Br[i][j]);
  34.       Br[i][j]=Br[i][j]-5;
  35.       text(txt[i][j], -20 + i * 49, 30 + j * 65);
  36.     }
  37.   }
  38. }

Processingにデスクトップ音声を入力する方法(Windows10)

 Processingでは基本的にWindowsのデフォルト入力しか使えません。それなのでProcessingでデスクトップ音声を認識したい場合は、デスクトップ出力をデフォルト入力にすることが必要です。

 これを実現するために今回はVB-Audioというソフトを使います。
 このソフトの使い方としては、まずhttps://vb-audio.com/Cable/からダウンロードをします。そしたらダウンロードしたzipファイルを解凍し、その中のVBCABLE_Setup_x64.exeを実行するとこのソフトが使えるようになります。

 windowsの設定画面で↓のように設定すると出力が入力にループバックします。それなので、Processingでデフォルト入力を使用するとデスクトップ出力を使用できます。

スクリーンショット 2021-01-10 142431

Processingで作るオーディオビジュアライザー

 オーディオビジュアライザーってかっこいいので作りたくなることがあります。自分も今回初めて正式名称を知りましたが、オーディオビジュアライザーとは音の大きさによってぴょこぴょこする棒のことです。

 今回はProcessingで作成するのでminimライブラリの中にあるFFTという機能を使います。そもそもオーディオビジュアライザーとはFFT(高速フーリエ変換)の結果をかっこよく表示したものなので、FFTをすれば後は表示するだけです。
 ↓のような画面ぐらいならすぐに作ることができます。
 この時に前回(http://blog.livedoor.jp/chisato_tofu/archives/25956603.html)のソフトを使用するとデスクトップ音声のオーディオビジュアライザが使用できます。

 ↓に今回のコードを載せておきます。
  1. import java.util.Random;
  2. import ddf.minim.*;
  3. import ddf.minim.analysis.*; 
  4. import ddf.minim.effects.*;
  5. import ddf.minim.signals.*;
  6. import ddf.minim.spi.*;
  7. import ddf.minim.ugens.*;

  8. Minim minim; 
  9. AudioInput in; 
  10. FFT fft; 
  11. int w;

  12. void setup() {
  13.   size(1920, 1080);
  14.   colorMode(HSB, 360, 255, 255, 255);
  15.   strokeWeight(5);
  16.   fill(180, 255, 255, 100);
  17.   minim = new Minim(this);
  18.   in = minim.getLineIn(Minim.STEREO, 512);//デフォルト入力をProcessingに取り込み
  19.   fft = new FFT(in.bufferSize(), in.sampleRate()); 
  20.   fft.logAverages(60, 2);//(FFTのバンドの数,FFTのオクターブ当たりの分割数)を設定
  21.   w=width/fft.avgSize();
  22. }

  23. void draw() {
  24.   background(0);
  25.   fft.forward(in.mix);
  26.   for (int i = 0; i < fft.avgSize(); i++) { //オーディオビジュアライザを描画
  27.     rect((i*w), height, w, -fft.getAvg(i) * 50);
  28.   }
  29. }

Processingで作る爆発エフェクト

 前回爆発音を作成しましたが、今回はそれを利用した爆発エフェクトの作成です。

 Processingを用いた爆破エフェクトの作成はGoogleで検索するといくつか出てきますが、今回はシンプルに円を拡大することにしました。
 特に難しいことはしていないので下の動画を見ればどのような表現をしているかわかると思います。


 中身としては、"爆発モード"に入る際に更新情報としてそのタイミングでの時間を取得し、そこからの経過時間で一番大きな円の大きさを変えています。小さい円は、ある程度ランダムな場所にある程度ランダムな最大サイズの円を設定し、半径0の円から最大サイズになるまで描画しています。小さい円は5個描画され、一つの描画が終わると次の円が表示されるようになっています。

 以下コードです。ある程度コメントで説明してあります。
  1. import java.util.Random;
  2. import ddf.minim.*;
  3. import ddf.minim.analysis.*; 
  4. import ddf.minim.effects.*;
  5. import ddf.minim.signals.*;
  6. import ddf.minim.spi.*;
  7. import ddf.minim.ugens.*;

  8. int[][] circle = new int[4][5];//x,y,r,t0,t
  9. char[] mode = new char[2];
  10. int[] bubble = new int[4];
  11. int[] noisevolmode = new int[2];

  12. Minim minim; 
  13. AudioOutput out;
  14. Random random = new Random();
  15. Noise[][] noisevol = new Noise[8800][2];

  16. void setup() {
  17.   size(1920, 1080);
  18.   colorMode(HSB, 360, 255, 255, 255);
  19.   strokeWeight(5);
  20.   background(0);
  21.   
  22.   minim = new Minim(this);
  23.   out = minim.getLineOut(Minim.STEREO);
  24.   for (int i = 0; i < 8800; i++) {
  25.     noisevol[i][0] = new Noise(1.0 + cos(map(i, 0, 8800, 0, PI)), Noise.Tint.BROWN);
  26.   }
  27.   for (int i = 0; i < 8800; i++) {
  28.     noisevol[i][1] = new Noise(1.0 + cos(map(i, 0, 8800, 0, PI)), Noise.Tint.RED);
  29.   }
  30. }
  31.   
  32. void draw() {//ループ処理
  33.   background(0);
  34.   if (mode[1] != mode[0]) {//更新処理の判定
  35.     update();
  36.     mode[1] = mode[0];
  37.   }
  38.   switch(mode[0]) {//現在のモードの実効
  39.   case 'b':
  40.     bubble();
  41.     break;
  42.   default:
  43.     break;
  44.   }
  45. }

  46. void update() {//更新処理
  47.   switch(mode[1]) {//終了処理
  48.   case 'b':
  49.     noisevol[noisevolmode[1]][0].unpatch(out);
  50.     noisevol[noisevolmode[1]][1].unpatch(out);
  51.     break;
  52.   default:
  53.     break;
  54.   }
  55.   switch(mode[0]) {//開始処理
  56.   case 'b':
  57.     if (mode[1] != mode[0]) {
  58.       bubble[0] = millis();
  59.     }
  60.     break;
  61.   default:
  62.     break;
  63.   }
  64. }

  65. void keyPressed() {//キーボード入力の割り込み
  66.   mode[0] = key;
  67. }

  68. void bubble() {//円と音の出力
  69.   background(0);
  70.   bubble[1] = millis() - bubble[0];
  71.   bubble[2] = (millis() - bubble[0]) * 10;
  72.   bubble[3] = bubble[2] % 2200;
  73.   
  74.   if (bubble[2] >= 4 * 2200) {//終了判定
  75.     mode[0] = 's';
  76.     return;
  77.   }
  78.   circle[0][4] = (millis() - circle[0][3]) * 2;
  79.   if (circle[0][2] == 0 || circle[0][2] < circle[0][4]) {
  80.     circle[0][4] = 0;
  81.     circle[0][3] = millis();
  82.     circle[0][2] = random.nextInt(500);
  83.     circle[0][1] = height / 4 + random.nextInt(height /2);
  84.     circle[0][0] = width / 4 + random.nextInt(width /2);
  85.   }
  86.   circle[1][4] = (millis() - circle[1][3]) * 2;
  87.   if (circle[1][2] == 0 || circle[1][2] < circle[1][4]) {
  88.     circle[1][4] = 0;
  89.     circle[1][3] = millis();
  90.     circle[1][2] = random.nextInt(500);
  91.     circle[1][1] = height / 4 + random.nextInt(height /2);
  92.     circle[1][0] = width / 4 + random.nextInt(width /2);
  93.   }
  94.   circle[2][4] = (millis() - circle[2][3]) * 2;
  95.   if (circle[2][2] == 0 || circle[2][2] < circle[2][4]) {
  96.     circle[2][4] = 0;
  97.     circle[2][3] = millis();
  98.     circle[2][2] = random.nextInt(500);
  99.     circle[2][1] = height / 4 + random.nextInt(height /2);
  100.     circle[2][0] = width / 4 + random.nextInt(width /2);
  101.   }
  102.   circle[3][4] = (millis() - circle[3][3]) * 2;
  103.   if (circle[3][2] == 0 || circle[3][2] < circle[3][4]) {
  104.     circle[3][4] = 0;
  105.     circle[3][3] = millis();
  106.     circle[3][2] = random.nextInt(500);
  107.     circle[3][1] = height / 4 + random.nextInt(height /2);
  108.     circle[3][0] = width / 4 + random.nextInt(width /2);
  109.   }

  110.   noisevolmode[0] = bubble[2];
  111.   noisevol[noisevolmode[1]][0].unpatch(out);
  112.   noisevol[noisevolmode[0]][0].patch(out);
  113.   noisevol[noisevolmode[1]][1].unpatch(out);
  114.   noisevol[noisevolmode[0]][1].patch(out);
  115.   noisevolmode[1] = noisevolmode[0];

  116.   fill(0, 0, 255, 255);
  117.   circle(width / 2, height / 2, bubble[3]);
  118.   circle(circle[0][0], circle[0][1], circle[0][4]);
  119.   circle(circle[1][0], circle[1][1], circle[1][4]);
  120.   circle(circle[2][0], circle[2][1], circle[2][4]);
  121.   circle(circle[3][0], circle[3][1], circle[3][4]);
  122. }

三相モーターをArduinoと自作VVVFで回した話

2021年になったので景気づけに三相モーターを回してみました。

 使った回路はこのときと同じで、↓のとおりとなります。
VVVFhbd_回路図
 使ったプログラムは最後に書いておきます。

 こんな感じで回してました。
 YouTubeにも上げました。


 そんなこんなで2021年もよろしくお願いします。

 以下コード(これもリンク先の記事と同じはずです。)
  1. const int IN_U = 3;
  2. const int SD_U = 2;
  3. const int IN_V = 5;
  4. const int SD_V = 4;
  5. const int IN_W = 9;
  6. const int SD_W = 8;

  7. int delayTime;

  8. void setup() {
  9.   pinMode(IN_U, OUTPUT);
  10.   pinMode(IN_V, OUTPUT);
  11.   pinMode(IN_W, OUTPUT);
  12.   pinMode(SD_U, OUTPUT);
  13.   pinMode(SD_V, OUTPUT);
  14.   pinMode(SD_W, OUTPUT);

  15.   analogWrite(IN_U, 0);
  16.   analogWrite(IN_V, 0);
  17.   analogWrite(IN_W, 0);
  18.   digitalWrite(SD_U, HIGH);
  19.   digitalWrite(SD_V, HIGH);
  20.   digitalWrite(SD_W, HIGH);
  21. }
  22. void loop() {
  23.   if (millis() < 8000) {
  24.     delayTime = 5 - millis() / 2000;
  25.   }

  26.   analogWrite(IN_U, 250);
  27.   analogWrite(IN_V, 0);
  28.   analogWrite(IN_W, 0);
  29.   digitalWrite(SD_U, HIGH);
  30.   digitalWrite(SD_V, LOW);
  31.   digitalWrite(SD_W, HIGH);
  32.   delay(delayTime);

  33.   analogWrite(IN_U, 250);
  34.   analogWrite(IN_V, 0);
  35.   analogWrite(IN_W, 0);
  36.   digitalWrite(SD_U, HIGH);
  37.   digitalWrite(SD_V, HIGH);
  38.   digitalWrite(SD_W, LOW);
  39.   delay(delayTime);

  40.   analogWrite(IN_U, 0);
  41.   analogWrite(IN_V, 0);
  42.   analogWrite(IN_W, 250);
  43.   digitalWrite(SD_U, LOW);
  44.   digitalWrite(SD_V, HIGH);
  45.   digitalWrite(SD_W, HIGH);
  46.   delay(delayTime);

  47.   analogWrite(IN_U, 0);
  48.   analogWrite(IN_V, 0);
  49.   analogWrite(IN_W, 250);
  50.   digitalWrite(SD_U, HIGH);
  51.   digitalWrite(SD_V, LOW);
  52.   digitalWrite(SD_W, HIGH);
  53.   delay(delayTime);

  54.   analogWrite(IN_U, 0);
  55.   analogWrite(IN_V, 250);
  56.   analogWrite(IN_W, 0);
  57.   digitalWrite(SD_U, HIGH);
  58.   digitalWrite(SD_V, HIGH);
  59.   digitalWrite(SD_W, LOW);
  60.   delay(delayTime);

  61.   analogWrite(IN_U, 0);
  62.   analogWrite(IN_V, 250);
  63.   analogWrite(IN_W, 0);
  64.   digitalWrite(SD_U, LOW);
  65.   digitalWrite(SD_V, HIGH);
  66.   digitalWrite(SD_W, HIGH);
  67.   delay(delayTime);
  68. }

Processingで作る爆発音

 皆さん爆発音を自分で用意したくなった時があると思います。でも、どう作ればいいかわからないですよね? そんな方のために今回は爆発音を作る方法を紹介しようと思います!

 まず、作成経緯です。爆発音のフリー素材なんかネット上にごろごろ転がっているので、それを持ってくればこの記事はいりません。しかし、全部Processingで完結させるといってしまった以上Processingで作るしかありません。いくら調べてもProcessing上で爆発音を作っている人はいなかったので日本初の試みです。
 次に爆発音についてです。爆発音は調べたところノイズを減衰させるといい感じに聞こえるらしいです。それなのでminimの中にあるNoiseというものを使って作ることにします。

 これを実装するためにはノイズの大きさを変える必要があるのですが、自分が英語リファレンスを読んだ感じできませんでした。それなので今回は音量が違う8800通りのノイズを定義しています。この8800という数字はほかのところとの兼ね合いで生まれたものなので特に気にしなくていいです。

 また、Processingには
  1. ホワイトノイズ
  2. ブラウンノイズ
  3. ピンクノイズ
  4. レッドノイズ
の4つのノイズが存在します。それぞれのノイズをsinカーブで減衰させたときの例を↓に出します。自分の好みに合わせて、組み合わせるノイズや減衰の関数を選んでください。



 個人的にはブラウンノイズとレッドノイズがそれっぽいと思うので今回のコードではこの二つを採用しています。

 ↓にそれぞれのツイートの元のコードを書いておきます。
1つ目のツイート
  1. import java.util.Random;
  2. import ddf.minim.*;
  3. import ddf.minim.analysis.*; 
  4. import ddf.minim.effects.*;
  5. import ddf.minim.signals.*;
  6. import ddf.minim.spi.*;
  7. import ddf.minim.ugens.*;

  8. Noise[] noisevol = new Noise[5];
  9. int mode;

  10. Minim minim; 
  11. AudioOutput out;

  12. void setup() {
  13.   size(300, 100);
  14.   textAlign(CENTER, CENTER);
  15.   fill(255);
  16.   textSize(64);
  17.   background(0);
  18.   minim = new Minim(this);
  19.   out = minim.getLineOut(Minim.STEREO);
  20.   noisevol[1] = new Noise(1.0, Noise.Tint.WHITE);
  21.   noisevol[2] = new Noise(1.0, Noise.Tint.BROWN);
  22.   noisevol[3] = new Noise(1.0, Noise.Tint.PINK);
  23.   noisevol[4] = new Noise(1.0, Noise.Tint.RED);
  24. }

  25. void draw() {
  26. }

  27. void keyPressed() {
  28.   background(0);
  29.   if (mode != 0) {
  30.     noisevol[mode].unpatch(out);
  31.   }
  32.   switch(key) {
  33.   case '1':
  34.     mode = 1;
  35.     text("WHITE", width / 2, height / 2);
  36.     break;
  37.   case '2':
  38.     mode = 2;
  39.     text("BROWN", width / 2, height / 2);
  40.     break;
  41.   case '3':
  42.     mode = 3;
  43.     text("PINK", width / 2, height / 2);
  44.     break;
  45.   case '4':
  46.     mode = 4;
  47.     text("RED", width / 2, height / 2);
  48.     break;
  49.   default:
  50.     break;
  51.   }
  52.   noisevol[mode].patch(out);
  53. }
2つ目のツイート
  1. import java.util.Random;
  2. import ddf.minim.*;
  3. import ddf.minim.analysis.*; 
  4. import ddf.minim.effects.*;
  5. import ddf.minim.signals.*;
  6. import ddf.minim.spi.*;
  7. import ddf.minim.ugens.*;

  8. Noise[][] noisevol = new Noise[8800][5];
  9. int[] noisevolmode = new int[3];
  10. int mode;

  11. Minim minim; 
  12. AudioOutput out;

  13. void setup() {
  14.   size(300,100);
  15.   textAlign(CENTER, CENTER);
  16.   fill(255);
  17.   textSize(64);
  18.   background(0);
  19.   minim = new Minim(this);
  20.   out = minim.getLineOut(Minim.STEREO);
  21.   for (int i = 0; i < 8800; i++) {
  22.     noisevol[i][1] = new Noise(1.0 + cos(map(i, 0, 8800, 0, PI)), Noise.Tint.WHITE);
  23.   }
  24.   for (int i = 0; i < 8800; i++) {
  25.     noisevol[i][2] = new Noise(1.0 + cos(map(i, 0, 8800, 0, PI)), Noise.Tint.BROWN);
  26.   }
  27.   for (int i = 0; i < 8800; i++) {
  28.     noisevol[i][3] = new Noise(1.0 + cos(map(i, 0, 8800, 0, PI)), Noise.Tint.PINK);
  29.   }
  30.   for (int i = 0; i < 8800; i++) {
  31.     noisevol[i][4] = new Noise(1.0 + cos(map(i, 0, 8800, 0, PI)), Noise.Tint.RED);
  32.   }
  33. }

  34. void draw() {
  35.   noisevolmode[0] = (millis() - noisevolmode[2]) * 10;
  36.   if (mode != 0) {
  37.     if (noisevolmode[0] > 8800) {
  38.       noisevol[noisevolmode[1]][mode].unpatch(out);
  39.       noisevolmode[0] = 0;
  40.     } else {
  41.       noisevol[noisevolmode[1]][mode].unpatch(out);
  42.       noisevol[noisevolmode[0]][mode].patch(out);
  43.       noisevolmode[1] = noisevolmode[0];
  44.     }
  45.   }
  46. }

  47. void keyPressed() {
  48.   background(0);
  49.   if (mode != 0) {
  50.     noisevol[noisevolmode[1]][mode].unpatch(out);
  51.   }
  52.   switch(key) {
  53.   case '1':
  54.     mode = 1;
  55.     text("WHITE", width / 2, height / 2);
  56.     break;
  57.   case '2':
  58.     mode = 2;
  59.     text("BROWN", width / 2, height / 2);
  60.     break;
  61.   case '3':
  62.     mode = 3;
  63.     text("PINK", width / 2, height / 2);
  64.     break;
  65.   case '4':
  66.     mode = 4;
  67.     text("RED", width / 2, height / 2);
  68.     break;
  69.   default:
  70.     break;
  71.   }
  72.   noisevolmode[2] = millis();
  73. }

Processingでカウントダウンタイマーを作る

 今まで使った技術で↓のカウントダウンが作れます。
 やってることとしては、その時間の時刻を表示し、文字の透明度をsinで変えているだけです。多分もっとスマートな方法があります。

 ↓にこれのコードを貼っておくのでこれをコピペして、コピペした先の.pdeと同じ階層にフォントの.ttfファイルを入れれば動きます。また、OBSに入れることを前提として制作していたのでFHDになってますが、小さくしたいときはsize(,)の中身で調節してください。その時多少文字がずれてしまう時は、121行目のrect(,,,)の係数を少しずつ変えてください。

  1. import ddf.minim.*;
  2. import ddf.minim.analysis.*; 
  3. import ddf.minim.effects.*;
  4. import ddf.minim.signals.*;
  5. import ddf.minim.spi.*;
  6. import ddf.minim.ugens.*;

  7. PFont D14;
  8. int[] now = new int[5];
  9. char[] mode = new char[2];
  10. int target;
  11. String s;

  12. Minim minim; 
  13. AudioOutput out;
  14. Oscil oscil;

  15. void setup() {
  16.   size(1920, 1080);
  17.   D14 = createFont("DSEG14Modern-Regular.ttf", 60);
  18.   colorMode(HSB, 360, 255, 255, 255);
  19.   textAlign(CENTER, CENTER);

  20.   strokeWeight(5);

  21.   minim = new Minim(this);
  22.   out = minim.getLineOut(Minim.STEREO);
  23.   oscil = new Oscil(440, 0.5, Waves.SQUARE);
  24. }

  25. void draw() {
  26.   background(0);
  27.   if (mode[1] != mode[0]) {
  28.     update();
  29.     mode[1] = mode[0];
  30.   }
  31.   switch(mode[0]) {
  32.   case 'c':
  33.     count();
  34.     break;
  35.   default:
  36.     break;
  37.   }
  38. }

  39. void count() {
  40.   now[0] = target - millis();
  41.   now[1] = int( map( sin( map( now[0] / 2 % 1000, 0, 1000, 0, 2*PI) + PI / 4), -1, 1, 0, 255));
  42.   now[2] = now[0] % 1000;
  43.   now[4] = now[0];
  44.   if (now[0]<10) {
  45.     mode[0] = 'b';
  46.     return;
  47.   }
  48.   if (now[0] % 1000 <10) {
  49.     s = "00" + str(now[0] % 1000);
  50.   } else {
  51.     if (now[0] % 1000 < 100) {
  52.       s = "0" + str(now[0] % 1000);
  53.     } else {
  54.       s = str(now[0] % 1000);
  55.     }
  56.   }
  57.   now[0] = now[0] / 1000;
  58.   if (now[0] % 60 <10) {
  59.     s = "0" + str(now[0] % 60) + ":" + s;
  60.   } else {
  61.     s = str(now[0] % 60) + ":" + s;
  62.   }
  63.   now[0] = now[0] / 60;
  64.   if (now[0] % 60 <10) {
  65.     s = "0" + str(now[0] % 60) + ":" + s;
  66.   } else {
  67.     s = str(now[0] % 60) + ":" + s;
  68.   }
  69.   now[0] = now[0] / 60;
  70.   if (now[0] % 60 <10) {
  71.     s = "0" + str(now[0] % 60) + ":" + s;
  72.   } else {
  73.     s = str(now[0] % 60) + ":" + s;
  74.   }

  75.   if (now[4] >10000) {
  76.     if (now[2] < 100) {
  77.       if (now[3] != 1) {
  78.         oscil.patch(out);
  79.         now[3] = 1;
  80.       }
  81.     } else {
  82.       oscil.unpatch(out);
  83.       now[3] = 0;
  84.     }
  85.   } else {
  86.     if (now[4] > 5000) {
  87.       if (now[2] < 100 || (now[2] > 500 && now[2] < 600)) {
  88.         if (now[3] != 1) {
  89.           oscil.patch(out);
  90.           now[3] = 1;
  91.         }
  92.       } else {
  93.         oscil.unpatch(out);
  94.         now[3] = 0;
  95.       }
  96.     } else {
  97.       if (now[4] > 1000) {
  98.         if (now[2] < 100 || (now[2] > 500 && now[2] < 600) || (now[2] > 250 && now[2] < 350) || (now[2] > 750 && now[2] < 850)) {
  99.           if (now[3] != 1) {
  100.             oscil.patch(out);
  101.             now[3] = 1;
  102.           }
  103.         } else {
  104.           oscil.unpatch(out);
  105.           now[3] = 0;
  106.         }
  107.       }
  108.     }
  109.   }

  110.   stroke(0, 0, 255, map( now[1], 0, 255, 100, 255));
  111.   fill(0, 0, 0, 0);
  112.   rect(width / 2 - textWidth(s) / 2, height / 2 - (textAscent() + textDescent()) / 2 - 5, textWidth(s), textAscent() + textDescent() + 10);
  113.   textFont(D14);
  114.   fill(0, 0, 255, now[1]);
  115.   text(s, width / 2, height / 2);
  116. }

  117. void update() {
  118.   switch(mode[1]) {
  119.   case 'c':
  120.     stroke(0, 0, 0, 255);
  121.     oscil.unpatch(out);
  122.     break;
  123.   default:
  124.     break;
  125.   }
  126.   switch(mode[0]) {
  127.   case 'c':
  128.     if (mode[1] != mode[0]) {
  129.       target = millis() + (((((0 * 60) + 1) * 60) + 0) * 1000);
  130.     }
  131.     break;
  132.   default:
  133.     break;
  134.   }
  135. }

  136. void keyPressed() {
  137.   mode[0] = key;
  138. }

Ene-1GPに向けた機体制作

 コロナの影響で、2020年のEne-1GPがなかった?ので期待をお披露目する場所がありませんでした。それなので、年を越してしまいましたが作っていた機体のお披露目をします。

 この機体ができるまでに1機違う機体があったのですが、それはいろいろあった影響で信頼性がなかったので今回は形にすることを目標にやりました。
 それなのでまだ未完成な部分がありますが、一応完成という形にしています。今年の状況の中で大会が開かれるかわからないですが、またサークルのメンバーが4年になってしまうので大会があっても参加できるかわかりませんが、これからもアップデートはしていきたいと思います。まあ逆に、大学卒業しちゃえば知り合いを動員して大会に参加できます。

 そんなこんなでできた機体は↓の動画の通りになります。


 見てもらえばわかる通り車用のバッテリーと775モーターを使ったものになります。

 こうなった経緯を1つ1つ説明すると...
  1.  レギュレーションとしては乾電池40本なのに車用バッテリーを使った理由としては、単純に充電がめんどくさいからです。あと、これをケースに入れて配線するのもめんどくさいからです。実際には乾電池20本を直列につないで30Vで走行するのですが、今回は車用バッテリー12.5Vで走行しています。また本来電流制限があるのですが、どう頑張っても越えられそうにもないので今回は無視しています。
  2.  また775モーターを利用した理由ですが、ある程度小型で、ある程度出力があり、ある程度安いモーターがほかになかったからです。ブラシレスモーターとか高くてあきらめました。
 です。また今回はインバーターを使わずに単純にFETのスイッチだけで動かしているので効率が悪いです。また、電圧も大会に出場する際の半分ほどなので、これを改善すればもっとスピードが出ると思います。

 こんな感じに今回の機体を作りました。インバータは近いうちに作ろうと思いますが、以前の大会で使っていた電池がどうも怪しいので、電源を変えるのは当分先かなと思います。
 最近は、プログラミングして動画編集してブログ書いて…と忙しいので、この改良をする前に色々片付けることになりそうです。
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

読者登録
LINE読者登録QRコード