百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

代码也浪漫:用Python来场烟花吧 python做烟花代码

liebian365 2024-10-26 13:00 26 浏览 0 评论

俗语有言,代码如诗;我也有言,代码如画!今天就和大家一起探讨下如何用python点烟花,让我们在工作之余可以随时用程序为自己放一场烟花秀。

基础知识:用Python和Tkinter设计烟花

这里不再一股脑把数学知识全丢出来,我们边写代码边说理论。首先,确保你安装和导入了 Tkinter ,它是Python的标准 GUI 库,广泛应用于各种各样的项目和程序开发,在Python中使用 Tkinter 可以快速的创建 GUI 应用程序。

import tkinter as tk

from PIL import Image, ImageTk

from time import time, sleep

from random import choice, uniform, randint

from math import sin, cos, radians

除了Tkinter之外,为了能让界面有漂亮的背景,我们也导入PIL用于图像处理,以及导入其它一些包,比如time,random和math。它们能让我们更容易的控制烟花粒子的运动轨迹。

Tkinter应用的基本设置如下:

root = tk.Tk()

为了能初始化Tkinter,我们必须创建一个Tk()根部件(root widget),它是一个窗口,带有标题栏和由窗口管理器提供的其它装饰物。该根部件必须在我们创建其它小部件之前就创建完毕,而且只能有一个根部件。

w = tk.Label(root, text="Hello Tkinter!")

这一行代码包含了Label部件。该Label调用中的第一个参数就是父窗口的名字,即我们这里用的“根”。关键字参数“text”指明显示的文字内容。你也可以调用其它小部件:Button,Canvas等等。

w.pack()


root.mainloop()

接下来的这两行代码很重要。这里的打包方法是告诉Tkinter调整窗口大小以适应所用的小部件。窗口直到我们进入Tkinter事件循环,被root.mainloop()调用时才会出现。在我们关闭窗口前,脚本会一直在停留在事件循环。

将烟花绽放转译成代码

现在我们设计一个对象,表示烟花事件中的每个粒子。每个粒子都会有一些重要的属性,支配了它的外观和移动状况:大小,颜色,位置,速度等等。

'''


particles 类



粒子在空中随机生成随机,变成一个圈、下坠、消失



属性:


- id: 粒子的id


- x, y: 粒子的坐标


- vx, vy: 在坐标的变化速度


- total: 总数


- age: 粒子存在的时长


- color: 颜色


- cv: 画布


- lifespan: 最高存在时长



'''

class part:def __init__(self, cv, idx, total, explosion_speed, x=0., y=0., vx = 0., vy = 0., size=2., color = 'red', lifespan = 2, **kwargs):


self.id = idx


self.x = x


self.y = y


self.initial_speed = explosion_speed


self.vx = vx


self.vy = vy


self.total = total


self.age = 0self.color = color


self.cv = cv


self.cid = self.cv.create_oval(


x - size, y - size, x + size,


y + size, fill=self.color)


self.lifespan = lifespan

如果我们回过头想想最开始的想法,就会意识到必须确保每个烟花绽放的所有粒子必须经过3个不同的阶段,即“膨胀”“坠落”和“消失”。 所以我们向粒子类中再添加一些运动函数,如下所示:

def update(self, dt):

# 粒子膨胀if self.alive() and self.expand():


move_x = cos(radians(self.id*360/self.total))*self.initial_speed


move_y = sin(radians(self.id*360/self.total))*self.initial_speed


self.vx = move_x/(float(dt)*1000)


self.vy = move_y/(float(dt)*1000)


self.cv.move(self.cid, move_x, move_y)


# 以自由落体坠落

elif self.alive():


move_x = cos(radians(self.id*360/self.total))

# we technically don't need to update x, y because move will do the jobself.cv.move(self.cid, self.vx + move_x, self.vy+GRAVITY*dt)self.vy += GRAVITY*dt


# 如果粒子的生命周期已过,就将其移除

elif self.cid is not None:


