2
3

推力変更ノズルシュミレーション。遅い、鼻毛が伸びる様子を見ているようだ。

Last updated at Posted at 2024-08-30

スクリーンショット 2024-08-30 175827.png

スクリーンショット 2024-08-30 175816.png

マウスの位置に基づいて風向きを指定し、その影響をパーティクルに反映させることができるゲーム。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>スモークパーティクルシミュレーション</title>
  <!-- p5.js ライブラリを含める -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }
    canvas {
      display: block;
    }
  </style>
</head>
<body>
  <script>
    let particleSystem;

    function setup() {
      createCanvas(windowWidth, windowHeight); // 全画面のキャンバスを作成
      colorMode(HSB); // カラーモードをHSBに設定
      particleSystem = new ParticleSystem(createVector(width / 2, height - 50)); // パーティクルシステムを初期化
    }

    function draw() {
      background(0, 0, 0, 25); // 背景を徐々に消えるように設定(スモークの効果)

      // マウスの位置に基づいて風力を計算
      let wind = createVector(mouseX - width / 2, mouseY - height / 2);
      wind.normalize(); // 風力の方向を正規化
      wind.mult(0.1); // 風力の強さを調整

      // パーティクルシステムに風力を適用
      particleSystem.applyForce(wind);
      particleSystem.addParticle(); // 新しいパーティクルを追加
      particleSystem.run(); // パーティクルシステムを更新し、表示する
    }

    class ParticleSystem {
      constructor(origin) {
        this.particles = []; // パーティクルの配列
        this.origin = origin.copy(); // 発生源の位置をコピー
      }

      run() {
        // 各パーティクルを更新し、表示する
        for (let i = this.particles.length - 1; i >= 0; i--) {
          let p = this.particles[i];
          p.run();
          if (p.isDead()) {
            this.particles.splice(i, 1); // 死亡したパーティクルを削除
          }
        }
      }

      addParticle() {
        this.particles.push(new Particle(this.origin)); // 新しいパーティクルを追加
      }

      applyForce(force) {
        for (let p of this.particles) {
          p.applyForce(force); // すべてのパーティクルに風力を適用
        }
      }
    }

    class Particle {
      constructor(origin) {
        this.position = origin.copy(); // パーティクルの位置を初期化
        this.velocity = createVector(random(-1, 1), random(-2, 0)); // ランダムな速度を設定
        this.acceleration = createVector(); // 加速度を初期化
        this.lifespan = 255; // 寿命を設定
        this.color = color(random(0, 360), 80, 80); // 色を設定(HSB)
      }

      run() {
        this.update(); // パーティクルの更新
        this.display(); // パーティクルの表示
      }

      update() {
        this.velocity.add(this.acceleration); // 加速度を速度に加算
        this.position.add(this.velocity); // 速度を位置に加算
        this.acceleration.mult(0); // 加速度をリセット
        this.lifespan -= 2; // 寿命を減少
      }

      display() {
        noStroke(); // パーティクルの枠線なし
        fill(this.color.levels[0], this.color.levels[1], this.color.levels[2], this.lifespan); // 色と透明度を設定
        ellipse(this.position.x, this.position.y, 12); // パーティクルを描画
      }

      applyForce(force) {
        this.acceleration.add(force); // 加速度に風力を追加
      }

      isDead() {
        return this.lifespan <= 0; // 寿命が終了したかチェック
      }
    }
  </script>
</body>
</html>

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3