如何使用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
相关产品推荐
相关产品推荐

