Pygame 粒子效果

问题描述 投票:0回答:2

所以我有这个迷你粒子效果,可以产生向上移动的圆圈。我想让它看起来像烟雾。但我有很多问题。

  1. 首先我想让它递归,这样当粒子到达顶部时 返回到原来的位置并重新开始,我所拥有的有点效果,但不完全是。
  2. 另一件事是我不觉得它真的看起来像烟雾,有人可以建议改变以使其看起来更好吗?
  3. 我也想将其添加到我的游戏中,我如何使其可在我的游戏中调用,这样我就可以调用粒子并给它一个位置,然后它就会出现在那里。任何人都可以帮忙解决这个问题吗?

我的代码

import pygame,random
from pygame.locals import *

xmax = 1000    #width of window
ymax = 600     #height of window

class Particle():
    def __init__(self, x, y, dx, dy, col):
        self.x = x
        self.y = y
        self.col = col
        self.ry = y
        self.rx = x
        self.dx = dx
        self.dy = dy

    def move(self):
        if self.y >= 10:
            if self.dy < 0:
                self.dy = -self.dy

        self.ry -= self.dy
        self.y = int(self.ry + 0.5)

        self.dy -= .1
        if self.y < 1:
            self.y += 500

def main():
    pygame.init()
    screen = pygame.display.set_mode((xmax,ymax))
    white = (255, 255, 255)
    black = (0,0,0)
    grey = (128,128,128)

    particles = []
    for part in range(25):
        if part % 2 > 0: col = black
        else: col = grey
        particles.append( Particle(random.randint(500, 530), random.randint(0, 500), 0, 0, col))

    exitflag = False
    while not exitflag:
        for event in pygame.event.get():
            if event.type == QUIT:
                exitflag = True
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    exitflag = True

        screen.fill(white)
        for p in particles:
            p.move()
            pygame.draw.circle(screen, p.col, (p.x, p.y), 8)

        pygame.display.flip()
    pygame.quit()

if __name__ == "__main__":
    main()
python recursion pygame effects particles
2个回答
4
投票

我对您的代码进行了一些重大编辑。首先,我极大地清理了你们的班级。让我们从参数和

__init__
函数开始。

首先,粒子不会下降 500 来重置,而是会前往设置为起点的位置。它开始的位置现在是在

__init__
函数中随机选择的,而不是在游戏中。我也摆脱了你一些不必要的争论。

在你们班级的

move
函数中,我简化了很多。为了让粒子检测它是否应该重置,它只是查看它是否高于 0。上升只是 y 简单地减少 1。我添加的一个更改是 x 随机变化并向右移动离开。这将使烟雾看起来更好/更真实。

我没有对您的其余代码进行太多更改。我更改了您对

Particle
类的调用以适应新的参数。我制作了更多的粒子,再次是为了视觉效果。我还大幅减小了为视觉效果(你能猜到吗?)绘制的圆圈的大小。我还添加了一个时钟,以防止粒子以超音速运动。

这是最终的代码。我希望你喜欢它。

import pygame,random
from pygame.locals import *

xmax = 1000    #width of window
ymax = 600     #height of window

class Particle():
    def __init__(self, startx, starty, col):
        self.x = startx
        self.y = random.randint(0, starty)
        self.col = col
        self.sx = startx
        self.sy = starty

    def move(self):
        if self.y < 0:
            self.x=self.sx
            self.y=self.sy

        else:
            self.y-=1

        self.x+=random.randint(-2, 2)

def main():
    pygame.init()
    screen = pygame.display.set_mode((xmax,ymax))
    white = (255, 255, 255)
    black = (0,0,0)
    grey = (128,128,128)

    clock=pygame.time.Clock()

    particles = []
    for part in range(300):
        if part % 2 > 0: col = black
        else: col = grey
        particles.append( Particle(515, 500, col) )

    exitflag = False
    while not exitflag:
        for event in pygame.event.get():
            if event.type == QUIT:
                exitflag = True
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    exitflag = True

        screen.fill(white)
        for p in particles:
            p.move()
            pygame.draw.circle(screen, p.col, (p.x, p.y), 2)

        pygame.display.flip()
        clock.tick(50)
    pygame.quit()

if __name__ == "__main__":
    main()

更新

