Open12

水やりWebアプリ🌸(ユーザーの動作を可視化するwebアプリケーションをアート思考で作成)

VanVan

【アイデア出し】

  • アノニマスのお面をかぶってWebカメラに向かって水やりをすると画面上で花が咲く
    →水やりは前回使用できなかったチルトセンサ(傾きセンサ)をobnizに接続して入力ポートがONなら花が咲くエフェクト、OFFなら何もしないという動きをさせたい。

世界を混乱に陥れるアノニマスが実は優しい心の持ち主だったというストーリーにしたい。

VanVan

とりあえず入力ポートの状態をみて、ON/OFFをp5.jsのエディタ上のコンソールとobnizのディプレイに表示されることはできた。
が、コンソール上にエラーメッセージが2件表示された。GitHub Discussionsに投げておく。

入力ポートは内蔵プルアップが使えるらしい。
内蔵プルアップは本業でよく使っている。配線を減らすことができるのがとても良い。

が、obnizのドキュメントにプルアップ抵抗値が書いてないので、面倒だけどチップセットのESP32-WROOM-32のデータシートを確認した。

とりあえずIOポートのHi電流は20mA以内だったら大丈夫そう。

内蔵プルアップ抵抗は45kΩtyp.だから、5[V]÷45[kΩ]=0.11[mA]
全然OK。

sketch.js
const obniz = new Obniz('Obniz_ID'); // Obniz_IDに自分のIDを入れます

// obnizがオンラインであることが確認されたら、以下の関数内が自動で実行されます
obniz.onconnect = async function () {   

    
  //*******ここから下にコードを入力*******

  obniz.io0.pull("5v");
  obniz.io1.output(false);

  obniz.io0.input(function(value){
  console.log("changed to " + value);
  obniz.display.clear();

  if (value === true) {
    // スイッチがOFF状態
    console.log('OFF');
    obniz.display.print('OFF');
  }
  else {
    // スイッチがON状態
    console.log('ON');
    obniz.display.print('ON');
  }
  });

  //*******ここまでの間にコードを入力*******
}

あとは以下のコードをGPTに聞いてp5.jsで実装できれば完成。

  • WebカメラをONする
  • チルトセンサONのときにWebアプリ上に花が咲くエフェクトをつける
VanVan

しーたけさんがすぐにQiitaの参考記事をご紹介くださり、一瞬で解決した。感謝。

修正後のコード

sketch.js
const obniz = new Obniz('Obniz_ID',{local_connect : false}); // Obniz_IDに自分のIDを入れます

// obnizがオンラインであることが確認されたら、以下の関数内が自動で実行されます
obniz.onconnect = async function () {   

    
  //*******ここから下にコードを入力*******

  obniz.io0.pull("5v");
  obniz.io1.output(false);

  obniz.io0.input(function(value){
  console.log("changed to " + value);
  obniz.display.clear();

  if (value === true) {
    // スイッチがOFF状態
    console.log('OFF');
    obniz.display.print('OFF');
  }
  else {
    // スイッチがON状態
    console.log('ON');
    obniz.display.print('ON');
  }
  });

  //*******ここまでの間にコードを入力*******
}
VanVan

p5.jsでobnizのチルトセンサがONしたら花を咲かすエフェクトってGPTに聞いたら変なこと返ってきそうな気がしたから、p5.jsでスペースキーを押したら花を咲かすエフェクトという形でできるだけシンプルな答えを引き出したい。

それが完璧になってからスペースキーの部分をobnizのチルトセンサに置き換えたい。

VanVan

気が済むまでGTP-4oとラリー

1
あなたはp5.jsのエキスパートです。
p5.jsのエディタ上で実行することで、スペースキーを押すことで花が咲くようにしたい。
それぞれコードを教えて
2
スペースキーを押すたびに花が増えるようにしたい
3
色々な色の花を咲かせたい
4
背景が寂しい。草原の背景にしたい。
HTMLコードもしくはCSSコードもしくはJavaScriptコードを教えて

WebカメラONにすることすっかり忘れてた

5
ごめんなさい。
・背景はなしで、PCのカメラをONにしたいです
・花が咲くとき効果音を付けて
6
花が咲くエフェクトをもっとダイナミックに派手に装飾して
VanVan

