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: Vec2Position offset for the emitter.
shape: EmitterShapeEmission shape.
rate: f32Particles per second.
burst: u32Burst count (if > 0, emit this many at once then stop).
template: ParticleTemplate 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: Vec2Gravity applied to all particles.
drag: f32Drag coefficient (0 = no drag, 1 = full stop).
max_particles: usizeMaximum number of alive particles.
active: boolWhether the emitter is active.
looping: boolWhether the emitter loops (re-emits after all particles die, if burst mode).
Implementations§
Source§impl ParticleEmitter
impl ParticleEmitter
Sourcepub fn new(position: Vec2) -> Self
pub fn new(position: Vec2) -> Self
Create a new emitter with default settings.
Examples found in repository?
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 }Sourcepub fn configure(&mut self, f: impl FnOnce(&mut ParticleEmitterConfig<'_>))
pub fn configure(&mut self, f: impl FnOnce(&mut ParticleEmitterConfig<'_>))
Configure the emitter using a builder-style closure.
Examples found in repository?
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 }Sourcepub fn particles(&self) -> &[Particle]
pub fn particles(&self) -> &[Particle]
Get a reference to the active particles (for rendering).
Examples found in repository?
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 }Sourcepub fn particles_mut(&mut self) -> &mut Vec<Particle>
pub fn particles_mut(&mut self) -> &mut Vec<Particle>
Get a mutable reference to active particles.
Sourcepub fn alive_count(&self) -> usize
pub fn alive_count(&self) -> usize
Count of alive particles.
Examples found in repository?
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 }Sourcepub fn update(&mut self, dt: f32)
pub fn update(&mut self, dt: f32)
Update the emitter and all its particles.
Examples found in repository?
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 }Sourcepub fn burst_now(&mut self, count: u32)
pub fn burst_now(&mut self, count: u32)
Trigger a burst emission regardless of current mode.
Examples found in repository?
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
impl Clone for ParticleEmitter
Source§fn clone(&self) -> ParticleEmitter
fn clone(&self) -> ParticleEmitter
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more