所以我试图制作一些类似于烟花的东西。我做了一个粒子类,它将组成烟花。
class Particle:
def __init__(self, pos, angle):
self.pos = pos
self.angle = angle
self.color = choice([(217, 103, 51), (238, 95, 30)])
self.radius = uniform(2, 7)
self.pull = 0
self.start = time.time()
def adjust(self):
self.radius -= 0.03
def draw(self):
if self.radius > 0:
pygame.draw.circle(D, self.color, (int(self.pos[0])
, int(self.pos[1])), int(self.radius))
def move(self):
now = time.time()
self.pos[0] += cos(radians(self.angle)) * 2
self.pos[1] += (sin(radians(self.angle)) + self.pull) * 2
if now - self.start > 0.1:
self.pull += 0.25
self.start = now
Run Code Online (Sandbox Code Playgroud)
然后我做了一个 Fireworks 类,它从 0 到 360 度发射粒子。
class FireWorks:
def __init__(self):
self.particles = []
for i in range(360):
self.particles.append(Particle([600, 300], i))
def explode(self):
for i in range(len(self.particles)):
self.particles[i].draw()
self.particles[i].move()
self.particles[i].adjust()
for p in self.particles:
if p.radius < 0:
self.particles.remove(p)
Run Code Online (Sandbox Code Playgroud)
现在我想从它们产生的位置 (600, 300) 沿着粒子所走的路径画一条线。但问题是粒子不会沿直线移动。为了使它看上去有点更自然,我这样做的y值:self.pos[1] += (sin(radians(self.angle)) + self.pull) * 2。的值self.pull每 0.1 秒增加 0.25。我尝试过的一件事是每次 y 增加时存储位置值并在这些位置之间画线,以便形成曲线,但根本没有绘制任何东西并导致滞后。这里的代码只显示了生成点和在点之间绘制线所涉及的位。
class Particle:
def __init__(self, pos, angle):
self.points = [] #added list to init to hold the points between which lines need to be drawn
def move(self):
# In move method, every time a value is added to y, we record position at that point
if now - self.start > 0.1:
self.points.append(self.pos)
self.pull += 0.25
def draw(self):
# Iterate through the points in the list and draw a line between them
for i in range(len(self.points)):
for j in range(1, len(self.points)):
pygame.draw.line(D, self.color, (int(self.points[i][0]), int(self.points[i][1]))
, (int(self.points[j][0]), int(self.points[j][1])), int(self.radius))
Run Code Online (Sandbox Code Playgroud)
下面是完整的代码供参考。
import pygame
from math import radians, sin, cos
from random import choice, uniform, randint
import time
pygame.init()
WIN = pygame.display
D = WIN.set_mode((1200, 600))
class Particle:
def __init__(self, pos, angle):
self.pos = pos
self.angle = angle
self.color = choice([(217, 103, 51), (238, 95, 30)])
self.radius = uniform(2, 7)
self.pull = 0
self.start = time.time()
self.points = []
def adjust(self):
self.radius -= 0.03
def draw(self):
if self.radius > 0:
pygame.draw.circle(D, self.color, (int(self.pos[0])
, int(self.pos[1])), int(self.radius))
for i in range(len(self.points)):
for j in range(1, len(self.points)):
pygame.draw.line(D, self.color, (int(self.points[i][0]), int(self.points[i][1]))
, (int(self.points[j][0]), int(self.points[j][1])), int(self.radius))
def move(self):
now = time.time()
self.pos[0] += cos(radians(self.angle)) * 2
self.pos[1] += (sin(radians(self.angle)) + self.pull) * 2
if now - self.start > 0.1:
self.points.append(self.pos)
self.pull += 0.25
self.start = now
class FireWorks:
def __init__(self):
self.particles = []
for i in range(360):
self.particles.append(Particle([600, 300], i))
def explode(self):
for i in range(len(self.particles)):
self.particles[i].draw()
self.particles[i].move()
self.particles[i].adjust()
for p in self.particles:
if p.radius < 0:
self.particles.remove(p)
f = FireWorks()
D.fill((0, 0, 0))
while True:
pygame.event.get()
D.fill((0, 0, 0))
f.explode()
WIN.flip()
Run Code Online (Sandbox Code Playgroud)
您必须将位置元组的副本附加到位置列表中,而不是对位置的引用:
self.points.append(self.pos)
self.points.append(self.pos[:])
Run Code Online (Sandbox Code Playgroud)
注意,self.pos指的是具有 2 个组件的元组。因此,self.points.append(self.pos)会将对此位置的新引用附加到列表中,但不会生成新位置。
为了提高性能,我建议将积分位置添加到列表中,并通过以下方式沿粒子路径绘制线条pygame.draw.lines():
class Particle:
# [...]
def draw(self):
if self.radius > 0:
pygame.draw.circle(D, self.color, (int(self.pos[0])
, int(self.pos[1])), int(self.radius))
if len(self.points) > 1:
pygame.draw.lines(D, self.color, False, self.points)
def move(self):
now = time.time()
self.pos[0] += cos(radians(self.angle)) * 2
self.pos[1] += (sin(radians(self.angle)) + self.pull) * 2
if now - self.start > 0.1:
x, y = round(self.pos[0]), round(self.pos[1])
self.points.append((x, y))
self.pull += 0.25
self.start = now
Run Code Online (Sandbox Code Playgroud)