为了将粒子添加到您的代码中,只需执行上面代码中所做的操作即可。效果很好。如果你想做一些事情来显示烟雾开始,只需在你的论证中加入一个暂停时间并抑制烟雾的移动,直到该时间过去。添加了新课程:

class Particle():
    def __init__(self, startx, starty, col, pause):
        self.x = startx
        self.y = starty
        self.col = col
        self.sx = startx
        self.sy = starty
        self.pause = pause

    def move(self):
        if self.pause==0:
            if self.y < 0:
                self.x=self.sx
                self.y=self.sy

            else:
                self.y-=1

            self.x+=random.randint(-2, 2)

        else:
            self.pause-=1

创建新粒子所需的代码:

for part in range(1, A):
    if part % 2 > 0: col = black
    else: col = grey
    particles.append( Particle(515, B, col, round(B*part/A)) )

A 和 B 是变量(我建议 A 为 300 左右,B 为 Y 值)

新代码将使粒子在起始位置产生,并连续上升而不会中断。希望您喜欢。


1
投票

我对您的代码做了很多更改,特别是在

Particle
类中。
虽然这段代码中有一些令人费解的地方,但它会比你当前的代码更灵活。

这里,
我已经相当有文化地重写了你的

Particle
课程。
除了更改
__init__
之外,还要采用许多参数(确切地说是 7 个),
我使用了三角函数和
math
模块来
move
粒子,使其更易于管理(如果您擅长数学!)。我还在
bounce
中添加了
draw
Particle
方法,使代码更具可读性。
就像 @PygameNerd 一样,我添加了一个时钟,用于限制最大 fps。 我没有更改任何事件处理,但在
bounce
循环中使用了
draw
for p in particles:
函数。

import pygame, random, math

def radians(degrees):
    return degrees*math.pi/180

class Particle:
    def __init__(self, (x, y), radius, speed, angle, colour, surface):
        self.x = x
        self.y = y
        self.speed = speed
        self.angle = angle
        self.radius = radius
        self.surface = surface
        self.colour = colour
        self.rect = pygame.draw.circle(surface,(255,255,0),
                           (int(round(x,0)),
                            int(round(y,0))),
                           self.radius)
    def move(self):
        """ Update speed and position based on speed, angle """
        # for constant change in position values.
        self.x += math.sin(self.angle) * self.speed
        self.y -= math.cos(self.angle) * self.speed
        # pygame.rect likes int arguments for x and y
        self.rect.x = int(round(self.x))
        self.rect.y = int(round(self.y))
        
    def draw(self):
        """ Draw the particle on screen"""
        pygame.draw.circle(self.surface,self.colour,self.rect.center,self.radius)
        
    def bounce(self):
        """ Tests whether a particle has hit the boundary of the environment """
        
        if self.x > self.surface.get_width() - self.radius: # right
            self.x = 2*(self.surface.get_width() - self.radius) - self.x
            self.angle = - self.angle
            
        elif self.x < self.radius: # left
            self.x = 2*self.radius - self.x
            self.angle = - self.angle            

        if self.y > self.surface.get_height() - self.radius: # bottom
            self.y = 2*(self.surface.get_height() - self.radius) - self.y
            self.angle = math.pi - self.angle
            
        elif self.y < self.radius: # top
            self.y = 2*self.radius - self.y
            self.angle = math.pi - self.angle

def main():
    xmax = 640    #width of window
    ymax = 480     #height of window
    white = (255, 255, 255)
    black = (0,0,0)
    grey = (128,128,128)
    
    pygame.init()
    screen = pygame.display.set_mode((xmax,ymax))
    clock = pygame.time.Clock()

    particles = []
    
    for i in range(1000):
        if i % 2:
            colour = black
        else:
            colour = grey
        # for readability
        x = random.randint(0, xmax)
        y = random.randint(0, ymax)
        speed = random.randint(0,20)*0.1
        angle = random.randint(0,360)
        radius = 3
        particles.append( Particle((x, y), radius, speed, angle, colour, screen) )

    done = False
    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
                break
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    done = True
                    break
        if done:
            break

        screen.fill(white)
        for p in particles:
            p.move()
            p.bounce()
            p.draw()
            
        clock.tick(40)
        
        pygame.display.flip()
    pygame.quit()

if __name__ == "__main__":
    main()
© www.soinside.com 2019 - 2024. All rights reserved.