TetrArcade/arcade/particle.py

135 lines
4.2 KiB
Python

"""
Particle - Object produced by an Emitter. Often used in large quantity to produce visual effects effects
"""
from arcade.sprite import Sprite
from arcade.draw_commands import Texture
import arcade.utils
from arcade.arcade_types import Point, Vector
from typing import Union
FilenameOrTexture = Union[str, Texture]
class Particle(Sprite):
"""Sprite that is emitted from an Emitter"""
def __init__(
self,
filename_or_texture: FilenameOrTexture,
change_xy: Vector,
center_xy: Point = (0.0, 0.0),
angle: float = 0,
change_angle: float = 0,
scale: float = 1.0,
alpha: int = 255,
mutation_callback=None
):
if isinstance(filename_or_texture, Texture):
super().__init__(None, scale=scale)
self.append_texture(filename_or_texture)
self.set_texture(0)
else:
super().__init__(filename_or_texture, scale=scale)
self.center_x = center_xy[0]
self.center_y = center_xy[1]
self.change_x = change_xy[0]
self.change_y = change_xy[1]
self.angle = angle
self.change_angle = change_angle
self.alpha = alpha
self.mutation_callback = mutation_callback
def update(self):
"""Advance the Particle's simulation"""
super().update()
if self.mutation_callback:
self.mutation_callback(self)
# def draw(self):
# raise NotImplementedError("Particle.draw needs to be implemented")
def can_reap(self):
"""Determine if Particle can be deleted"""
raise NotImplementedError("Particle.can_reap needs to be implemented")
class EternalParticle(Particle):
"""Particle that has no end to its life"""
def __init__(
self,
filename_or_texture: FilenameOrTexture,
change_xy: Vector,
center_xy: Point = (0.0, 0.0),
angle: float = 0,
change_angle: float = 0,
scale: float = 1.0,
alpha: int = 255,
mutation_callback=None
):
super().__init__(filename_or_texture, change_xy, center_xy, angle, change_angle, scale, alpha,
mutation_callback)
def can_reap(self):
"""Determine if Particle can be deleted"""
return False
class LifetimeParticle(Particle):
"""Particle that lives for a given amount of time and is then deleted"""
def __init__(
self,
filename_or_texture: FilenameOrTexture,
change_xy: Vector,
lifetime: float,
center_xy: Point = (0.0, 0.0),
angle: float = 0,
change_angle: float = 0,
scale: float = 1.0,
alpha: int = 255,
mutation_callback=None
):
super().__init__(filename_or_texture, change_xy, center_xy, angle, change_angle, scale, alpha,
mutation_callback)
self.lifetime_original = lifetime
self.lifetime_elapsed = 0.0
def update(self):
"""Advance the Particle's simulation"""
super().update()
self.lifetime_elapsed += 1 / 60
def can_reap(self):
"""Determine if Particle can be deleted"""
return self.lifetime_elapsed >= self.lifetime_original
class FadeParticle(LifetimeParticle):
"""Particle that animates its alpha between two values during its lifetime"""
def __init__(
self,
filename_or_texture: FilenameOrTexture,
change_xy: Vector,
lifetime: float,
center_xy: Point = (0.0, 0.0),
angle: float = 0,
change_angle: float = 0,
scale: float = 1.0,
start_alpha: int = 255,
end_alpha: int = 0,
mutation_callback=None
):
super().__init__(filename_or_texture, change_xy, lifetime, center_xy, angle, change_angle, scale, start_alpha,
mutation_callback)
self.start_alpha = start_alpha
self.end_alpha = end_alpha
def update(self):
"""Advance the Particle's simulation"""
super().update()
self.alpha = arcade.utils.lerp(self.start_alpha, self.end_alpha, self.lifetime_elapsed / self.lifetime_original)