Fire, Smoke & Sparks
A Reusable Particle System
Smoke, fire, rain, snow, explosions and magic effects all come from the same underlying idea: spawn a burst of tiny short-lived objects that move, fade, and disappear. This module builds one reusable ParticleSystem that powers every effect.
The Particle Class
A single particle needs just enough state to move and fade: position, velocity, a lifetime that counts down, and something visual (color/size, or a small sprite) that changes as it ages.
import random
class Particle:
def __init__(self, pos, vel, color, radius, lifetime):
self.pos = pygame.Vector2(pos)
self.vel = pygame.Vector2(vel)
self.color = color
self.radius = radius
self.lifetime = lifetime
self.age = 0
def update(self, dt):
self.age += dt
self.pos += self.vel * dt
self.vel *= 0.98 # slight drag so particles slow down over time
def is_dead(self):
return self.age >= self.lifetime
def draw(self, screen):
life_pct = 1 - (self.age / self.lifetime)
alpha = max(0, int(255 * life_pct))
surf = pygame.Surface((self.radius*2, self.radius*2), pygame.SRCALPHA)
pygame.draw.circle(surf, (*self.color, alpha), (self.radius, self.radius), self.radius)
screen.blit(surf, self.pos - pygame.Vector2(self.radius, self.radius))
The Particle System Manager
The manager holds a list of every active particle, updates them all, removes dead ones, and offers emit() methods that spawn new bursts configured for a specific effect.
class ParticleSystem:
def __init__(self):
self.particles = []
def emit_explosion(self, pos, count=30):
for _ in range(count):
angle = random.uniform(0, 6.28)
speed = random.uniform(100, 350)
vel = pygame.Vector2(speed, 0).rotate_rad(angle)
color = random.choice([(255,180,50), (255,100,30), (255,220,120)])
self.particles.append(
Particle(pos, vel, color, radius=random.randint(2,5), lifetime=random.uniform(0.4,0.9))
)
def update(self, dt):
for p in self.particles:
p.update(dt)
self.particles = [p for p in self.particles if not p.is_dead()]
def draw(self, screen):
for p in self.particles:
p.draw(screen)
Configuring Different Effects
Every effect below reuses the exact same Particle/ParticleSystem classes — only the emit parameters (velocity spread, color, lifetime, gravity) change.
Opacity Decay Over a Particle's Lifetime
Every particle's draw() method computes life_pct = 1 - (age / lifetime) and turns it straight into an alpha value. Plotted over time, that relationship is a simple straight-line decay from fully opaque to fully transparent.