音が再生されない問題。
以下のサイトを参考に、コードと同じ階層にassetsのフォルダを作って、その中にmp3ファイルを格納した。
https://yoppa.org/taunet14/5921.html

修正後のコード

sketch.js
let flowers = [];
let capture;
let bloomSound;
let sparks = [];

function preload() {
  bloomSound = loadSound('assets/きらきら輝く3.mp3'); // 効果音ファイルをロード
}

function setup() {
  createCanvas(800, 600);
   
  // Webカメラのキャプチャを開始
  capture = createCapture(VIDEO);
  capture.size(800, 600);
  capture.hide(); // デフォルトではビデオエレメントを隠します
}

function draw() {
  // カメラ映像を背景として表示
  image(capture, 0, 0, width, height);
  
  // 配列内の全ての花を描画
  for (let i = 0; i < flowers.length; i++) {
    let flower = flowers[i];
    drawFlower(flower.x, flower.y, flower.color);
  }

  // スパークルエフェクトを描画
  for (let i = sparks.length - 1; i >= 0; i--) {
    if (sparks[i].isFinished()) {
      sparks.splice(i, 1); // スパークルの寿命が尽きたら配列から削除
    } else {
      sparks[i].update();
      sparks[i].display();
    }
  }
}

// スペースキーが押された時に呼び出される関数
function keyPressed() {
  if (key === ' ') {
    // ランダムな位置に新しい花を追加
    let flowerX = random(width);
    let flowerY = random(height);
    
    // ランダムな色を生成
    let r = random(255);
    let g = random(255);
    let b = random(255);
    let flowerColor = color(r, g, b);
    
    flowers.push({x: flowerX, y: flowerY, color: flowerColor});
    
    // 効果音を再生
    if (bloomSound.isLoaded()) {
      bloomSound.play();
    }
    
    // スパークルエフェクトを追加
    for (let i = 0; i < 100; i++) {
      sparks.push(new Spark(flowerX, flowerY));
    }
  }
}

// 花を描画する関数
function drawFlower(x, y, col) {
  push();
  translate(x, y);
  
  // 花の茎
  stroke(0, 128, 0);
  strokeWeight(4);
  line(0, 0, 0, 100);
  
  // 花びら
  noStroke();
  fill(col);
  for (let i = 0; i < 10; i++) {
    ellipse(20 * cos(TWO_PI * i / 10), 20 * sin(TWO_PI * i / 10), 30, 30);
  }
  
  // 花の中心
  fill(255, 255, 0);
  ellipse(0, 0, 30, 30);
  
  pop();
}

// スパークルエフェクト用のクラス
class Spark {
  constructor(x, y) {
    this.pos = createVector(x, y);
    this.vel = p5.Vector.random2D().mult(random(1, 6));
    this.lifespan = 255;
  }

  update() {
    this.pos.add(this.vel);
    this.vel.mult(0.95); // 速度を減少させる
    this.lifespan -= 5;
  }

  display() {
    noStroke();
    fill(255, this.lifespan);
    ellipse(this.pos.x, this.pos.y, 5);
  }

  isFinished() {
    return this.lifespan < 0;
  }
}
VanVan

全然すんなりいかなかった。結局最初に戻ってGPTに聞き直し。
最初からobnizの接続を想定しておけばよかった。

最終的なコード

sketch.js
let obniz
let flowers = [];
let camera;
let bloomSound;
let lastClickTime = 0;
const debounceTime = 1000; // デバウンスする時間(ミリ秒)

function preload() {
  // 効果音を読み込む
  // ご自身のサウンドファイルのパスを使用してください
  bloomSound = loadSound('assets/きらきら輝く3.mp3'); // サウンドファイルのURLを指定
}

function setup() {
  createCanvas(640, 480);
  
  // カメラを起動
  camera = createCapture(VIDEO);
  camera.size(640, 480);
  camera.hide(); // カメラ映像を表示しない

  // Obnizの初期化
  obniz = new Obniz('obnizId',{local_connect : false});

  obniz.onconnect = async function () {
    let button = obniz.wired("Button", { signal: 1, gnd: 0 });

    button.onchange = function(pressed) {
      let currentTime = Date.now();
      if (currentTime - lastClickTime > debounceTime) {
        lastClickTime = currentTime;
        if (pressed) {
          // 新しい花を追加
          let newFlower = {
            x: random(width),
            y: random(height),
            color1: color(random(255), random(255), random(255)),
            color2: color(random(255), random(255), random(255))
          };
          flowers.push(newFlower);
          bloomSound.play(); // 効果音を再生
        }
      }
    };
  };

  // 連続的に描画するためにはエンドレスループを設定
  loop();
}

