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

如何在Manim中模拟二维碰撞?相对论动量场景实现问题求解

问题原因

你写的碰撞判断逻辑仅在construct函数初始化阶段执行1次,不会在动画运行的每一帧实时检测碰撞状态;同时新增反弹updater时没有移除原有运动updater,多updater同时生效会造成位置逻辑冲突,最终表现为两个圆直接穿过对方。

修正方案
  • 移除初始化阶段的一次性碰撞判断,将碰撞检测逻辑放入逐帧执行的updater中
  • 增加碰撞状态标记位,避免碰撞后逻辑被反复触发
  • 统一管理两个圆的位置更新逻辑,避免多updater冲突
  • 碰撞触发后交换两个圆的运动轨迹,同时校准ValueTracker数值,避免位置跳变

修正后可直接运行的代码如下:

from manim import *
import numpy as np

def construct(self):
    ax = Axes().add_coordinates()
    # 初始运动轨迹:黄球向右,红球向左
    def move_right(x):
        return x + 1
    def move_left(x):
        return -x + 1

    t_yellow = ValueTracker(-5)
    t_red = ValueTracker(0)
    has_collided = False

    yellow_circle = Circle(color=YELLOW)
    red_circle = Circle(color=RED)

    def frame_update(mob):
        nonlocal has_collided, move_right, move_left
        # 按当前轨迹更新两球位置
        yellow_circle.move_to(ax.c2p(move_right(t_yellow.get_value()), 0.5))
        red_circle.move_to(ax.c2p(move_left(t_red.get_value()), 0.5))

        # 逐帧检测碰撞:圆心距小于等于两球半径之和即判定碰撞
        center_dist = np.linalg.norm(yellow_circle.get_center() - red_circle.get_center())
        if not has_collided and center_dist <= yellow_circle.radius + red_circle.radius:
            has_collided = True
            # 校准时间tracker数值,保证碰撞后运动衔接无跳变
            t_yellow.set_value(0)
            t_red.set_value(2)
            # 交换运动函数,实现沿原路径反向弹开
            move_right, move_left = move_left, move_right

    self.add(ax, yellow_circle, red_circle)
    self.add_updater(frame_update)
    self.play(
        t_yellow.animate.set_value(2),
        t_red.animate.set_value(5),
        run_time=6
    )
    self.remove_updater(frame_update)
扩展提示

如果要实现严谨的相对论动量模拟,不需要改动碰撞检测框架,只需要在碰撞触发分支中,按照相对论动量守恒、能量守恒公式计算两个小球碰撞后的速度,替换当前示例中直接交换运动轨迹的逻辑即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 00:09:39