Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用Tkinter制作焰火_Python_Tkinter - Fatal编程技术网

Python 使用Tkinter制作焰火

Python 使用Tkinter制作焰火,python,tkinter,Python,Tkinter,我正在尝试使用Tkinter(python)创建一个非常漂亮的彩色焰火,尽管它对我不起作用。问题是爆炸(火箭级)部分的烟火粒子没有停止,我不知道为什么。我已经尝试了很多东西,但都没有变好 **注意:我所说的类叫做Rocket,其中粒子移动,爆炸,并且不会停止“爆炸”**-我使用了粒子类和焰火类,所以您不需要阅读所有代码,只需阅读这些部分 我的代码: import tkinter as tk from time import time, sleep from random import choic

我正在尝试使用Tkinter(python)创建一个非常漂亮的彩色焰火,尽管它对我不起作用。问题是爆炸(火箭级)部分的烟火粒子没有停止,我不知道为什么。我已经尝试了很多东西,但都没有变好

**注意:我所说的类叫做Rocket,其中粒子移动,爆炸,并且不会停止“爆炸”**-我使用了粒子类和焰火类,所以您不需要阅读所有代码,只需阅读这些部分

我的代码:

import tkinter as tk
from time import time, sleep
from random import choice, uniform, randint
from math import sin, cos, radians
from sys import modules

GRAVITY = 30  # you can play around with this if you want

class Particle:
    """Generic class for particles.

    Particles can be emitted by Fireworks objects. They are displayed for a
    specified lifespan and then removed from the canvas.

    Attributes:
        cv (Tk.canvas): the canvas in which the particle is drawn.
        cid (Tk.canvas): the tkinter canvas id for the particle.
        x (float): x-coordinate of the particle.
        y (float): y-coordinate of the particle.
        vx (float): x-velocity of the particle (in pixels per second).
        vy (float): y-velocity of the particle (in pixels per second).
        color (str): color of the particle.
        age (float): age of the particle.
        lifespan (float): lifespan of the particle (in seconds).

    """

    def __init__(self, cv=None, color='white', x=0., y=0.,
                 vx=0., vy=0., lifespan=5.):
        """Init Particle objects.

        Args:
            cv (Tk.canvas): the canvas in which the particle is drawn.
            x (float): x-coordinate of the particle.
                Defaults to 0.0.
            y (float): y-coordinate of the particle.
                Defaults to 0.0.
            vx (float): x-velocity of the particle (in pixels per second).
                Defaults to 0.0.
            vy (float): y-velocity of the particle (in pixels per second).
                Defaults to 0.0.
            color (str): color of the particle.
                Defaults to 'white'.
            lifespan (float): lifespan of the particle (in seconds).
                Defaults to 5.0.

        """
        self.cv = cv
        self.cid = None
        self.x, self.y = x, y
        self.vx, self.vy = vx, vy
        self.color = color
        self.age, self.lifespan = 0, lifespan

    def update(self, dt):
        """Update position and velocity after dt seconds have passed.

        Args:
            dt (float): the time that has passed after the last update (in s).

        """
        self.age += dt
        if self.alive():
            self.vy += GRAVITY * dt
            self.x += self.vx * dt
            self.y += self.vy * dt
            self.cv.move(self.cid, self.vx * dt, self.vy * dt)
        elif self.cid is not None:
            cv.delete(self.cid)
            self.cid = None

    def alive(self):
        """Check if particle is still within its lifespan."""
        return self.age <= self.lifespan


class SquareParticle(Particle):
    """A Particle with a quadratic shape"""
    def __init__(self, x=0., y=0., size=2., **kwargs):
        super().__init__(x=x, y=y, **kwargs)
        self.cid = self.cv.create_polygon(
            x - size, y - size, x + size, y - size,
            x + size, y + size, x - size, y + size,
            fill=self.color)


class TriangleParticle(Particle):
    """A Particle with a triangular shape"""
    def __init__(self, x=0., y=0., size=2., **kwargs):
        super().__init__(x=x, y=y, **kwargs)
        self.cid = self.cv.create_polygon(
            x - size, y - size, x + size,
            y - size, x, y + size,
            fill=self.color)


class CircularParticle(Particle):
    """A Particle with a circular shape."""
    def __init__(self, x=0., y=0., size=2., **kwargs):
        super().__init__(x=x, y=y, **kwargs)
        self.cid = self.cv.create_oval(
            x - size, y - size, x + size,
            y + size, fill=self.color)


class Fireworks:
    """Generic class for fireworks.

    The main "behavior" of a fireworks is specified via its update method.
    E.g., new particles can be emitted and added to the particle list. The
    Fireworks base class automatically updates all particles from the particle
    list in its update method.

    Attributes:
        cv (Tk.canvas): the canvas in which the fireworks is drawn.
        age (float): age of the fireworks.
        particles (list of Particle): list of generated particles.

    """

    def __init__(self, cv=None):
        """Init Fireworks objects.

        Args:
            cv (Tk.canvas): the canvas in which the particle is drawn.

        """
        self.cv = cv
        self.age = 0
        self.particles = []

    def update(self, dt):
        """Update the fireworks' particles and remove dead ones.

        Args:
            dt (float): the time that has passed after the last update (in s).

        """
        self.age += dt
        for p in self.particles:
                 p.update(dt)
        for i in range(len(self.particles) - 1, -1, -1):
            if not self.particles[i].alive():
                del self.particles[i]


