Skip to main content

ParticleEmitter

Struct ParticleEmitter 

Source
pub struct ParticleEmitter {
Show 14 fields pub position: Vec2, pub shape: EmitterShape, pub rate: f32, pub burst: u32, pub template: Particle, pub speed_range: (f32, f32), pub angle_range: (f32, f32), pub size_range: (f32, f32), pub lifetime_range: (f32, f32), pub gravity: Vec2, pub drag: f32, pub max_particles: usize, pub active: bool, pub looping: bool, /* private fields */
}
Expand description

A particle emitter that spawns particles over time.

Fields§

§position: Vec2

Position offset for the emitter.

§shape: EmitterShape

Emission shape.

§rate: f32

Particles per second.

§burst: u32

Burst count (if > 0, emit this many at once then stop).

§template: Particle

Template particle (properties are copied to new particles).

§speed_range: (f32, f32)

Velocity range (min, max speed).

§angle_range: (f32, f32)

Angle range for initial velocity (min, max in radians).

§size_range: (f32, f32)

Size range (min, max).

§lifetime_range: (f32, f32)

Lifetime range (min, max seconds).

§gravity: Vec2

Gravity applied to all particles.

§drag: f32

Drag coefficient (0 = no drag, 1 = full stop).

§max_particles: usize

Maximum number of alive particles.

§active: bool

Whether the emitter is active.

§looping: bool

Whether the emitter loops (re-emits after all particles die, if burst mode).

Implementations§

Source§

impl ParticleEmitter

Source

pub fn new(position: Vec2) -> Self

Create a new emitter with default settings.

Examples found in repository?
examples/particles.rs (line 14)
12    fn on_enter(&mut self, _ctx: &mut Context) {
13        // Fire emitter at bottom center
14        let mut fire = ParticleEmitter::new(vec2(400.0, 500.0));
15        fire.configure(|cfg| {
16            cfg
17                .rate(80.0)
18                .shape(EmitterShape::Line { x1: 370.0, y1: 500.0, x2: 430.0, y2: 500.0 })
19                .speed(80.0, 200.0)
20                .angle(std::f32::consts::PI * 1.1, std::f32::consts::PI * 1.9)
21                .size(3.0, 10.0)
22                .lifetime(0.3, 1.0)
23                .gravity(0.0, -80.0)
24                .color_start(Color::from_hex("#FF6600").unwrap())
25                .color_end(Color::from_hex("#FFFF00").unwrap())
26                .size_end(0.0)
27                .drag(1.5);
28        });
29        self.emitters.push(fire);
30
31        // Sparkle emitter
32        let mut sparkles = ParticleEmitter::new(vec2(400.0, 300.0));
33        sparkles.configure(|cfg| {
34            cfg
35                .rate(30.0)
36                .shape(EmitterShape::Circle { cx: 400.0, cy: 300.0, radius: 150.0 })
37                .speed(10.0, 50.0)
38                .angle(0.0, std::f32::consts::TAU)
39                .size(2.0, 6.0)
40                .lifetime(0.5, 1.5)
41                .gravity(0.0, 20.0)
42                .color_start(Color::from_hex("#FFFFFF").unwrap())
43                .color_end(Color::TRANSPARENT)
44                .size_end(0.0);
45        });
46        self.emitters.push(sparkles);
47    }
Source

