介绍
在平面上画一个方框代表墙壁,框内有一个运动的弹球,当弹球碰到墙壁时就弹回去,小球不停的运动。
代码
新建一个文件particle.py,增加如下代码:
先引入相应的包
代码语言:javascript复制import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
新建一个ParticleBox类
代码语言:javascript复制class ParticleBox:
'''
初始化方法
init_state是一个数组:[x,y,vx,vy],四个值分别表示x坐标,y坐标,x方向的速度,y方向的速度
bounds 是箱子的边界: [xmin, xmax, ymin, ymax]
size: 球的半径
'''
def __init__(self,
init_state = [1,0,0.5,1],
bounds = [-2, 2, -2, 2],
size = 0.04):
self.init_state = np.asarray(init_state, dtype=float)
self.size = size
self.state = self.init_state.copy()
self.bounds = bounds
'''
每一帧动画调用一次step函数,画出小球的位置。
dt是每一帧代表的时间,其乘以速度就是运动的距离
'''
def step(self, dt):
'''
x = x dt * vx
y = y dt * vy
'''
self.state[:2] = dt * self.state[2:]
'''
如果弹球碰到墙,就弹回来
'''
crossed_x1 = (self.state[0] < self.bounds[0] self.size)
crossed_x2 = (self.state[0] > self.bounds[1] - self.size)
crossed_y1 = (self.state[1] < self.bounds[2] self.size)
crossed_y2 = (self.state[1] > self.bounds[3] - self.size)
if crossed_x1:
self.state[0] = self.bounds[0] self.size
if crossed_x2:
self.state[0] = self.bounds[1] - self.size
if crossed_y1:
self.state[1] = self.bounds[2] self.size
if crossed_y2:
self.state[1] > self.bounds[3] - self.size
#反方向运动
if crossed_x1 | crossed_x2 :
self.state[2] *= -1
if crossed_y1 | crossed_y2 :
self.state[3] *= -1
每一帧动画调用一次animate函数,i表示帧号。
代码语言:javascript复制def animate(i):
global box, rect
box.step(dt)
rect.set_edgecolor('k')
particles.set_data(box.state[0], box.state[1])
particles.set_markersize(4)
return particles, rect
生成边框、小球以及让它动起来
代码语言:javascript复制#随机取四个数作为起始位置和速度
init_state = np.random.random(4)
box = ParticleBox(init_state, size=0.04)
#每帧代表0.1秒
dt = 0.1
#画图
fig = plt.figure()
fig.subplots_adjust(left=0, right=1, bottom=0, top=1)
ax = fig.add_subplot(111, aspect='equal', autoscale_on=False,
xlim=(-3.2, 3.2), ylim=(-2.4, 2.4))
particles, = ax.plot([], [], 'bo', ms=4)
rect = plt.Rectangle(box.bounds[::2],
box.bounds[1] - box.bounds[0],
box.bounds[3] - box.bounds[2],
ec='none', lw=2, fc='none')
ax.add_patch(rect)
ani = animation.FuncAnimation(fig, animate, frames=600,
interval=1, blit=False)
plt.show()
完整代码为:
代码语言:javascript复制import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
class ParticleBox:
'''
init_state is an array:[x,y,vx,vy]
bounds 箱子的边界: [xmin, xmax, ymin, ymax]
size: 球的半径
'''
def __init__(self,
init_state = [1,0,0.5,1],
bounds = [-2, 2, -2, 2],
size = 0.04):
self.init_state = np.asarray(init_state, dtype=float)
self.size = size
self.state = self.init_state.copy()
self.bounds = bounds
'''
每一帧动画调用一次step函数,画出小球的位置。
dt是每一帧代表的时间,其乘以速度就是运动的距离
'''
def step(self, dt):
'''
x = x dt * vx
y = y dt * vy
'''
self.state[:2] = dt * self.state[2:]
'''
如果碰到墙,就弹回来
'''
crossed_x1 = (self.state[0] < self.bounds[0] self.size)
crossed_x2 = (self.state[0] > self.bounds[1] - self.size)
crossed_y1 = (self.state[1] < self.bounds[2] self.size)
crossed_y2 = (self.state[1] > self.bounds[3] - self.size)
if crossed_x1:
self.state[0] = self.bounds[0] self.size
if crossed_x2:
self.state[0] = self.bounds[1] - self.size
if crossed_y1:
self.state[1] = self.bounds[2] self.size
if crossed_y2:
self.state[1] > self.bounds[3] - self.size
if crossed_x1 | crossed_x2 :
self.state[2] *= -1
if crossed_y1 | crossed_y2 :
self.state[3] *= -1
def animate(i):
global box, rect
box.step(dt)
rect.set_edgecolor('k')
particles.set_data(box.state[0], box.state[1])
particles.set_markersize(4)
return particles, rect
#随机取四个数作为起始位置和速度
init_state = np.random.random(4)
box = ParticleBox(init_state, size=0.04)
#每帧代表0.1秒
dt = 0.1
#画图
fig = plt.figure()
fig.subplots_adjust(left=0, right=1, bottom=0, top=1)
ax = fig.add_subplot(111, aspect='equal', autoscale_on=False,
xlim=(-3.2, 3.2), ylim=(-2.4, 2.4))
particles, = ax.plot([], [], 'bo', ms=4)
rect = plt.Rectangle(box.bounds[::2],
box.bounds[1] - box.bounds[0],
box.bounds[3] - box.bounds[2],
ec='none', lw=2, fc='none')
ax.add_patch(rect)
ani = animation.FuncAnimation(fig, animate, frames=600,
interval=1, blit=False)
plt.show()
执行命令
代码语言:javascript复制python3 particle.py