如何正确编写代码实现三体系统的运动模拟动画效果
错误原因排查
- 你的
animate函数没有用到入参j(帧序号),每次调用都绘制固定的a1[0]和a1[1],本质是把第一个点的x、y当成两个独立列表直接画直线,自然和预期运动轨迹不符 - 重复调用
axes.plot()会不断在画布上叠加新的线,不会更新原有元素的位置,最终会堆满冗余绘图元素,也不会产生动态效果 - 你的位置列表结构是
a1 = [[x0,y0],[x1,y1],...],取某一帧的坐标应该是a1[j][0](x轴)、a1[j][1](y轴),而不是直接取a1[0]、a1[1]
正确实现方案
标准做法是先初始化3个空的绘图对象,每一帧直接更新对象的数据即可,不需要重复调用plot:
import matplotlib.pyplot as plt from matplotlib import animation # 此处替换为你自己生成的a1、a2、a3位置数据 # a1 = [[x0,y0],[x1,y1],...] # a2 = [[x0,y0],[x1,y1],...] # a3 = [[x0,y0],[x1,y1],...] fig, axes = plt.subplots(nrows = 1, ncols = 1, figsize = (10,10)) axes.set_ylim(-1.5, 1.5) axes.set_xlim(-1.5, 1.5) plt.style.use("ggplot") # 初始化三个线对象,分别对应三个物体的运动轨迹;如果只要显示当前位置不需要轨迹,可换成scatter散点对象 line1, = axes.plot([], [], color="red", linewidth=1, label="物体1") line2, = axes.plot([], [], color="gray", linewidth=0.5, label="物体2") line3, = axes.plot([], [], color="blue", linewidth=1, label="物体3") axes.legend() def init(): # 初始帧清空所有绘图对象的数据 line1.set_data([], []) line2.set_data([], []) line3.set_data([], []) return line1, line2, line3 def animate(j): # 保留历史轨迹的写法:取从第0帧到第j帧的所有坐标 x1 = [pos[0] for pos in a1[:j+1]] y1 = [pos[1] for pos in a1[:j+1]] x2 = [pos[0] for pos in a2[:j+1]] y2 = [pos[1] for pos in a2[:j+1]] x3 = [pos[0] for pos in a3[:j+1]] y3 = [pos[1] for pos in a3[:j+1]] # 仅显示当前帧物体位置的写法(不需要轨迹时启用) # x1, y1 = a1[j][0], a1[j][1] # x2, y2 = a2[j][0], a2[j][1] # x3, y3 = a3[j][0], a3[j][1] line1.set_data(x1, y1) line2.set_data(x2, y2) line3.set_data(x3, y3) return line1, line2, line3 # frames设为位置数据的总长度,blit=True开启局部刷新提升性能 ani = animation.FuncAnimation(fig, animate, init_func=init, frames=len(a1), interval=10, blit=True) plt.show() # 如需保存动画可启用以下代码 # ani.save('three_body_motion.gif', writer='pillow')
内容的提问来源于stack exchange,提问作者Matthew Semyonov
相关产品推荐
相关产品推荐

