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

发布于:2025-03-09 ⋅ 阅读:(10) ⋅ 点赞:(0)

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

cd p5-demo
copy .\node_modules\p5\lib\p5.min.js .
编写  p5_3d_42_balls.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  如下

  • <!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  如下

  • <!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 


网站公告

今日签到

点亮在社区的每一天
去签到