前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >原 matplotlib动画入门(3):弹球

原 matplotlib动画入门(3):弹球

作者头像
Stanley Sun
发布2019-09-23 15:18:25
7830
发布2019-09-23 15:18:25
举报

介绍

在平面上画一个方框代表墙壁,框内有一个运动的弹球,当弹球碰到墙壁时就弹回去,小球不停的运动。

代码

新建一个文件particle.py,增加如下代码:

先引入相应的包

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

新建一个ParticleBox类

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表示帧号。

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()

完整代码为:

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()

执行命令

python3 particle.py 
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档