p5.js:模拟 n个彩色小球在一个3D大球体内部弹跳

向 豆包 提问:编写一个 p5.js 脚本,模拟 42 个彩色小球在一个3D大球体内部弹跳。每个小球都应留下一条逐渐消失的轨迹。大球体应缓慢旋转,并显示透明的轮廓线。请确保实现适当的碰撞检测,使小球保持在球体内部。

cd p5-demo

copy .\node_modules\p5\lib\p5.min.js .

编写 p5_3d_42_balls.html 如下

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3D Bouncing Balls in Sphere</title>
    <script src="p5.min.js"></script>
</head>

<body>
<script>
    let balls = [];
    let sphereRadius = 200;
    let rotationSpeed = 0.01;

    function setup() {
        createCanvas(800, 600, WEBGL);
        for (let i = 0; i < 42; i++) {
            balls.push(new Ball());
        }
    }

    function draw() {
        background(0);
        rotateX(frameCount * rotationSpeed);
        rotateY(frameCount * rotationSpeed);

        // 绘制大球体
        stroke(255, 100);
        noFill();
        sphere(sphereRadius);

        // 更新并绘制小球
        for (let ball of balls) {
            ball.update();
            ball.display();
        }
    }

    class Ball {
        constructor() {
            this.pos = p5.Vector.random3D().mult(random(0, sphereRadius));
            this.vel = p5.Vector.random3D().mult(random(1, 3));
            this.color = color(random(255), random(255), random(255));
            this.trail = [];
            this.trailLength = 20;
        }

        update() {
            this.pos.add(this.vel);

            // 碰撞检测
            let distanceToCenter = this.pos.mag();
            if (distanceToCenter > sphereRadius) {
                let normal = this.pos.copy().normalize();
                this.vel.reflect(normal);
                // 确保小球回到球体内
                this.pos = normal.mult(sphereRadius - 0.1); 
            }

            // 更新轨迹
            this.trail.push(this.pos.copy());
            if (this.trail.length > this.trailLength) {
                this.trail.shift();
            }
        }

        display() {
            // 绘制轨迹
            for (let i = 0; i < this.trail.length; i++) {
                let alpha = map(i, 0, this.trail.length, 255, 0);
                stroke(this.color.levels[0], this.color.levels[1], this.color.levels[2], alpha);
                if (i > 0) {
                    line(this.trail[i - 1].x, this.trail[i - 1].y, this.trail[i - 1].z, this.trail[i].x, this.trail[i].y, this.trail[i].z);
                }
            }

            // 绘制小球
            fill(this.color);
            noStroke();
            push();
            translate(this.pos.x, this.pos.y, this.pos.z);
            sphere(5);
            pop();
        }
    }
</script>
</body>
</html>

双击打开 p5_3d_42_balls.html


交互式分形树

  • 描述: 创建一个分形树,用户可以通过鼠标或键盘控制树的生长角度、分支长度等参数。

  • 编写 p5_branch.html 如下

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>p5 branch Example</title>
   <script src="p5.min.js"></script>
</head>
<body>
<script>
// 创建分形树,用户可以通过鼠标控制树的生长角度、分支长度等参数。
  function setup() {
    createCanvas(800, 600);
    angleMode(DEGREES);
  }
  
  function draw() {
    background(50);
    stroke(255);
    translate(width/2, height);
    branch(map(mouseX, 0, width, 50, 150));
  }
  
  function branch(len) {
    line(0, 0, 0, -len);
    translate(0, -len);
  
    if (len > 4) {
      push();
      rotate(map(mouseY, 0, height, 20, 60));
      branch(len * 0.67);
      pop();
      push();
      rotate(-map(mouseY, 0, height, 20, 60));
      branch(len * 0.67);
      pop();
    }
  }
</script>
</body>
</html>

双击打开 p5_branch.html


动态波形生成器

  • 描述: 创建一个动态波形,用户可以通过鼠标或键盘控制波形的频率、振幅或颜色。

  • 编写 p5_wave.html 如下

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>p5 wave Example</title>
   <script src="p5.min.js"></script>
</head>
<body>
<script>
  let angle = 0;
  let amplitude = 100;
  let frequency = 0.02;
  
  function setup() {
    createCanvas(windowWidth, windowHeight);
  }
  
  function draw() {
    background(0);
    noFill();
    stroke(255);
    strokeWeight(2);
  
    beginShape();
    for (let x = 0; x < width; x += 10) {
      let y = height / 2 + sin(angle + x * frequency) * amplitude;
      vertex(x, y);
    }
    endShape();
  
    angle += 0.05;
  }
  
  function mouseMoved() {
    amplitude = map(mouseY, 0, height, 50, 200);
    frequency = map(mouseX, 0, width, 0.01, 0.1);
  }
</script>
</body>
</html>

双击打开 p5_wave.html

相关推荐
Fantasywt3 小时前
THREEJS 片元着色器实现更自然的呼吸灯效果
前端·javascript·着色器
IT、木易3 小时前
大白话JavaScript实现一个函数,将字符串中的每个单词首字母大写。
开发语言·前端·javascript·ecmascript
Mr.NickJJ4 小时前
JavaScript系列06-深入理解 JavaScript 事件系统:从原生事件到 React 合成事件
开发语言·javascript·react.js
念九_ysl5 小时前
深入解析Vue3单文件组件:原理、场景与实战
前端·javascript·vue.js
Jenna的海糖5 小时前
vue3如何配置环境和打包
前端·javascript·vue.js
Mr.NickJJ6 小时前
React Native v0.78 更新
javascript·react native·react.js
烛阴6 小时前
JavaScript 构造器进阶:掌握 “new” 的底层原理,写出更优雅的代码!
前端·javascript
Alan-Xia6 小时前
使用jest测试用例之入门篇
前端·javascript·学习·测试用例
鱼樱前端6 小时前
📚 Vue Router 4 核心知识点(Vue3技术栈)面试指南
前端·javascript·vue.js
JobsandCzj6 小时前
PDF 分割工具
javascript·小程序·pdf