xxxxxxxxxx
let osc; // オシレーター
let frequency; // ランダムな周波数
let ripples = []; // 波紋のリスト
let waves = []; // ランダムで現れる波のリスト
let spawnInterval = 2000; // 新しい波が現れる間隔(ミリ秒)
let lastSpawnTime = 0; // 最後に波が現れた時間
function setup() {
createCanvas(800, 800);
noFill();
// サウンドライブラリを初期化
getAudioContext().resume();
}
function draw() {
background(255);
// 波紋を更新・描画
for (let i = ripples.length - 1; i >= 0; i--) {
ripples[i].update();
ripples[i].display();
// 波紋が終了したら削除
if (ripples[i].isFinished()) {
ripples.splice(i, 1);
}
}
// ランダムに現れる波を更新・描画
for (let i = waves.length - 1; i >= 0; i--) {
waves[i].update();
waves[i].display();
// 波形が終了したら削除
if (waves[i].isFinished()) {
waves.splice(i, 1);
}
}
// 一定時間ごとに中央から新しい波を生成
if (millis() - lastSpawnTime > spawnInterval) {
waves.push(new Wave(width / 2, height / 2)); // 画面中央に新しい波を生成
lastSpawnTime = millis();
}
}
function mousePressed() {
// クリック位置から波紋を生成
ripples.push(new Ripple(mouseX, mouseY));
}
// 波紋を管理するクラス
class Ripple {
constructor(x, y) {
this.x = x; // 波紋の中心X
this.y = y; // 波紋の中心Y
this.radius = 0; // 波紋の半径
this.speed = 2; // 波紋が広がる速度
this.lifetime = 255; // 波紋の寿命
this.components = [];
// 8Hz〜13Hzの周波数成分を生成
for (let i = 0; i < 5; i++) {
let frequency = random(8, 13); // 周波数を8Hz〜13Hzでランダム
let amplitude = random(5, 20); // 振幅をランダム
let phase = random(TWO_PI); // 初期位相をランダム
this.components.push({ frequency, amplitude, phase });
// 音の生成
this.createSound(frequency, amplitude);
}
}
// 音を生成するメソッド
createSound(frequency, amplitude) {
let osc = new p5.Oscillator('sine');
osc.freq(frequency);
osc.amp(amplitude * 0.01); // 音量調整
osc.start();
osc.stop(0.1); // 音の持続時間
}
// 更新処理
update() {
this.radius += this.speed; // 半径を拡大
this.lifetime -= 2; // 寿命を減少
}
// 描画処理
display() {
stroke(0, this.lifetime); // 寿命に応じて透明度を変更
noFill();
beginShape();
// 波紋の輪郭を描画
for (let angle = 0; angle < TWO_PI; angle += PI / 100) {
let r = this.radius;
let waveOffset = 0;
// 各周波数成分を合成して波紋の形を計算
for (let comp of this.components) {
waveOffset += comp.amplitude * sin(2 * PI * comp.frequency * (this.radius / 100) + comp.phase);
}
let x = this.x + (r + waveOffset) * cos(angle);
let y = this.y + (r + waveOffset) * sin(angle);
vertex(x, y);
}
endShape(CLOSE);
}
// 波紋が終了したか確認
isFinished() {
return this.lifetime <= 0;
}
}
// ランダムに現れる波を管理するクラス
class Wave {
constructor(x, y) {
this.x = x; // 波形の中心X
this.y = y; // 波形の中心Y
this.length = 0; // 波形の表示長さ
this.maxLength = width; // 波形の最大長さ
this.speed = 5; // 波形の広がる速度
this.components = [];
// 8Hz〜13Hzの周波数成分を生成
for (let i = 0; i < 5; i++) {
let frequency = random(8, 13); // 周波数を8Hz〜13Hzでランダム
let amplitude = random(20, 50); // 振幅をランダム
let phase = random(TWO_PI); // 初期位相をランダム
this.components.push({ frequency, amplitude, phase });
// 音の生成
this.createSound(frequency, amplitude);
}
this.time = 0; // 時間の経過
}
// 音を生成するメソッド
createSound(frequency, amplitude) {
let osc = new p5.Oscillator('sine');
osc.freq(frequency);
osc.amp(amplitude * 0.01); // 音量調整
osc.start();
osc.stop(0.1); // 音の持続時間
}
// 更新処理
update() {
this.time += 0.02; // 時間を進める
this.length += this.speed; // 波形を広げる
if (this.length > this.maxLength) {
this.length = this.maxLength;
}
}
// 描画処理
display() {
stroke(0);
noFill();
beginShape();
// 波形を描画
for (let t = -this.length / 2; t < this.length / 2; t++) {
let yOffset = 0;
// 各周波数成分を合成して波形の値を計算
for (let comp of this.components) {
yOffset += comp.amplitude * sin(2 * PI * comp.frequency * (t / width) + comp.phase + this.time);
}
let x = this.x + t; // X座標は中心から左右に広がる
let y = this.y + yOffset; // Y座標に波形の値を加算
vertex(x, y);
}
endShape();
}
// 波形が終了したか確認
isFinished() {
return this.length >= this.maxLength && this.time > 5; // 時間が経過したら終了
}
}