function draw() {
  background(255);
  
  // カメラ映像を背景にする
  image(camera, 0, 0, width, height);

  // 一つ一つの花を描画
  for (let flower of flowers) {
    drawFlower(flower.x, flower.y, flower.color1, flower.color2);
  }
}

function drawFlower(x, y, col1, col2) {
  noStroke();
  fill(col1);
  for (let i = 0; i < 10; i++) {
    ellipse(x + 40 * cos(TWO_PI * i / 10), y + 40 * sin(TWO_PI * i / 10), 40, 40);
  }
  fill(col2);
  ellipse(x, y, 40, 40);
}
VanVan

動くは動くんだが、エラーメッセージが表示される。
気持ちが悪いのでこれもGitHub Discussionsに投げておく。

前回質問できたおかげで質問のフォーマットができていたので、時間をかけずに質問することができた。

VanVan

GitHub Discussionに投げた質問をまたしーたけさんに答えていただいた。
おかげでエラーメッセージがなくなり、気持ちよく実行することができるようになった。

VanVan

以下2点修正した。

  1. HTMLコードを修正して、デモのプレビュー画面に「ダイヤルスイッチを押したらお花が咲くよ🌸」という文言を追加(お試しのデモ用のみ)

  2. 表示される花を明るい色になるように補正
    (当初、RGB値すべて155以上255以下に修正したが、明るいというよりは白っぽい色味になっただった。R値を255に固定して、GB値を0~255のランダムとすることで、赤みのある明るい色に補正することができた。)

修正後の最終的なコード

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.4/p5.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.4/addons/p5.sound.min.js"></script>
    <script src="https://unpkg.com/obniz@3.31.0/obniz.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css">
    <meta charset="utf-8" />

  </head>
  <body>
    <main>
      <h2>ダイヤルスイッチを押したらお花が咲くよ🌸</h2>
    </main>
    <script src="sketch.js"></script>
  </body>
</html>
sketch.js
let obniz
let flowers = [];
let camera;
let bloomSound;
let lastClickTime = 0;
const debounceTime = 1000; // デバウンスする時間(ミリ秒)

function preload() {
  // 効果音を読み込む
  // ご自身のサウンドファイルのパスを使用してください
  bloomSound = loadSound('assets/きらきら輝く3.mp3'); // サウンドファイルのURLを指定
}

function setup() {
  createCanvas(640, 480);
  
  // カメラを起動
  camera = createCapture(VIDEO);
  camera.size(640, 480);
  camera.hide(); // カメラ映像を表示しない
  
  // Obnizの初期化
  obniz = new Obniz('obnizId',{local_connect : false});

  obniz.onconnect = async function () {
    let state = await obniz.switch.getWait();
  

      obniz.switch.onchange = function(state) {
      let currentTime = Date.now();
      if (currentTime - lastClickTime > debounceTime) {
        lastClickTime = currentTime;
        if (state === "push") {
          // 新しい花を追加
          let newFlower = {
            x: random(width),
            y: random(height),
            color1: color(255, random(155, 255), random(155, 255)),
            color2: color(255, random(155, 255), random(155, 255))
          };
          flowers.push(newFlower);
          bloomSound.play(); // 効果音を再生
        }
      }
    };
    // };    
  };

  // 連続的に描画するためにはエンドレスループを設定
  loop();
}

function draw() {
  background(255);
  
  // カメラ映像を背景にする
  image(camera, 0, 0, width, height);

  // 一つ一つの花を描画
  for (let flower of flowers) {
    drawFlower(flower.x, flower.y, flower.color1, flower.color2);
  }
}

function drawFlower(x, y, col1, col2) {
  noStroke();
  fill(col1);
  for (let i = 0; i < 10; i++) {
    ellipse(x + 40 * cos(TWO_PI * i / 10), y + 40 * sin(TWO_PI * i / 10), 40, 40);
  }
  fill(col2);
  ellipse(x, y, 40, 40);
}
style.css
html, body {
  margin: 0;
  padding: 0;
}
canvas {
  display: block;
}