You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何基于重力与运动角度改变轨道点的移动速度

嘿,我完全懂你现在的感受——没碰过物理的话,这些运动相关的公式真的像看天书一样!不过别慌,我用最直白的方式给你拆解清楚,一步步帮你实现「让轨道运动的点根据运动方向,按比例随重力改变速度」的需求。

核心逻辑拆解

首先要明确:重力是一个固定方向的力(比如在Canvas里我们默认向下,对应y轴正方向),而轨道点的运动方向是轨道的切线方向。我们只需要把重力“拆分”到运动方向上,这个方向的重力分量就是改变速度的关键。

1. 大白话版物理概念

  • 运动方向:轨道上某一点的瞬间运动方向,就是该点的切线方向(想象甩绳子上的小球,小球此刻的运动方向是和绳子垂直的)。
  • 重力的作用:只有和运动方向平行的重力分量,才会改变速度的大小;垂直的分量只会让轨道变弯,咱们现在重点关注速度变化,所以只处理平行分量。

2. 关键公式(不用死记,照着用就行)

先定义几个你需要用到的变量:

  • g:重力加速度(不用用现实中的9.8,Canvas里是像素单位,建议设成0.2-0.5之间,效果更自然)
  • vx, vy:轨道点当前的x、y方向速度
  • speed:当前速度的大小(用Math.hypot(vx, vy)计算,比开平方更安全)
  • dirX, dirY:运动方向的单位向量(把速度向量缩小到长度为1,用来表示方向)
  • deltaTime:两帧之间的时间差(单位秒,用来让运动速度和帧率无关)

计算步骤:

  1. 先算出运动方向的单位向量:
    const speed = Math.hypot(orbiter.vx, orbiter.vy);
    if (speed > 0) { // 避免点静止时除以0
      const dirX = orbiter.vx / speed;
      const dirY = orbiter.vy / speed;
    }
    
  2. 计算重力在运动方向上的加速度分量:
    // 重力向下,所以重力向量是(0, g),和运动方向单位向量做点乘得到切向加速度
    const tangentialAccel = g * dirY;
    
  3. 用这个加速度更新速度:
    orbiter.vx += tangentialAccel * dirX * deltaTime;
    orbiter.vy += tangentialAccel * dirY * deltaTime;
    

3. 结合你的Canvas代码完整实现

我把你没写完的代码补全,并且加入了上面的速度逻辑,直接就能运行:

var c = document.createElement("canvas");
c.width = window.innerWidth;
c.height = window.innerHeight;
c.style = "position:absolute; top: 0; left: 0; background-color: black;";
document.body.appendChild(c);
var ctx = c.getContext("2d");

// 配置参数
const centerPoint = { x: c.width/2, y: c.height/2 }; // 固定的中心轨道点
const orbitingPoint = { 
  x: c.width/2 + 150, 
  y: c.height/2, 
  vx: 0, 
  vy: 6, // 初始速度,让点开始绕转
  radius: 6 
};
const gravity = 0.4; // 重力加速度,可根据效果调整
let lastFrameTime = performance.now();

function animate(currentTime) {
  // 计算时间差,转成秒,保证运动速度和帧率无关
  const deltaTime = (currentTime - lastFrameTime) / 1000;
  lastFrameTime = currentTime;

  // 清空画布
  ctx.fillStyle = "black";
  ctx.fillRect(0, 0, c.width, c.height);

  // 更新轨道点的速度(核心逻辑)
  const speed = Math.hypot(orbitingPoint.vx, orbitingPoint.vy);
  if (speed > 0) {
    const dirX = orbitingPoint.vx / speed;
    const dirY = orbitingPoint.vy / speed;

    // 计算重力带来的切向加速度
    const tangentialAccel = gravity * dirY;

    // 更新速度
    orbitingPoint.vx += tangentialAccel * dirX * deltaTime * 60;
    orbitingPoint.vy += tangentialAccel * dirY * deltaTime * 60;
  }

  // 更新轨道点的位置
  orbitingPoint.x += orbitingPoint.vx * deltaTime * 60;
  orbitingPoint.y += orbitingPoint.vy * deltaTime * 60;

  // 绘制中心和轨道点
  ctx.fillStyle = "#ffffff";
  ctx.beginPath();
  ctx.arc(centerPoint.x, centerPoint.y, 8, 0, Math.PI * 2);
  ctx.fill();

  ctx.fillStyle = "#ff4444";
  ctx.beginPath();
  ctx.arc(orbitingPoint.x, orbitingPoint.y, orbitingPoint.radius, 0, Math.PI * 2);
  ctx.fill();

  requestAnimationFrame(animate);
}

// 启动动画
requestAnimationFrame(animate);

4. 效果调整小技巧

  • 觉得重力影响太强/太弱?直接改gravity的数值就行,比如0.2是弱重力,0.6是强重力。
  • 想改变初始绕转方向?调整vxvy的初始值,比如vx: -6, vy: 0会让点向左开始绕转。
  • 要是想让轨道更接近行星绕转的稳定效果,可以额外加一个向心力的计算,但你当前的需求已经被上面的代码满足啦。

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

火山引擎 最新活动