美文网首页
Python烟花爆炸程序实例学习

Python烟花爆炸程序实例学习

作者: 大龙10 | 来源:发表于2022-02-21 00:19 被阅读0次

    摘自:哈哈老师的日记

    https://www.toutiao.com/a7054756551550140965
    

      哈哈老师设计的烟花程序,学习实践一下。

    一、烟花爆炸设计

      给定一个点,生成粒子,爆炸效果是该粒子的半径逐渐加大,颜色随机变化,方向360度速度随机变化。


    烟花爆炸

    二、烟花爆炸主程序

      主程序 firework.py

    # firework.py
    
    from particle import Particle
    from base import *
    import time
    
    W,H = 1920,1080
    
    g= 0.1      # 重力
    balls = []  # 存放烟花粒子
    
    def Bang(n=100,pos = (W/2,H/4)):
        '''烟花爆炸'''
        for i in range(n):
            ball = Particle(pos,(4,4),(255,255,255),(0,0),(0,0),5)
            ball.color = ctx.hsv_to_rgb(random.randint(0,360),100,100)
            r = random.randint(2,12)
            ball.size = (r,r)
            ball.r = r
            speed = Vector2(random.random()*15,0).rotate(random.randint(0,360))
            ball.vel = speed
            balls.append(ball)
    
    def setup():
        size(W,H)
    
    last_time = 0   # 上次爆炸时间
    
    def draw():
        global last_time
        for event in ctx.events:
            if event.type == KEYDOWN:
                if event.key == K_SPACE:
                    pos = random.randint(50,W-100),random.randint(100,H/2)
                    Bang(200,pos)
            if event.type == MOUSEBUTTONDOWN:
                Bang(200,event.pos)
    
        if time.time() - last_time > random.randint(30,100)/10:     # 每隔一段时间爆炸一次(3 - 10秒)
            pos = random.randint(50,W-100),random.randint(100,H/2)
            Bang(random.randint(50,300),pos)
            last_time = time.time()
    
        ctx.screen.fill((0,0,0,100))    # 先清屏,alpha = 100 留残影
    
        for ball in balls[:]:       # 有删除操作,所以用 balls 的副本遍历
            if not ball.alive:
                balls.remove(ball)
            else:
                ball.applyForce(Vector2(0,g))
                ball.draw(ctx.screen)
    
    run()
    

    三、 粒子程序的实现

    粒子程序particle.py

    import pygame
    from pygame.math import Vector2
    import random,time
    
    class Particle():
    
        def __init__(self,pos,size,color=(255,255,255),vel=(0,0),acc = (0,0),mass = 1):
            self.pos = Vector2(pos)
            self.size = size
            self.color = color
            self.vel = Vector2(vel)
            self.acc = Vector2(acc)
            self.r = size[0]/2
            self.mass = mass
    
            self.borth_time = time.time()
            self.life = random.random()*10
            self.alive = True
    
        def applyForce(self,force):
            f = force / self.mass
            self.acc += f
    
        def is_OutOfEdges(self,canvas):
            rect = canvas.get_rect()
            w,h = self.size
            if self.pos.x - w/2 >= rect.width:
                return True
            elif self.pos.x +w/2<= 0:
                return True
            if self.pos.y-h/2 >= rect.height:
                return True
            elif self.pos.y +h/2<= 0:
                return True
    
        def checkLife(self):
            if self.life <= time.time() - self.borth_time:
                self.alive = False
    
        def update(self):
            self.vel += self.acc
            self.pos += self.vel
            self.acc *= 0
    
            self.checkLife()
    
        def draw(self,canvas):
            self.update()
            if not self.is_OutOfEdges(canvas):
                pygame.draw.circle(canvas,self.color,self.pos,self.r)
            else:
                self.alive = False
    
    

    四、封装 pygame

    用来简单封装 pygame的程序base.py

    # base.py
    
    import pygame
    from pygame.locals import *
    from pygame.math import Vector2
    import sys,random,math,os
    
    width,height = 1920,1080
    pygame.init()
    window = None
    pygame.display.set_caption('测试')
    
    clock = pygame.time.Clock()
    running = True
    
    class real_contex():
        def __init__(self):
            self.screen = None
            x,y = pygame.mouse.get_pos()
            self.mouseX = x
            self.mouseY = y
            self.fps = 60
    
        def fill(self,color):
            self.window.fill(0)
            if self.screen is not None:
                self.screen.fill(color)
    
        def hsv_to_rgb(self,h,s,v,a=100):
            '''颜色转换'''
            c = pygame.Color(0,0,0,a)
            c.hsva = (h,s,v,a)
            return c
    
        def setup(self):
            pass
    
        def draw(self):
            pass
    
    ctx = real_contex()
    
    def size(w,h):
        global width,height,window
        width,height = w,h
        if w == 1920 and h == 1080:
            window = pygame.display.set_mode((width,height),FULLSCREEN)
        else:
            window = pygame.display.set_mode((width,height))
    
        ctx.window = window    
        # ctx.screen = window.convert_alpha() # 支持透明度
        ctx.screen = pygame.Surface((w,h), pygame.SRCALPHA)
        ctx.width = width
        ctx.height = height
        ctx.rect = window.get_rect()
        ctx.center = ctx.rect.center
    
    def run():
        global running,window
    
        # 获取调用 run 函数的文件名
        m_name = sys._getframe(1).f_code.co_filename
        f_name = os.path.basename(m_name)
        module_name = os.path.splitext(f_name)[0]
        # print(f_name,module_name)
        # 通过文件名加载为模块,并动态获取 setup 和 draw 方法
        app_module = __import__(module_name)
        m_dir = dir(app_module)
        if 'setup' in m_dir:
            ctx.setup = app_module.setup
        if 'draw' in m_dir:
            ctx.draw = app_module.draw
        del m_dir
    
        ctx.setup()
        if window is None:
            size(800,600)
        while running:
            ctx.events = pygame.event.get()
            ctx.mouseX,ctx.mouseY = pygame.mouse.get_pos()
            for evt in ctx.events:
                if evt.type == QUIT:
                    pygame.quit()
                    sys.exit()
                if evt.type == KEYDOWN:
                    if evt.key == K_ESCAPE:
                        pygame.quit()
                        sys.exit()
    
            ctx.draw()
            window.blit(ctx.screen,(0,0))
            pygame.display.update()
            clock.tick(ctx.fps)
    

    相关文章

      网友评论

          本文标题:Python烟花爆炸程序实例学习

          本文链接:https://www.haomeiwen.com/subject/jptblrtx.html