You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用p5.js与Matter.js绘制金字塔形状的圆形

实现金字塔排列的圆形(Matter.js + p5.js)

问题背景

需要绘制金字塔形状排列的圆形,已基于Matter.js和p5.js编写Balls类,但当前所有球都生成在同一坐标,无法形成金字塔布局。

修改后完整代码

class Balls {
  constructor(x, y, radius, color, ballCount) {
    this.x = x;
    this.y = y;
    this.radius = radius;
    this.color = color;
    this.balls = [];
    this.ballCount = ballCount;
    this.option = { restitution: 1, friction: 0.01, label: "ball" };
  }

  setupBalls() {
    // 计算金字塔层数:通过累加1+2+3+...直到总和等于总球数
    let layers = 0;
    let total = 0;
    while (total < this.ballCount) {
      layers++;
      total += layers;
    }

    const diameter = this.radius * 2;
    // 上下层球的垂直间距:正三角形的高 = 半径 * √3,保证球相切
    const verticalGap = this.radius * Math.sqrt(3);

    let currentBallIndex = 0;
    // 遍历每一层生成球
    for (let layer = 1; layer <= layers; layer++) {
      // 当前层起始x坐标:让整层水平居中
      const startX = this.x - (layer - 1) * this.radius;
      // 当前层的y坐标
      const currentY = this.y + (layer - 1) * verticalGap;

      // 生成当前层的每个球
      for (let i = 0; i < layer; i++) {
        if (currentBallIndex >= this.ballCount) break; // 避免超过设定的总球数
        const ballX = startX + i * diameter;
        const ball = Bodies.circle(ballX, currentY, this.radius, this.option);
        this.balls.push(ball);
        World.add(engine.world, ball);
        currentBallIndex++;
      }
    }
  }

  drawBalls() {
    fill(this.color);
    noStroke();
    for (let ball of this.balls) {
      drawVertices(ball.vertices);
    }
  }
}

// Matter.js 模块别名
var Engine = Matter.Engine;
var World = Matter.World;
var Bodies = Matter.Bodies;
var Body = Matter.Body;

function setup() {
  createCanvas(1200, 600);
  // 创建物理引擎并关闭重力
  engine = Engine.create();
  engine.world.gravity.y = 0;

  // 初始化金字塔球:中心x、起始y、半径、颜色、总球数(15对应5层金字塔)
  balls = new Balls(width / 2, 100, 8, color(200, 0, 0), 15);
  balls.setupBalls();
}

function draw() {
  background(125);
  Engine.update(engine);
  balls.drawBalls();
}

关键逻辑说明

  • 层数计算:通过累加自然数得到金字塔层数,比如15个球对应5层(1+2+3+4+5=15)
  • 坐标控制:
    • 水平方向:每层起始x基于中心坐标向左偏移,保证整层居中,同层球x坐标依次增加一个直径,确保相切
    • 垂直方向:每层y坐标基于初始y递增正三角形的高,保证上下层球相切
  • 边界处理:添加判断防止生成的球数量超过设定的总球数

内容的提问来源于stack exchange,提问作者vince

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 16:15:55