class Volcano(Fireworks):
    """A volcano that continuously emits colored particles.

    Attributes:
        x (float): x-coordinate of the volcano.
        pps (float): the number of particles to spawn per second.
        colors (list of string): the colors of the particles to spawn."""

    def __init__(self, cv, x, pps, colors):
        """Init Volcano objects.

        Args:
            cv (Tk.canvas): the canvas in which the particle is drawn.
            x (float): x-coordinate of the volcano.
            pps (float): the number of particles to spawn per second.
            colors (list of string): the colors of the particles to spawn.

        """
        super().__init__(cv)
        self.cid = cv.create_polygon(x - 12, 530,  # size and color are fixed
                                     x + 12, 530,  # (can be parametrized)
                                     x, 500,
                                     fill="orange")
        self.x = x
        self.pps = pps
        self.colors = colors
        self._tospawn = 0

    def update(self, dt):
        """Continuously emits new random particles and updates them.

        Args:
            dt (float): the time that has passed after the last update (in s).

        """
        super().update(dt)
        self._tospawn += self.pps * dt
        color = self.colors[int(self.age / 3) % len(self.colors)]
        for i in range(int(self._tospawn)):
            ptype = choice(
                [SquareParticle, TriangleParticle, CircularParticle])
            angle = uniform(-0.25, 0.25)
            speed = -uniform(80.0, 120.0)
            vx = sin(angle) * speed
            vy = cos(angle) * speed
            self.particles.append(
                ptype(cv=self.cv, x=self.x, y=500, color=color, vx=vx, vy=vy))
        self._tospawn -= int(self._tospawn)


class Rocket(Particle, Fireworks):

    def __init__(self, cv, x=0., y=0., size=2., **kwargs):
        super().__init__(cv, x=x, y=y, **kwargs)
        self.cid = self.cv.create_oval(
            x - size, y - size, x + size,
            y + size, fill=self.color)
        self.x = x
        self.pps = 100
        self.colors = ['red']
        self._tospawn = 0
        self.particles = []

    def update(self, dt):
        self.age += dt
        if self.alive():
            self.vy += -GRAVITY * dt
            self.x += self.vx * dt
            self.y += self.vy * dt
            self.cv.move(self.cid, self.vx * dt, self.vy * dt)
        elif self.cid is not None:
            cv.delete(self.cid)
            self.cid = None
        if self.cid is None:
             Fireworks.update(self, dt)
             color = self.colors[int(self.age / 3) % len(self.colors)]
             self._tospawn += self.pps * dt
             for i in range(int(self._tospawn)):
              ptype = choice(
                [CircularParticle])
              angle = uniform(-100, 100)
              speed = -uniform(80, 120.0)
              vx = sin(angle) * speed
              vy = cos(angle) * speed
              self.particles.append(
                 ptype(cv=self.cv, x=self.x, y=self.y, color=color, vx=vx, vy=vy))
              self._tospawn -= self.pps * dt


def simulate(cv, objects):
    """Fireworks simulation loop.

        Args:
            cv (float): the canvas in which the firework objects are drawn.
            objects (float): the firework objects.

    """
    t = time()
    while running:
        sleep(0.01)
        tnew = time()
        t, dt = tnew, tnew - t
        for o in objects:
            o.update(dt)
        cv.update()


def close(*ignore):
    """Stops simulation loop and closes the window."""
    global running
    running = False
    root.destroy()


if __name__ == '__main__':
    x = 10
    root = tk.Tk()
    cv = tk.Canvas(root, height=600, width=800)
    cv.create_rectangle(0, 0, 800, 600, fill="black")  # sky
    cv.create_rectangle(0, 450, 800, 600, fill="gray11")  # ground
    cv.pack()

    v1 = Volcano(cv, 400, 100, ["red", "green", "gold"])
    ro = Rocket(cv, 600, 500)
    objects = [v1, ro]

    # close with [ESC] or (x) button
    root.bind('<Escape>', close)
    root.protocol("WM_DELETE_WINDOW", close)

    running = True
    root.after(500, simulate, cv, objects)
    if "idlelib" not in modules:
        root.mainloop()
