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

相关推荐
年纪轻轻只想躺平19 分钟前
JavaScript ES6+ 最佳实践
前端·javascript·es6
CHQIUU43 分钟前
使用 CDN 在国内加载本地 PDF 文件并处理批注:PDF.js 5.x 实战指南
开发语言·javascript·pdf
geovindu2 小时前
javascript: Multi-page PDF in Canvas using PDFJS 5.1
前端·javascript
吃面必吃蒜2 小时前
前端实战中的单例模式:以医疗药敏管理为例
前端·javascript·单例模式·设计模式
哎哟喂_!2 小时前
Node.js vs 浏览器中的JavaScript:区别全解析
开发语言·javascript·node.js
这个懒人3 小时前
Solidity语言基础:区块链智能合约开发入门指南
javascript·python·智能合约·solidity
不吃香菜的猪3 小时前
Axios替代品Alova
前端·javascript
大G哥3 小时前
.NET 配置文件详解:高效使用 .props 文件
开发语言·前端·javascript·ui·.net
百锦再3 小时前
《易语言学习大全》
开发语言·javascript·python·学习·django·sqlite·android studio
纪元A梦9 小时前
华为OD机试真题——荒岛求生(2025A卷:200分)Java/python/JavaScript/C/C++/GO最佳实现
java·c语言·javascript·c++·python·华为od·go