摘自:哈哈老师的日记
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)
网友评论