将tkinter作为tk导入
从时间导入时间,睡眠
来自随机导入选择、统一、随机输入
从数学输入sin,cos,radians
从系统导入模块
重力=30#如果你愿意,你可以玩这个
类粒子:
“”“粒子的泛型类。”。
粒子可以由焰火对象发射。它们将显示一段时间
指定的使用寿命,然后从画布中删除。
属性:
cv(Tk.canvas):绘制粒子的画布。
cid(Tk.canvas):粒子的tkinter画布id。
x(浮动):粒子的x坐标。
y(浮动):粒子的y坐标。
vx(浮点):粒子的x速度(以像素每秒为单位)。
vy(float):粒子的y速度(以像素/秒为单位)。
颜色(str):粒子的颜色。
年龄(浮动):粒子的年龄。
寿命(浮动):粒子的寿命(以秒为单位)。
"""
定义初始值(self,cv=None,color='white',x=0,y=0。,
vx=0,vy=0,寿命=5。):
“”“初始化粒子对象。”。
Args:
cv(Tk.canvas):绘制粒子的画布。
x(浮动):粒子的x坐标。
默认值为0.0。
y(浮动):粒子的y坐标。
默认值为0.0。
vx(浮点):粒子的x速度(以像素每秒为单位)。
默认值为0.0。
vy(float):粒子的y速度(以像素/秒为单位)。
默认值为0.0。
颜色(str):粒子的颜色。
默认为“白色”。
寿命(浮动):粒子的寿命(以秒为单位)。
默认值为5.0。
"""
self.cv=cv
self.cid=无
self.x,self.y=x,y
self.vx,self.vy=vx,vy
self.color=颜色
self.age,self.lifespan=0,寿命
def更新(自我,dt):
“”“在dt秒后更新位置和速度。
Args:
dt(float):上次更新后经过的时间(以秒为单位)。
"""
自我年龄+=dt
如果self.alive():
self.vy+=重力*dt
self.x+=self.vx*dt
self.y+=self.vy*dt
self.cv.move(self.cid、self.vx*dt、self.vy*dt)
elif self.cid不是无:
cv.delete(self.cid)
self.cid=无
def活动(自我):
“”“检查粒子是否仍在其寿命内。”“”

返回self.age在
火箭中
我不得不移动

self._tospawn += self.pps * dt
进入

阻止烟火

   elif self.cid is not None:
        cv.delete(self.cid)
        self.cid = None

        self._tospawn += 10 * self.pps * dt

   if self.cid is None:
        Fireworks.update(self, dt)
        color = self.colors[int(self.age / 3) % len(self.colors)]
        for i in range(int(self._tospawn)):
          ptype = choice(
            [CircularParticle])
          angle = uniform(-100, 100)
          speed = -uniform(80, 120.0)
          vx = sin(angle) * speed
          vy = cos(angle) * speed
          self.particles.append(
             ptype(cv=self.cv, x=self.x, y=self.y, color=color, vx=vx, vy=vy))
          self._tospawn -= self.pps * dt
您可以移动除
Framework.update()之外的所有内容


使用
print()
查看执行代码的哪一部分以及变量中有哪些值。我运行代码,Rockec仅在移动窗口时停止。非常感谢,先生,这真的很有帮助。关于这一点的任何解释?
Rocket.update()
总是在运行
时在
中执行。它设置了
self.cid=None
,因此如果self.cid始终为None:
,它将开始执行
,如果设置了
self.\u tospawn+=self.pps*dt
。这意味着
对于范围内的i(int(self.\u tospawn)):
一次又一次地创建新粒子。即使是
self.\u tospawn-=self.pps*dt
也无法阻止它。但是如果您将
self.\u tospawn+=self.pps*dt
移动到
elif self.cid不是None:
那么它将只被设置一次,
for
将只执行一次,
self.\u tospawn-=self.pps*dt
将重置它,这样下次
for
将不会产生新粒子。谢谢先生,还有一个问题,是否有可能创建一个重复多次火箭类的类,换句话说,创建随机的焰火,不仅仅是一个,而是多个?如果可能的话,请你解释一下,你是指更多的火箭还是一枚火箭加上更多的烟火。您可以在开始时创建更多火箭,并将其添加到
对象=[v1,ro]
。或者您可以使用方法
update()
创建一些
RocketsLaucher
,这样您可以添加到
对象=[v1,ro,laucher]
,它将在
模拟中执行
laucher.update()
作为
o.update()
。它需要访问
对象
,以便将新的
火箭
添加到此列表中。
   elif self.cid is not None:
        cv.delete(self.cid)
        self.cid = None

        self._tospawn += 10 * self.pps * dt

   if self.cid is None:
        Fireworks.update(self, dt)
        color = self.colors[int(self.age / 3) % len(self.colors)]
        for i in range(int(self._tospawn)):
          ptype = choice(
            [CircularParticle])
          angle = uniform(-100, 100)
          speed = -uniform(80, 120.0)
          vx = sin(angle) * speed
          vy = cos(angle) * speed
          self.particles.append(
             ptype(cv=self.cv, x=self.x, y=self.y, color=color, vx=vx, vy=vy))
          self._tospawn -= self.pps * dt
   elif self.cid is not None:
        cv.delete(self.cid)
        self.cid = None

        self._tospawn += 10 * self.pps * dt

        color = self.colors[int(self.age / 3) % len(self.colors)]
        for i in range(int(self._tospawn)):
          ptype = choice(
            [CircularParticle])
          angle = uniform(-100, 100)
          speed = -uniform(80, 120.0)
          vx = sin(angle) * speed
          vy = cos(angle) * speed
          self.particles.append(
             ptype(cv=self.cv, x=self.x, y=self.y, color=color, vx=vx, vy=vy))
          self._tospawn -= self.pps * dt

   if self.cid is None:
        Fireworks.update(self, dt)