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

太阳系模拟天体不运动问题排查(附love.update代码)

太阳系模拟程序天体无法运动问题排查

正在开发太阳系模拟程序,所有初始值设置完成且绘图显示正常,但天体完全无法运动,问题集中在love.update(dt)函数中。

错误的love.update(dt)代码

function love.update(dt)
local  G = 6.67430e-11 -- gravitational constant
-- Force Between all the bodies 
for i, body in ipairs(bodies) do
 local fx = 0
  local fy = 0

 for j, body in ipairs(bodies) do
  if i ~= j then // skip calculation for the same body
            local dx = body.px - body.x
            local dy = body.py - body.y
            local dist = math.sqrt(dx^2 + dy^2)
            local f = G * body.mass * body.mass / dist^2
        
        theta = math.atan2(dy, dx)
            fx = math.cos(theta) * f
            fy = math.sin(theta) * f
    return fx, fy
  end
   end
        
  body.ax = fx / body.mass
  body.ay = fy / body.mass

--Update of Velocity and Position
     for _, body in ipairs(bodies) do
    body.x = body.x + body.vx * dt + 0.5 * body.ax * dt^2
    body.y = body.y + body.vy * dt + 0.5 * body.ay * dt^2
    body.vx = body.vx + 0.5 * (body.ax + body.a0x) * dt
    body.vy = body.vy + 0.5 * (body.ay + body.a0y) * dt
    body.a0x = body.ax
    body.a0y = body.ay
end
end

天体初始值示例

bodies[1] = {name = "sun", mass = 1.9891e30, radius = 696340000, x = width/2, y = height/2, vx = 0, vy = 0 , a0x= 0, a0y= 0, ax= 0, ay= 0, px = 0, py = 0}
bodies[2]= {name = "mercury", mass = 0.3302e24, radius = 2440000, x = width/2 + 0.38*100, y =  height/2, vx = 0, vy = 48.92 * 1000, a0x= 0, a0y= 0, ax= 0, ay= 0, px = 46.0e9, py = 0} 

尝试过的dx写法

  • local dx = body.px - body.x
  • local dx = body2.px - body1.px
  • local dx = body.px - body.px

核心问题分析

  1. 循环变量命名冲突:内外层循环都使用body作为变量名,内层循环会覆盖外层的天体引用,无法正确获取两个不同天体的数据。
  2. 语法错误:Lua单行注释是--,代码中使用的//会直接导致函数执行失败,这是天体不动的直接原因之一。
  3. 错误的return语句:内层循环中直接return fx, fy会导致函数提前终止,根本无法完成所有天体间的引力计算。
  4. 引力计算逻辑错误:
    • 引力公式应为G * mass_i * mass_j / dist²,代码中错误使用了同一个天体的质量平方。
    • dx/dy的计算逻辑错误,应该是两个天体真实位置的差值(body_j.px - body_i.px),而非同一个天体真实位置与屏幕位置的差。
  5. 位置更新逻辑嵌套错误:位置更新的循环被放在外层天体循环内部,导致每个天体计算完加速度后,所有天体都被重复更新多次,逻辑混乱。
  6. 真实位置未同步:仅更新了屏幕显示的x/y,未同步真实位置px/py,导致后续引力计算始终使用初始位置。

修复后的代码

function love.update(dt)
    local G = 6.67430e-11 -- gravitational constant

    -- 第一步:计算所有天体的加速度
    for i, body_i in ipairs(bodies) do
        local fx = 0
        local fy = 0

        for j, body_j in ipairs(bodies) do
            if i ~= j then
                local dx = body_j.px - body_i.px
                local dy = body_j.py - body_i.py
                local dist_sq = dx^2 + dy^2
                local dist = math.sqrt(dist_sq)

                -- 避免除以0(天体碰撞时的保护)
                if dist < 1e9 then
                    dist = 1e9
                end

                -- 计算引力大小
                local f = G * body_i.mass * body_j.mass / dist_sq
                -- 计算引力分量(用dx/dist、dy/dist代替三角函数,更高效)
                fx = fx + (dx / dist) * f
                fy = fy + (dy / dist) * f
            end
        end

        -- 更新当前天体的加速度
        body_i.ax = fx / body_i.mass
        body_i.ay = fy / body_i.mass
    end

    -- 第二步:更新所有天体的速度和位置
    for _, body in ipairs(bodies) do
        -- 同步更新屏幕位置和真实位置
        body.x = body.x + body.vx * dt + 0.5 * body.ax * dt^2
        body.y = body.y + body.vy * dt + 0.5 * body.ay * dt^2
        body.px = body.px + body.vx * dt + 0.5 * body.ax * dt^2
        body.py = body.py + body.vy * dt + 0.5 * body.ay * dt^2

        -- 更新速度(使用平均加速度)
        body.vx = body.vx + 0.5 * (body.ax + body.a0x) * dt
        body.vy = body.vy + 0.5 * (body.ay + body.a0y) * dt

        -- 保存当前加速度作为下一次的初始加速度
        body.a0x = body.ax
        body.a0y = body.ay
    end
end

额外说明

  • 用dx/dist * f和dy/dist * f替代三角函数计算引力分量,减少性能开销且结果一致。
  • 添加距离最小值保护,防止天体距离过近导致数值溢出。
  • 分离加速度计算与位置更新步骤,逻辑更清晰,避免重复更新。
  • 同步屏幕位置与真实位置,确保引力计算使用最新数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 02:25:44