p5.js中小圆在大圆内部碰撞反弹的运动向量计算问题
p5.js 大圆内部小圆弹跳碰撞速度计算方案
你当前的错误出在碰撞后速度向量的计算逻辑,无需手动构造反向力,使用向量反射运算即可得到正确的弹跳方向:
核心逻辑说明
- 大圆内壁碰撞的法线向量为大圆圆心指向小圆中心的方向,该向量垂直于碰撞点的切线方向
- 直接调用p5.js内置的
reflect()方法对速度向量做反射运算,即可得到反弹后的速度 - 碰撞后需要先把小圆位置回退到合法边界内,避免卡在边界触发多次错误碰撞
修改后完整代码
JavaScript 代码
let pos, vel, acc; // 提前定义固定参数,避免硬编码出错 const bigCircleRadius = 50; const smallCircleRadius = 10; const bigCircleCenter = {x: 200, y: 200}; function setup() { createCanvas(400, 400); pos = createVector(width / 2 + 20, height / 2 - 10); vel = createVector(0, 0.5); acc = createVector(0.1, 0.1); } function draw() { background(220); fill(255); // vel.add(acc); pos.add(vel); ellipse(pos.x, pos.y, smallCircleRadius * 2); noFill(); circle(bigCircleCenter.x, bigCircleCenter.y, bigCircleRadius * 2); const distToCenter = dist(pos.x, pos.y, bigCircleCenter.x, bigCircleCenter.y); if (distToCenter >= bigCircleRadius - smallCircleRadius) { // 计算法线向量并归一化 const normal = p5.Vector.sub(pos, createVector(bigCircleCenter.x, bigCircleCenter.y)).normalize(); // 反射速度 vel.reflect(normal); // 修正小圆位置到边界内,避免卡墙 pos.set(p5.Vector.add(createVector(bigCircleCenter.x, bigCircleCenter.y), normal.mult(bigCircleRadius - smallCircleRadius))); // 原有碰撞点标记逻辑保留 const theta = atan2(pos.y - bigCircleCenter.y, pos.x - bigCircleCenter.x); const pX = bigCircleRadius * cos(theta) + bigCircleCenter.x; const pY = bigCircleCenter.y + bigCircleRadius * sin(theta); fill(255, 0, 0); circle(pX, pY, 2); } }
HTML 代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
关键修改点说明
- 修正了原代码中法向量构造的参数错误:原代码
p5.Vector.sub(POI, (width / 2, height / 2))第二个参数不是向量类型,返回结果不符合预期 - 用内置的
reflect()方法替代手动加反向力的逻辑,符合物理碰撞的运动规律 - 新增位置修正逻辑,避免小圆因速度过快卡在碰撞边界反复触发碰撞判定
内容的提问来源于stack exchange,提问作者TheTallestOfMidgets
相关产品推荐
相关产品推荐

