Guest User

Particles

a guest
Feb 11th, 2025
35
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.16 KB | None | 0 0
  1. import dataclasses
  2. import random
  3. from collections import deque
  4. from dataclasses import dataclass
  5. from dataclasses import fields
  6.  
  7. import pygame
  8.  
  9. POOL_MAX = 2_000
  10. PARTICLE_COLORS = [tuple(color[:3]) for color in list(pygame.color.THECOLORS.values())]
  11. GRAVITY = 0.015
  12.  
  13. image_cache = {}
  14. particle_pool = deque(maxlen=POOL_MAX)
  15.  
  16.  
  17. @dataclass(slots=True)
  18. class Particle:
  19.     position: pygame.Vector2
  20.     direction: pygame.Vector2
  21.     color: tuple
  22.     radius: float = 5.0
  23.     glow_radius: float = 30.0
  24.     float_duration: float = 0.1
  25.     speed: int = 100
  26.     alive: bool = True
  27.  
  28.     def reset(self, position, direction, color):
  29.         self.position.update(position)
  30.         self.direction.update(direction)
  31.         self.color = color
  32.  
  33.         for data_field in fields(self):
  34.             if data_field.default is not dataclasses.MISSING:
  35.                 setattr(self, data_field.name, data_field.default)
  36.  
  37.     def update(self, delta_time):
  38.         self.float_duration -= delta_time
  39.         if self.float_duration <= 0:
  40.             self.direction.y += GRAVITY
  41.  
  42.         self.radius -= 0.03
  43.         self.glow_radius -= 0.15
  44.  
  45.         if self.glow_radius <= 1.0:
  46.             self.alive = False
  47.  
  48.         self.position += self.direction * self.speed * delta_time
  49.  
  50.  
  51. def create_background(surface):
  52.     rectangle_colors = [
  53.         ["red", "black", "skyblue"],
  54.         ["black", "green", "white"],
  55.         ["grey", "black", "blue"]
  56.     ]
  57.     margin = 50
  58.     background_surface = surface.copy()
  59.     rectangle_width = (background_surface.get_width() - (margin * 2)) // len(rectangle_colors[0])
  60.     rectangle_height = (background_surface.get_height() - (margin * 2)) // len(rectangle_colors)
  61.  
  62.     for y, colors in enumerate(rectangle_colors):
  63.         for x, color in enumerate(colors):
  64.             rect = pygame.Rect(
  65.                 (x * rectangle_width + margin, y * rectangle_height + margin),
  66.                 (rectangle_width, rectangle_height)
  67.             )
  68.             pygame.draw.rect(background_surface, color, rect, 0)
  69.  
  70.     return background_surface
  71.  
  72.  
  73. def draw_particle(surface, particles):
  74.     global image_cache
  75.  
  76.     for particle in particles:
  77.         key = (particle.color, particle.glow_radius)
  78.         if key not in image_cache:
  79.             size = [particle.glow_radius * 2] * 2
  80.             base_surface = pygame.Surface(size, flags=pygame.SRCALPHA)
  81.             glow_surface = base_surface.copy()
  82.             glow_surface.set_colorkey("black")
  83.  
  84.             center = base_surface.get_rect().center
  85.             pygame.draw.circle(glow_surface, (*particle.color, 150), center, particle.glow_radius)
  86.             glow_surface = pygame.transform.gaussian_blur(glow_surface, 5, repeat_edge_pixels=False)
  87.             base_surface.blit(glow_surface, (0, 0))
  88.  
  89.             image_cache[key] = base_surface
  90.  
  91.         base_surface = image_cache[key]
  92.         pygame.draw.circle(surface, particle.color, particle.position, particle.radius)
  93.         surface.blit(base_surface, base_surface.get_rect(center=particle.position), special_flags=pygame.BLEND_RGB_ADD)
  94.  
  95.  
  96. def update_particles(particles, delta_time):
  97.     global particle_pool
  98.  
  99.     for particle in particles[:]:
  100.         particle.update(delta_time)
  101.         if not particle.alive:
  102.             particles.remove(particle)
  103.             particle_pool.append(particle)
  104.  
  105.  
  106. def create_particles(particles, particle_count=1):
  107.     global particle_pool
  108.  
  109.     position = pygame.mouse.get_pos()
  110.  
  111.     for count in range(particle_count):
  112.         color = random.choice(PARTICLE_COLORS)
  113.  
  114.         if particle_pool:
  115.             particle = particle_pool.popleft()
  116.             particle.reset(
  117.                 position=position,
  118.                 direction=(random.uniform(-1, 1), -1),
  119.                 color=color
  120.             )
  121.         else:
  122.             particle = Particle(pygame.Vector2(position), pygame.Vector2(random.uniform(-1, 1), -1), color=color)
  123.         particles.append(particle)
  124.  
  125.  
  126. def main():
  127.     global image_cache, particle_pool
  128.  
  129.     pygame.init()
  130.     display = pygame.display.set_mode((1500, 900))
  131.     clock = pygame.Clock()
  132.     background_surface = create_background(display)
  133.  
  134.     particles = []
  135.     for _ in range(POOL_MAX):
  136.         particle_pool.append(Particle(pygame.Vector2(0, 0), pygame.Vector2(0, 0), (0, 0, 0, 0)))
  137.  
  138.     elapsed_time = 0
  139.     fixed_delta_time = 1 / 60
  140.     delta_time = 0
  141.  
  142.     running = True
  143.     while running:
  144.         for event in pygame.event.get():
  145.             if event.type == pygame.QUIT:
  146.                 running = False
  147.  
  148.         create_particles(particles, particle_count=1)
  149.  
  150.         elapsed_time += delta_time
  151.         if elapsed_time >= fixed_delta_time:
  152.             elapsed_time = 0
  153.             update_particles(particles, fixed_delta_time)
  154.  
  155.         display.fill("black")
  156.         display.blit(background_surface, (0, 0))
  157.         draw_particle(display, particles)
  158.         pygame.display.flip()
  159.         delta_time = clock.tick() / 1000
  160.         pygame.display.set_caption(
  161.             f"Cache size: {len(image_cache.keys())} "
  162.             f"Particle Pool: {len(particle_pool)} "
  163.             f"FPS: {clock.get_fps():.2f}"
  164.         )
  165.  
  166.  
  167. if __name__ == '__main__':
  168.     main()
  169.  
Add Comment
Please, Sign In to add comment