cv.delete(self.cid)


self.cid = None

当然,这也意味着我们必须定义每个粒子绽放多久、坠落多久。这部分需要我们多尝试一些参数,才能达到最佳视觉效果。

# 定义膨胀效果的时间帧

def expand (self):

return self.age <= 1.2

使用Tkinter模拟

现在我们将粒子的移动概念化,不过很明显,一个烟花不能只有一个粒子,一场烟花秀也不能只有一个烟花。我们下一步就是让Python和Tkinter以我们可控的方式向天上连续“发射”粒子。

到了这里,我们需要从操作一个粒子升级为在屏幕上展现多个烟花及每个烟花中的多个粒子。

我们的解决思路如下:创建一列列表,每个子列表是一个烟花,其包含一列粒子。每个列表中的例子有相同的x,y坐标、大小、颜色、初始速度。

numb_explode = randint(6,10)

# 为所有模拟烟花绽放的全部粒子创建一列列表

for point in range(numb_explode):

objects = []

x_cordi = randint(50,550)

y_cordi = randint(50, 150)

size = uniform (0.5,3)

color = choice(colors)

explosion_speed = uniform(0.2, 1)

total_particles = randint(10,50)

for i in range(1,total_particles):

r = part(cv, idx = i, total = total_particles, explosion_speed = explosion_speed, x = x_cordi, y = y_cordi,

color=color, size = size, lifespan = uniform(0.6,1.75))

objects.append(r)

explode_points.append(objects)

我们下一步就是确保定期更新粒子的属性。这里我们设置让粒子每0.01秒更新它们的状态,在1.8秒之后停止更新(这意味着每个粒子的存在时间为1.6秒,其中1.2秒为“绽放”状态,0.4秒为“坠落”状态,0.2秒处于Tkinter将其完全移除前的边缘状态)。

total_time = .0

# 在1.8秒时间帧内保持更新

while total_time < 1.8:

sleep(0.01)

tnew = time()

t, dt = tnew, tnew - t

for point in explode_points:

for part in point:

part.update(dt)

cv.update()

total_time += dt

现在,我们只需将最后两个gist合并为一个能被Tkinter调用的函数,就叫它simulate()吧。该函数会展示所有的数据项,并根据我们设置的时间更新每个数据项的属性。在我们的主代码中,我们会用一个alarm处理模块after()调用此函数,after()会等待一定的时间,然后再调用函数。

我们这里设置让Tkinter等待100个单位(1秒钟)再调取simulate。

# 检查粒子是否仍在生命周期内

def alive(self):

return self.age <= self.lifespan

if __name__ == '__main__':

root = tk.Tk()

cv = tk.Canvas(root, height=600, width=600)

# 绘制一个黑色背景

cv.create_rectangle(0, 0, 600, 600, fill="black")

cv.pack()

root.protocol("WM_DELETE_WINDOW", close)

# 在1秒后才开始调用stimulate()

root.after(100, simulate, cv)

root.mainloop()

好了,这样我们就用Python代码放了一场烟花秀

本文只一个简单版本,等进一步熟悉Tkinter后,还可以添加更多颜色更漂亮的背景照片,让代码为你绽放更美的烟花!

以下是全部代码:










相关推荐

go语言也可以做gui,go-fltk让你做出c++级别的桌面应用

大家都知道go语言生态并没有什么好的gui开发框架,“能用”的一个手就能数的清,好用的就更是少之又少。今天为大家推荐一个go的gui库go-fltk。它是通过cgo调用了c++的fltk库,性能非常高...

旧电脑的首选系统:TinyCore!体积小+精简+速度极快,你敢安装吗

这几天老毛桃整理了几个微型Linux发行版,准备分享给大家。要知道可供我们日常使用的Linux发行版有很多,但其中的一些发行版经常会被大家忽视。其实这些微型Linux发行版是一种非常强大的创新:在一台...

codeblocks和VS2019下的fltk使用中文