pub fn configure(&mut self, f: impl FnOnce(&mut ParticleEmitterConfig<'_>))

Configure the emitter using a builder-style closure.

Examples found in repository?
examples/particles.rs (lines 15-28)
12    fn on_enter(&mut self, _ctx: &mut Context) {
13        // Fire emitter at bottom center
14        let mut fire = ParticleEmitter::new(vec2(400.0, 500.0));
15        fire.configure(|cfg| {
16            cfg
17                .rate(80.0)
18                .shape(EmitterShape::Line { x1: 370.0, y1: 500.0, x2: 430.0, y2: 500.0 })
19                .speed(80.0, 200.0)
20                .angle(std::f32::consts::PI * 1.1, std::f32::consts::PI * 1.9)
21                .size(3.0, 10.0)
22                .lifetime(0.3, 1.0)
23                .gravity(0.0, -80.0)
24                .color_start(Color::from_hex("#FF6600").unwrap())
25                .color_end(Color::from_hex("#FFFF00").unwrap())
26                .size_end(0.0)
27                .drag(1.5);
28        });
29        self.emitters.push(fire);
30
31        // Sparkle emitter
32        let mut sparkles = ParticleEmitter::new(vec2(400.0, 300.0));
33        sparkles.configure(|cfg| {
34            cfg
35                .rate(30.0)
36                .shape(EmitterShape::Circle { cx: 400.0, cy: 300.0, radius: 150.0 })
37                .speed(10.0, 50.0)
38                .angle(0.0, std::f32::consts::TAU)
39                .size(2.0, 6.0)
40                .lifetime(0.5, 1.5)
41                .gravity(0.0, 20.0)
42                .color_start(Color::from_hex("#FFFFFF").unwrap())
43                .color_end(Color::TRANSPARENT)
44                .size_end(0.0);
45        });
46        self.emitters.push(sparkles);
47    }
Source

pub fn particles(&self) -> &[Particle]

Get a reference to the active particles (for rendering).

Examples found in repository?
examples/particles.rs (line 77)
72    fn render(&mut self, ctx: &mut Context) {
73        ctx.graphics.clear(Color::from_hex("#0A0A1A").unwrap());
74
75        // Draw particles
76        for emitter in &self.emitters {
77            for particle in emitter.particles() {
78                if !particle.alive {
79                    continue;
80                }
81                ctx.graphics.draw_circle(
82                    particle.position.x,
83                    particle.position.y,
84                    particle.size,
85                    particle.color,
86                );
87            }
88        }
89
90        // HUD
91        ctx.graphics.draw_text(
92            &format!("Particles: {}", self.emitters.iter().map(|e| e.alive_count()).sum::<usize>()),
93            10.0, 10.0, 18.0, Color::WHITE,
94        );
95        ctx.graphics.draw_text(
96            "Move mouse = fire | Click = sparkles | Esc = quit",
97            10.0, 35.0, 14.0, Color::LIGHT_GRAY,
98        );
99    }
Source

pub fn particles_mut(&mut self) -> &mut Vec<Particle>

Get a mutable reference to active particles.

Source

pub fn alive_count(&self) -> usize

Count of alive particles.

Examples found in repository?
examples/particles.rs (line 92)
72    fn render(&mut self, ctx: &mut Context) {
73        ctx.graphics.clear(Color::from_hex("#0A0A1A").unwrap());
74
75        // Draw particles
76        for emitter in &self.emitters {
77            for particle in emitter.particles() {
78                if !particle.alive {
79                    continue;
80                }
81                ctx.graphics.draw_circle(
82                    particle.position.x,
83                    particle.position.y,
84                    particle.size,
85                    particle.color,
86                );
87            }
88        }
89
90        // HUD
91        ctx.graphics.draw_text(
92            &format!("Particles: {}", self.emitters.iter().map(|e| e.alive_count()).sum::<usize>()),
93            10.0, 10.0, 18.0, Color::WHITE,
94        );
95        ctx.graphics.draw_text(
96            "Move mouse = fire | Click = sparkles | Esc = quit",
97            10.0, 35.0, 14.0, Color::LIGHT_GRAY,
98        );
99    }
Source

pub fn update(&mut self, dt: f32)

Update the emitter and all its particles.

Examples found in repository?
examples/particles.rs (line 64)
49    fn update(&mut self, ctx: &mut Context) {
50        let dt = ctx.time.delta() as f32;
51
52        // Move fire emitter to mouse X
53        self.emitters[0].position.x = ctx.input.mouse.position.x;
54        self.emitters[0].position.y = ctx.screen_height() - 50.0;
55
56        // Burst on click
57        if ctx.input.mouse.is_pressed(MouseButton::Left) {
58            self.emitters[1].position = ctx.input.mouse.position;
59            self.emitters[1].burst_now(50);
60        }
61
62        // Update all emitters
63        for emitter in &mut self.emitters {
64            emitter.update(dt);
65        }
66
67        if ctx.input.keyboard.is_pressed(KeyCode::Escape) {
68            ctx.quit();
69        }
70    }
Source

pub fn clear(&mut self)

Remove all particles and reset the emitter.

Source

pub fn burst_now(&mut self, count: u32)

Trigger a burst emission regardless of current mode.

Examples found in repository?
examples/particles.rs (line 59)
49    fn update(&mut self, ctx: &mut Context) {
50        let dt = ctx.time.delta() as f32;
51
52        // Move fire emitter to mouse X
53        self.emitters[0].position.x = ctx.input.mouse.position.x;
54        self.emitters[0].position.y = ctx.screen_height() - 50.0;
55
56        // Burst on click
57        if ctx.input.mouse.is_pressed(MouseButton::Left) {
58            self.emitters[1].position = ctx.input.mouse.position;
59            self.emitters[1].burst_now(50);
60        }
61
62        // Update all emitters
63        for emitter in &mut self.emitters {
64            emitter.update(dt);
65        }
66
67        if ctx.input.keyboard.is_pressed(KeyCode::Escape) {
68            ctx.quit();
69        }
70    }

Trait Implementations§

Source§

impl Clone for ParticleEmitter

Source§

fn clone(&self) -> ParticleEmitter

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ParticleEmitter

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.