弹跳小球

450 阅读2分钟

效果说明

本案例实现了一个具有重力和弹性效果的小球动画。小球会在画布中弹跳,并受到重力影响,模拟真实的物理运动。

Snipaste_2024-12-18_22-30-15.png

核心实现

1. 物理模拟

小球的运动遵循简单的物理规律:

  • 垂直方向受重力影响,速度会不断增加
  • 水平方向保持匀速运动
  • 位置根据速度更新
// 重力使垂直速度增加
ball.speedY += ball.gravity;

// 更新小球位置
ball.x += ball.speedX;  // 水平位置 = 当前位置 + 水平速度
ball.y += ball.speedY;  // 垂直位置 = 当前位置 + 垂直速度

2. 碰撞处理

当小球碰到边界时需要反弹:

  • 碰到左右边界时,水平速度反向
  • 碰到底部时,垂直速度反向
  • 每次碰撞都会损失部分能量(由bounce系数控制)
// 水平碰撞(左右边界)
if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {
    // 速度反向,并损失部分能量
    ball.speedX *= -ball.bounce;  // bounce=0.8表示保留80%的速度
}

// 垂直碰撞(底部)
if (ball.y + ball.radius > canvas.height) {
    // 1. 修正位置,防止小球陷入底部
    ball.y = canvas.height - ball.radius;
    // 2. 速度反向,并损失部分能量
    ball.speedY *= -ball.bounce;
}

3. 拖尾效果

通过在每一帧绘制半透明背景来实现拖尾:

  • 透明度越低,拖尾越长
  • 透明度越高,拖尾越短
  • 当前使用0.2的透明度,产生适中的拖尾长度
// 绘制半透明背景
ctx.fillStyle = 'rgba(26, 26, 26, 0.2)';  // 透明度0.2
ctx.fillRect(0, 0, canvas.width, canvas.height);

// 之前帧的小球会被半透明层遮住一部分
// 连续多帧后形成渐变消失的拖尾效果

关键参数说明

  • gravity: 重力加速度,控制下落速度
  • bounce: 弹性系数(0-1),控制反弹力度
    • 1: 完全弹性碰撞,不损失能量
    • 0: 完全非弹性碰撞,碰撞后停止
    • 0.8: 保留80%的速度
  • speedX/speedY: 水平/垂直速度
  • radius: 小球半径

扩展思路

  1. 添加多个小球
  2. 实现小球之间的碰撞
  3. 添加拖拽交互
  4. 自定义重力和弹性
  5. 添加空气阻力模拟

Demo