专栏首页思考是一种快乐原 matplotlib动画入门(3):弹球

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

介绍

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

代码

新建一个文件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 

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何用遗传算法进化出一只聪明的小鹦鹉

    现在有一些样本数据,如下表所示。你是否能找到其中的规律,然后计算出新样本的output是多少?

    Stanley Sun
  • Python代码搭建简单的神经网络

    https://medium.com/technology-invention-and-more/how-to-build-a-simple-neural-ne...

    Stanley Sun
  • 人工智能算法通俗讲解系列(四):xgboost

    不要被这个名字吓唬到,其实它的基本原理并不复杂。要理解xgboost,需要首先理解决策树。还没有接触过决策树的同学可以看一下《人工智能算法通俗讲解系列(三):决...

    Stanley Sun
  • iOS开发 UIlabel 文字两边对齐

    czjwarrior
  • Django打造大型企业官网(六)

    zhang_derek
  • 打牢地基-链表

    注意: 关键点: 找到要插入节点的前一个节点 LinkedList - (head实现)

    用户1081422
  • Python高级进阶#015 pyqt5进度条QProgressBar结合使用qbasictimer

    这里我们在学习使用进度条的时候,必须要结合使用时钟控件,这样才能让我们看到进度条动的感觉。

    刘金玉编程
  • Python系列之循环定时器

    近期在学习并使用Python开发一些小工具,在这里记录方便回忆,也与各位开始走上这条路的朋友共勉,如有不正确希望指正,谢谢!

    py3study
  • 六天完成一个简单iOS App - 第四天

    xx_Cc
  • 【AlphaGo Zero 核心技术-深度强化学习教程代码实战04】Agent类和SARSA算法实现

    【导读】Google DeepMind在Nature上发表最新论文,介绍了迄今最强最新的版本AlphaGo Zero,不使用人类先验知识,使用纯强化学习,将价值...

    WZEARW

扫码关注云+社区

领取腾讯云代金券