fireeeee
This commit is contained in:
parent
345478e6e9
commit
b422cd4621
BIN
__pycache__/particle.cpython-311.pyc
Normal file
BIN
__pycache__/particle.cpython-311.pyc
Normal file
Binary file not shown.
93
main.py
93
main.py
@ -3,60 +3,75 @@ import random
|
|||||||
from particle import Particle
|
from particle import Particle
|
||||||
|
|
||||||
pygame.init()
|
pygame.init()
|
||||||
|
|
||||||
# Set up display and clock.
|
|
||||||
screen = pygame.display.set_mode((800, 600))
|
screen = pygame.display.set_mode((800, 600))
|
||||||
pygame.display.set_caption("Particle Test")
|
pygame.display.set_caption("Fireplace Simulation")
|
||||||
clock = pygame.time.Clock()
|
clock = pygame.time.Clock()
|
||||||
|
|
||||||
particles = []
|
particles = []
|
||||||
|
|
||||||
|
# Define the fireplace area (a simple rectangle to simulate a brick fireplace)
|
||||||
|
fireplace_rect = pygame.Rect(300, 400, 200, 200) # x, y, width, height
|
||||||
|
|
||||||
running = True
|
running = True
|
||||||
while running:
|
while running:
|
||||||
dt = clock.tick(60) / 1000.0 # Delta time in seconds.
|
dt = clock.tick() / 1000.0 # Delta time in seconds
|
||||||
|
|
||||||
# Event loop: quit on window close or spawn new particles on mouse click.
|
|
||||||
for event in pygame.event.get():
|
for event in pygame.event.get():
|
||||||
if event.type == pygame.QUIT:
|
if event.type == pygame.QUIT:
|
||||||
running = False
|
running = False
|
||||||
elif event.type == pygame.MOUSEBUTTONDOWN:
|
|
||||||
# Create several particles at the mouse position.
|
|
||||||
for _ in range(10):
|
|
||||||
pos = pygame.mouse.get_pos()
|
|
||||||
vel = (random.uniform(-100, 100), random.uniform(-100, 100))
|
|
||||||
p = Particle(
|
|
||||||
pos=pos,
|
|
||||||
vel=vel,
|
|
||||||
acceleration=(0, 0),
|
|
||||||
lifetime=2.0,
|
|
||||||
decay_rate=1,
|
|
||||||
color=(
|
|
||||||
random.randint(100, 255),
|
|
||||||
random.randint(100, 255),
|
|
||||||
random.randint(100, 255)
|
|
||||||
),
|
|
||||||
size=5,
|
|
||||||
size_decay=2,
|
|
||||||
glow=True,
|
|
||||||
glow_intensity=1.0,
|
|
||||||
friction=0.1,
|
|
||||||
gravity=50,
|
|
||||||
bounce=True,
|
|
||||||
bounce_damping=0.7,
|
|
||||||
random_spread=10,
|
|
||||||
spin=0,
|
|
||||||
spin_rate=random.uniform(-180, 180),
|
|
||||||
spin_decay=0.5,
|
|
||||||
trail=True,
|
|
||||||
trail_length=15,
|
|
||||||
fade=True,
|
|
||||||
shape='circle'
|
|
||||||
)
|
|
||||||
particles.append(p)
|
|
||||||
|
|
||||||
# Clear the screen.
|
# Clear the screen.
|
||||||
screen.fill((0, 0, 0))
|
screen.fill((0, 0, 0))
|
||||||
|
|
||||||
|
# Draw the fireplace background:
|
||||||
|
# Fill with a dark brick color and draw a border to simulate the fireplace frame.
|
||||||
|
# pygame.draw.rect(screen, (70, 20, 20), fireplace_rect) # Fireplace interior
|
||||||
|
# pygame.draw.rect(screen, (150, 50, 50), fireplace_rect, 5) # Fireplace border
|
||||||
|
|
||||||
|
# Determine a random fire origin along the bottom edge inside the fireplace.
|
||||||
|
|
||||||
|
|
||||||
|
# Spawn fire particles from the fire origin.
|
||||||
|
particles_to_spawn = (16000 - len(particles))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for _ in range(particles_to_spawn):
|
||||||
|
fire_origin = (
|
||||||
|
random.uniform(0, 800),
|
||||||
|
600
|
||||||
|
)
|
||||||
|
fire_particle = Particle(
|
||||||
|
pos=(fire_origin[0] + random.uniform(-5, 5), fire_origin[1] + random.uniform(-2, 2)),
|
||||||
|
vel=(random.uniform(-20, 20), random.uniform(-80, -120)), # Upward motion
|
||||||
|
lifetime=1.5,
|
||||||
|
decay_rate=1,
|
||||||
|
size=random.uniform(5, 8),
|
||||||
|
size_decay=5,
|
||||||
|
glow=True,
|
||||||
|
glow_intensity=1.0,
|
||||||
|
friction=0.05,
|
||||||
|
gravity=-30, # Negative gravity makes the particle rise
|
||||||
|
fade=True,
|
||||||
|
particle_type="fire"
|
||||||
|
)
|
||||||
|
particles.append(fire_particle)
|
||||||
|
|
||||||
|
# smoke_particle = Particle(
|
||||||
|
# pos=(fire_origin[0] + random.uniform(-10, 10), fire_origin[1] + random.uniform(-2, 2)),
|
||||||
|
# vel=(random.uniform(-10, 10), random.uniform(-40, -60)), # Slower upward motion
|
||||||
|
# lifetime=2.5,
|
||||||
|
# decay_rate=0.8,
|
||||||
|
# size=random.uniform(8, 12),
|
||||||
|
# size_decay=1,
|
||||||
|
# glow=False,
|
||||||
|
# friction=0.02,
|
||||||
|
# gravity=-10,
|
||||||
|
# fade=True,
|
||||||
|
# particle_type="smoke"
|
||||||
|
# )
|
||||||
|
# particles.append(smoke_particle)
|
||||||
|
|
||||||
# Update and draw each particle.
|
# Update and draw each particle.
|
||||||
for particle in particles[:]:
|
for particle in particles[:]:
|
||||||
particle.update(dt, screen.get_rect())
|
particle.update(dt, screen.get_rect())
|
||||||
|
92
particle.py
92
particle.py
@ -1,6 +1,5 @@
|
|||||||
import pygame
|
import pygame
|
||||||
import random
|
import random
|
||||||
import math
|
|
||||||
|
|
||||||
class Particle:
|
class Particle:
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -8,15 +7,15 @@ class Particle:
|
|||||||
pos,
|
pos,
|
||||||
vel=(0, 0),
|
vel=(0, 0),
|
||||||
acceleration=(0, 0),
|
acceleration=(0, 0),
|
||||||
lifetime=2.0, # seconds the particle lives
|
lifetime=1.0, # seconds the particle lives
|
||||||
decay_rate=1, # how fast the lifetime decreases
|
decay_rate=1.0, # how fast the lifetime decreases
|
||||||
color=(255, 255, 255),
|
color=(255, 255, 255),
|
||||||
size=5,
|
size=5,
|
||||||
size_decay=0, # rate at which the size decreases
|
size_decay=5, # rate at which the size decreases
|
||||||
glow=False,
|
glow=False,
|
||||||
glow_intensity=0, # multiplier for glow radius
|
glow_intensity=0, # multiplier for glow radius
|
||||||
friction=0, # slows down velocity over time
|
friction=0.05, # slows down velocity over time
|
||||||
gravity=0, # constant acceleration downward
|
gravity=0, # constant acceleration (negative makes it rise)
|
||||||
bounce=False,
|
bounce=False,
|
||||||
bounce_damping=0.5, # energy loss when bouncing off boundaries
|
bounce_damping=0.5, # energy loss when bouncing off boundaries
|
||||||
random_spread=0, # randomness added to velocity each update
|
random_spread=0, # randomness added to velocity each update
|
||||||
@ -25,20 +24,19 @@ class Particle:
|
|||||||
spin_decay=0, # how spin_rate slows down
|
spin_decay=0, # how spin_rate slows down
|
||||||
trail=False,
|
trail=False,
|
||||||
trail_length=10, # how many previous positions to store
|
trail_length=10, # how many previous positions to store
|
||||||
fade=False, # if True, the particle will fade (alpha decreases)
|
fade=True, # if True, the particle will fade (alpha decreases)
|
||||||
shape='circle' # could be 'circle' or 'square'
|
shape='circle', # could be 'circle' or 'square'
|
||||||
|
particle_type="generic" # "fire" or "smoke"
|
||||||
):
|
):
|
||||||
# Position, velocity, and acceleration are stored as vectors.
|
# Position, velocity, and acceleration as vectors.
|
||||||
self.pos = pygame.math.Vector2(pos)
|
self.pos = pygame.math.Vector2(pos)
|
||||||
self.vel = pygame.math.Vector2(vel)
|
self.vel = pygame.math.Vector2(vel)
|
||||||
self.acceleration = pygame.math.Vector2(acceleration)
|
self.acceleration = pygame.math.Vector2(acceleration)
|
||||||
|
|
||||||
# Lifetime and decay
|
|
||||||
self.lifetime = lifetime
|
self.lifetime = lifetime
|
||||||
self.initial_lifetime = lifetime
|
self.initial_lifetime = lifetime
|
||||||
self.decay_rate = decay_rate
|
self.decay_rate = decay_rate
|
||||||
|
|
||||||
# Appearance settings
|
|
||||||
self.color = color
|
self.color = color
|
||||||
self.size = size
|
self.size = size
|
||||||
self.initial_size = size
|
self.initial_size = size
|
||||||
@ -46,7 +44,6 @@ class Particle:
|
|||||||
self.fade = fade
|
self.fade = fade
|
||||||
self.alpha = 255
|
self.alpha = 255
|
||||||
|
|
||||||
# Effects options
|
|
||||||
self.glow = glow
|
self.glow = glow
|
||||||
self.glow_intensity = glow_intensity
|
self.glow_intensity = glow_intensity
|
||||||
self.friction = friction
|
self.friction = friction
|
||||||
@ -55,44 +52,61 @@ class Particle:
|
|||||||
self.bounce_damping = bounce_damping
|
self.bounce_damping = bounce_damping
|
||||||
self.random_spread = random_spread
|
self.random_spread = random_spread
|
||||||
|
|
||||||
# Spin (if using rotated images or shapes)
|
|
||||||
self.spin = spin
|
self.spin = spin
|
||||||
self.spin_rate = spin_rate
|
self.spin_rate = spin_rate
|
||||||
self.spin_decay = spin_decay
|
self.spin_decay = spin_decay
|
||||||
|
|
||||||
# Trail settings: stores previous positions to create a trailing effect
|
|
||||||
self.trail = trail
|
self.trail = trail
|
||||||
self.trail_length = trail_length
|
self.trail_length = trail_length
|
||||||
self.positions = [self.pos.copy()] if trail else []
|
self.positions = [self.pos.copy()] if trail else []
|
||||||
|
|
||||||
# Shape of the particle ('circle' or 'square')
|
|
||||||
self.shape = shape
|
self.shape = shape
|
||||||
|
|
||||||
|
# Particle type for specialized behavior.
|
||||||
|
self.particle_type = particle_type
|
||||||
|
|
||||||
def update(self, dt, screen_rect):
|
def update(self, dt, screen_rect):
|
||||||
"""
|
# Decrease lifetime.
|
||||||
dt: Delta time in seconds.
|
|
||||||
screen_rect: The rectangle representing screen boundaries (for bounce).
|
|
||||||
"""
|
|
||||||
# Decrease lifetime
|
|
||||||
self.lifetime -= self.decay_rate * dt
|
self.lifetime -= self.decay_rate * dt
|
||||||
if self.lifetime < 0:
|
if self.lifetime < 0:
|
||||||
self.lifetime = 0
|
self.lifetime = 0
|
||||||
|
|
||||||
# Add random variation to velocity if enabled.
|
# Compute life ratio (1 at birth, 0 at death).
|
||||||
|
life_ratio = self.lifetime / self.initial_lifetime if self.initial_lifetime else 0
|
||||||
|
|
||||||
|
# Update color based on particle type.
|
||||||
|
if self.particle_type == "fire":
|
||||||
|
# Realistic fire uses a multi-stage color gradient:
|
||||||
|
# At birth: bright white-yellow, mid-life: vivid orange, end: dark red.
|
||||||
|
if life_ratio > 0.5:
|
||||||
|
factor = (life_ratio - 0.5) / 0.5 # factor from 1 to 0 as life_ratio goes from 1 -> 0.5
|
||||||
|
r = 255
|
||||||
|
g = int(255 * factor + 180 * (1 - factor))
|
||||||
|
b = int(240 * factor + 50 * (1 - factor))
|
||||||
|
else:
|
||||||
|
factor = life_ratio / 0.5 # factor from 1 to 0 as life_ratio goes from 0.5 -> 0
|
||||||
|
r = int(255 * factor + 150 * (1 - factor))
|
||||||
|
g = int(180 * factor)
|
||||||
|
b = int(50 * factor)
|
||||||
|
self.color = (r, g, b)
|
||||||
|
elif self.particle_type == "smoke":
|
||||||
|
# Smoke transitions from a semi-transparent dark gray to a light gray.
|
||||||
|
start_shade = 100
|
||||||
|
end_shade = 230
|
||||||
|
shade = int(start_shade * life_ratio + end_shade * (1 - life_ratio))
|
||||||
|
self.color = (shade, shade, shade)
|
||||||
|
|
||||||
|
# Optionally add random spread.
|
||||||
if self.random_spread:
|
if self.random_spread:
|
||||||
self.vel.x += random.uniform(-self.random_spread, self.random_spread) * dt
|
self.vel.x += random.uniform(-self.random_spread, self.random_spread) * dt
|
||||||
self.vel.y += random.uniform(-self.random_spread, self.random_spread) * dt
|
self.vel.y += random.uniform(-self.random_spread, self.random_spread) * dt
|
||||||
|
|
||||||
# Apply gravity (as an extra acceleration on the y-axis)
|
# Apply gravity (negative gravity makes particles rise).
|
||||||
self.acceleration.y += self.gravity
|
self.acceleration.y += self.gravity
|
||||||
|
|
||||||
# Update velocity using acceleration.
|
# Update velocity and position.
|
||||||
self.vel += self.acceleration * dt
|
self.vel += self.acceleration * dt
|
||||||
|
|
||||||
# Apply friction to slow the particle over time.
|
|
||||||
self.vel *= (1 - self.friction * dt)
|
self.vel *= (1 - self.friction * dt)
|
||||||
|
|
||||||
# Update the position based on velocity.
|
|
||||||
self.pos += self.vel * dt
|
self.pos += self.vel * dt
|
||||||
|
|
||||||
# Bounce off screen edges if enabled.
|
# Bounce off screen edges if enabled.
|
||||||
@ -110,55 +124,57 @@ class Particle:
|
|||||||
elif self.pos.y + self.size > screen_rect.bottom:
|
elif self.pos.y + self.size > screen_rect.bottom:
|
||||||
self.pos.y = screen_rect.bottom - self.size
|
self.pos.y = screen_rect.bottom - self.size
|
||||||
|
|
||||||
# Update spin
|
# Update spin.
|
||||||
self.spin += self.spin_rate * dt
|
self.spin += self.spin_rate * dt
|
||||||
self.spin_rate *= (1 - self.spin_decay * dt)
|
self.spin_rate *= (1 - self.spin_decay * dt)
|
||||||
|
|
||||||
# Decrease size if size_decay is set.
|
# Decrease size.
|
||||||
if self.size_decay:
|
if self.size_decay:
|
||||||
self.size = max(0, self.size - self.size_decay * dt)
|
self.size = max(0, self.size - self.size_decay * dt)
|
||||||
|
|
||||||
# Fade out by decreasing alpha based on lifetime.
|
# Fade out by adjusting alpha.
|
||||||
if self.fade:
|
if self.fade:
|
||||||
self.alpha = int(255 * (self.lifetime / self.initial_lifetime))
|
self.alpha = int(255 * life_ratio)
|
||||||
if self.alpha < 0:
|
if self.alpha < 0:
|
||||||
self.alpha = 0
|
self.alpha = 0
|
||||||
|
|
||||||
# Update trail history.
|
# Update trail positions if enabled.
|
||||||
if self.trail:
|
if self.trail:
|
||||||
self.positions.append(self.pos.copy())
|
self.positions.append(self.pos.copy())
|
||||||
if len(self.positions) > self.trail_length:
|
if len(self.positions) > self.trail_length:
|
||||||
self.positions.pop(0)
|
self.positions.pop(0)
|
||||||
|
|
||||||
|
# Reset acceleration for next update.
|
||||||
|
self.acceleration = pygame.math.Vector2(0, 0)
|
||||||
|
|
||||||
def draw(self, surface):
|
def draw(self, surface):
|
||||||
# Set drawing color with alpha if fading.
|
# Apply alpha to color if fading.
|
||||||
if self.fade:
|
if self.fade:
|
||||||
draw_color = (*self.color, self.alpha)
|
draw_color = (*self.color, self.alpha)
|
||||||
else:
|
else:
|
||||||
draw_color = self.color
|
draw_color = self.color
|
||||||
|
|
||||||
# Draw the particle's trail if enabled.
|
# Optionally draw a trail.
|
||||||
if self.trail and len(self.positions) > 1:
|
if self.trail and len(self.positions) > 1:
|
||||||
for i in range(1, len(self.positions)):
|
for i in range(1, len(self.positions)):
|
||||||
start = self.positions[i - 1]
|
start = self.positions[i - 1]
|
||||||
end = self.positions[i]
|
end = self.positions[i]
|
||||||
pygame.draw.line(surface, draw_color, start, end, int(self.size))
|
pygame.draw.line(surface, draw_color, start, end, int(self.size))
|
||||||
|
|
||||||
# Draw glow effect if enabled.
|
# Optionally draw glow.
|
||||||
if self.glow:
|
if self.glow:
|
||||||
glow_radius = int(self.size * (1 + self.glow_intensity))
|
glow_radius = int(self.size * (1 + self.glow_intensity))
|
||||||
glow_color = (*self.color, self.alpha) if self.fade else self.color
|
glow_color = (*self.color, self.alpha)
|
||||||
glow_surface = pygame.Surface((glow_radius * 2, glow_radius * 2), pygame.SRCALPHA)
|
glow_surface = pygame.Surface((glow_radius * 2, glow_radius * 2), pygame.SRCALPHA)
|
||||||
pygame.draw.circle(glow_surface, glow_color, (glow_radius, glow_radius), glow_radius)
|
pygame.draw.circle(glow_surface, glow_color, (glow_radius, glow_radius), glow_radius)
|
||||||
surface.blit(glow_surface, (self.pos.x - glow_radius, self.pos.y - glow_radius), special_flags=pygame.BLEND_ADD)
|
surface.blit(glow_surface, (self.pos.x - glow_radius, self.pos.y - glow_radius), special_flags=pygame.BLEND_ADD)
|
||||||
|
|
||||||
# Draw the particle shape.
|
# Draw the particle (default is circle).
|
||||||
if self.shape == 'circle':
|
if self.shape == 'circle':
|
||||||
pygame.draw.circle(surface, draw_color, (int(self.pos.x), int(self.pos.y)), int(self.size))
|
pygame.draw.circle(surface, draw_color, (int(self.pos.x), int(self.pos.y)), int(self.size))
|
||||||
elif self.shape == 'square':
|
elif self.shape == 'square':
|
||||||
rect = pygame.Rect(self.pos.x - self.size, self.pos.y - self.size, self.size * 2, self.size * 2)
|
rect = pygame.Rect(self.pos.x - self.size, self.pos.y - self.size, self.size * 2, self.size * 2)
|
||||||
pygame.draw.rect(surface, draw_color, rect)
|
pygame.draw.rect(surface, draw_color, rect)
|
||||||
# Additional shapes (e.g., triangles, rotated images) can be added here.
|
|
||||||
|
|
||||||
def is_dead(self):
|
def is_dead(self):
|
||||||
"""Return True if the particle should be removed."""
|
"""Return True if the particle should be removed."""
|
||||||
|
Loading…
Reference in New Issue
Block a user