可视化之粒子风场

绘制风场的关键点在Perlin 噪声。我们依然采用p5.js来绘制风场。 Perlin 噪声,Perlin 噪声是一种基于梯度的连续随机函数,可以用来生成连续的、自然的随机数。在这个代码中,我们使用 Perlin 噪声来计算粒子的运动角度,以此来实现粒子的运动轨迹。

在 Particle 类中,我们使用了 Perlin 噪声来计算粒子的角度,并根据角度计算粒子的方向向量和速度向量。然后,我们将速度向量乘以大小系数,并使用 add() 函数将速度向量加到位置向量上,从而更新粒子的位置。

在 Particle 类中,我们使用 checkEdges() 方法来检测粒子是否碰到边界,如果是则重新生成粒子。这样可以避免粒子飞出画布,同时也可以增加粒子的数量和密度。

在 setup() 函数中,我们创建了三个粒子数组,分别用来存储不同颜色的粒子对象。这样可以方便地遍历和绘制不同颜色的粒子。

在 draw() 函数中,我们使用 rect() 函数来绘制背景。由于我们希望背景具有一定的透明度,所以使用了 fill() 函数来设置背景颜色的透明度。

js 复制代码
// 定义粒子类
class Particle {
    constructor(loc_, dir_, speed_) {
        this.loc = loc_; // 粒子位置向量
        this.dir = dir_; // 粒子方向向量
        this.speed = speed_; // 粒子速度
        this.d = 1; // 粒子大小系数
    }

    // 粒子运动,包括更新位置和速度
    move() {
        // 使用 Perlin 噪声计算粒子的角度
        this.angle = noise(this.loc.x / noiseScale, this.loc.y / noiseScale, frameCount / noiseScale) * TWO_PI * noiseStrength;
        // 根据角度计算粒子的方向向量
        this.dir.x = cos(this.angle) + sin(this.angle) - sin(this.angle);
        this.dir.y = sin(this.angle) - cos(this.angle) * sin(this.angle);
        // 根据方向向量计算粒子的速度向量
        this.vel = this.dir.copy();
        this.vel.mult(this.speed * this.d);
        // 更新粒子的位置向量
        this.loc.add(this.vel);
    }

    // 检测粒子是否碰到边界,如果是则重新生成粒子
    checkEdges() {
        if (this.loc.x < 0 || this.loc.x > width || this.loc.y < 0 || this.loc.y > height) {
            this.loc.x = random(width * 1.2);
            this.loc.y = random(height);
        }
    };

    // 更新粒子的大小和位置
    update(r) {
        ellipse(this.loc.x, this.loc.y, r);
    };

    // 粒子的总运动,包括运动、碰撞检测和更新
    run() {
        this.move();
        this.checkEdges();
        this.update();
    }
}

// 粒子数量
let num = 1024;

// 粒子数组
var particles_a = [];
var particles_b = [];
var particles_c = [];

// 粒子消失的速度
var fade = 600;

// 粒子半径
var radius = 3; 

// 噪声的规模
let noiseScale = 400;

// 噪声的强度
let noiseStrength = 1.4;

function setup() {
    createCanvas(windowWidth, windowHeight);
    noStroke();
    // 创建粒子数组
    for (let i = 0; i < num; i++) {
        // 随机生成粒子的位置向量和方向向量
        let loc_a = createVector(random(width * 1.2), random(height), 2);
        let angle_a = random(TWO_PI);
        let dir_a = createVector(cos(angle_a), sin(angle_a));
        let loc_b = createVector(random(width * 1.2), random(height), 2);
        let angle_b = random(TWO_PI);
        let dir_b = createVector(cos(angle_b), sin(angle_b));
        let loc_c = createVector(random(width * 1.2), random(height), 2);
        let angle_c = random(TWO_PI);
        let dir_c = createVector(cos(angle_c), sin(angle_c));
        // 创建粒子对象并添加到数组中
        particles_a[i] = new Particle(loc_a, dir_a, 0.5);
        particles_b[i] = new Particle(loc_b, dir_b, 0.5);
        particles_c[i] = new Particle(loc_c, dir_c, 0.75);

    }
}

function draw() {
    // 绘制背景
    fill(0, 2); 
    noStroke();
    rect(0, 0, width, height);

    // 遍历所有的粒子
    for (let i = 0; i < num; i++) {
        // 绘制蓝色粒子
        fill(255, fade); 
        particles_a[i].move();
        particles_a[i].update(radius);
        particles_a[i].checkEdges();

        // 绘制青色粒子
        fill(0, 255, 255, fade); 
        particles_b[i].move();
        particles_b[i].update(radius);
        particles_b[i].checkEdges();

        // 绘制浅蓝色粒子
        fill(102, 153, 255, fade); 
        particles_c[i].move();
        particles_c[i].update(radius);
        particles_c[i].checkEdges();
    }
}

在 Particle 类中,我们定义了四个方法:

  1. constructor() 方法:在创建粒子对象时,初始化粒子的位置向量、方向向量、速度和大小系数。

  2. move() 方法:根据 Perlin 噪声计算粒子的角度,并根据角度计算粒子的方向向量和速度向量,最后根据速度向量更新粒子的位置向量。

  3. checkEdges() 方法:检测粒子是否碰到边界,如果是则重新生成粒子。

  4. update() 方法:更新粒子的大小和位置。

在 setup() 函数中,我们完成了以下工作:

  1. 创建画布。

  2. 创建粒子数组。

  3. 随机生成粒子的位置向量和方向向量,并创建粒子对象并添加到数组中。

在 draw() 函数中,我们完成了以下工作:

  1. 绘制背景。

  2. 遍历所有的粒子,在每个粒子的位置绘制相应颜色的粒子。

  3. 调用粒子对象的方法,包括运动、碰撞检测和更新。

相关推荐
默_笙4 分钟前
🚥 给 RAG 装一台心电监护仪:LangSmith 全链路观测(上)
前端·javascript
计算机源码社39 分钟前
基于大数据技术的城市空气质量时序趋势与站点特征分析系统 面向监测站点的城市空气污染时空异质性分析与可视化系统
大数据·机器学习·数据挖掘·数据分析·毕业设计·课程设计·数据可视化
前端snow1 小时前
ai agent --- mem0 外挂记忆系统
前端
特立独行的猫a2 小时前
用仓颉写一个 Tauri:IPC 的每次往返实现原理(web层到仓颉层的触发过程)
前端·ui·harmonyos·tauri·鸿蒙·仓颉
Dovis(誓平步青云)2 小时前
多个链接不等于多份证据,新闻核验看板怎样合并来源
java·服务器·前端·javascript·人工智能·pdf·电脑
骑着蜗牛撵大象3272 小时前
Qt 事件机制详解:从 QEvent 派生类到事件过滤器的全景指南
前端·python
qq_2518364573 小时前
理发管理系统 —— 会员模块
开发语言·前端·python·flask
Frag0ut3 小时前
2027 年浏览器展望:Chrome 与 Edge 的 AI 智能体进化方向
前端·人工智能·chrome·edge·浏览器·新功能
计算机魔术师3 小时前
从AI绘图鼻祖到音乐版权破局者,Stability AI如何被三大唱片巨头「收编」
前端
奕鼎竜瑆4 小时前
Chrome 插件开发实战指南:从入门到发布
前端·chrome