在fltk中用中文有点问题。英文是这样。中文就成这个样子了。我查了查资料,说用UTF-8编码就行了。edit->Fileencoding->UTF-8然后保存文件。看下下边的编码指示确...

FLTK(Fast Light Toolkit)一个轻量级的跨平台Python GUI库

FLTK(FastLightToolkit)是一个轻量级的跨平台GUI库,特别适用于开发需要快速、高效且简单界面的应用程序。本文将介绍Python中的FLTK库,包括其特性、应用场景以及如何通过代...

中科院开源 RISC-V 处理器“香山”流片,已成功运行 Linux

IT之家1月29日消息,去年6月份,中科院大学教授、中科院计算所研究员包云岗,发布了开源高性能RISC-V处理器核心——香山。近日,包云岗在社交平台晒出图片,香山芯片已流片,回片后...

Linux 5.13内核有望合并对苹果M1处理器支持的初步代码

预计Linux5.13将初步支持苹果SiliconM1处理器,不过完整的支持工作可能还需要几年时间才能完全完成。虽然Linux已经可以在苹果SiliconM1上运行,但这需要通过一系列的补丁才能...

Ubuntu系统下COM口测试教程(ubuntu port)

1、在待测试的板上下载minicom,下载minicom有两种方法:方法一:在Ubuntu软件中心里面搜索下载方法二:按“Ctrl+Alt+T”打开终端,打开终端后输入“sudosu”回车;在下...

湖北嵌入式软件工程师培训怎么选,让自己脱颖而出

很多年轻人毕业即失业、面试总是不如意、薪酬不满意、在家躺平。“就业难”该如何应对,参加培训是否能改变自己的职业走向,在湖北,有哪些嵌入式软件工程师培训怎么选值得推荐?粤嵌科技在嵌入式培训领域有十几年经...

新阁上位机开发---10年工程师的Modbus总结

前言我算了一下,今年是我跟Modbus相识的第10年,从最开始的简单应用到协议了解,从协议开发到协议讲解,这个陪伴了10年的协议,它一直没变,变的只是我对它的理解和认识。我一直认为Modbus协议的存...

创建你的第一个可运行的嵌入式Linux系统-5

@ZHangZMo在MicrochipBuildroot中配置QT5选择Graphic配置文件增加QT5的配置修改根文件系统支持QT5修改output/target/etc/profile配置文件...

如何在Linux下给zigbee CC2530实现上位机

0、前言网友提问如下:粉丝提问项目框架汇总下这个网友的问题,其实就是实现一个网关程序,内容分为几块:下位机,通过串口与上位机相连;下位机要能够接收上位机下发的命令,并解析这些命令;下位机能够根据这些命...

Python实现串口助手 - 03串口功能实现

 串口调试助手是最核心的当然是串口数据收发与显示的功能,pzh-py-com借助的是pySerial库实现串口收发功能,今天痞子衡为大家介绍pySerial是如何在pzh-py-com发挥功能的。一、...

为什么选择UART(串口)作为调试接口,而不是I2C、SPI等其他接口

UART(通用异步收发传输器)通常被选作调试接口有以下几个原因:简单性:协议简单:UART的协议非常简单,只需设置波特率、数据位、停止位和校验位就可以进行通信。相比之下,I2C和SPI需要处理更多的通...

同一个类,不同代码,Qt 串口类QSerialPort 与各种外设通讯处理

串口通讯在各种外设通讯中是常见接口,因为各种嵌入式CPU中串口标配,工业控制中如果不够还通过各种串口芯片进行扩展。比如spi接口的W25Q128FV.对于软件而言,因为驱动接口固定,软件也相对好写,因...

嵌入式linux为什么可以通过PC上的串口去执行命令?

1、uboot(负责初始化基本硬bai件,如串口,网卡,usb口等,然du后引导系统zhi运行)2、linux系统(真正的操作系统)3、你的应用程序(基于操作系统的软件应用)当你开发板上电时,u...

取消回复欢迎 发表评论: