1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use comfy::*;
simple_game!("Particle Systems Example", setup, update);
fn setup(c: &mut EngineContext) {
c.load_texture_from_bytes(
// Every texture gets a string name later used to reference it.
"comfy",
include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/../assets/comfy.png"
)),
);
// ParticleSystem's are based off the same principle as singular Particle's, except the
// automatically handle the spawning.
commands().spawn((
ParticleSystem::with_spawn_rate(500, 0.01, || {
Particle {
texture: texture_id("comfy"),
position: random_circle(5.0),
size: splat(0.5),
// Other than the builtin easing curves, any f32 -> f32 curve
// will work.
size_curve: quad_in_out,
direction: vec2(0.0, 1.0),
velocity: 10.0,
velocity_end: 5.0,
..Default::default()
}
})
.with_size(vec2(3.0, 8.0)),
Transform::position(vec2(-8.0, 0.0)),
));
commands().spawn((
ParticleSystem::with_spawn_on_death(300, || {
Particle {
texture: texture_id("comfy"),
position: random_circle(5.0),
direction: random_dir().normalize(),
velocity: 3.0,
velocity_end: 10.0,
lifetime_max: 10.0,
size: splat(0.5),
// Both size and color can be faded.
fade_type: FadeType::None,
color_start: GREEN,
color_end: LIME,
// Particles can have trails. These aren't currently
// very nice to configure, but they do work!
trail: TrailRef::Local(Trail::new(
0.1,
1.0,
5,
GREEN,
BLACK,
50,
0.5,
5.0,
None,
None,
BlendMode::Additive,
)),
// If the builtin particle system logic isn't enough, the particles can also use a
// custom `update` function with arbitrary logic inside that gets called on each
// frame.
update: Some(|p| {
// Calculate distance from origin.
let current_distance = p.position.length();
const DESIRED_RADIUS: f32 = 5.0;
// Calculate the difference from the desired radius.
let difference = DESIRED_RADIUS - current_distance;
// Calculate a direction towards or away from the origin.
let orbit_pull = if difference > 0.0 {
p.position.normalize_or_zero() // Towards origin.
} else {
-p.position.normalize_or_zero() // Away from origin.
};
// Tangent along the orbit.
let side_pull = p.position.perp().normalize_or_right();
let abs_diff = difference.abs();
// Rescale the radius from 0..radius for interpolation
let abs_diff_scaled =
abs_diff.clamp_scale(0.0..DESIRED_RADIUS, 0.2..0.8);
let t = if abs_diff < 1.0 {
1.0 - abs_diff_scaled
} else {
abs_diff_scaled
};
// Combine the two directions.
p.direction =
orbit_pull.lerp(side_pull, t).normalize_or_right();
}),
..Default::default()
}
}),
Transform::position(Vec2::ZERO),
));
commands().spawn((
ParticleSystem::with_spawn_on_death(300, || {
Particle {
texture: texture_id("comfy"),
position: random_circle(5.0),
size: splat(0.7),
size_curve: expo_out,
angular_velocity: random() * 10.0,
// Both size and color can be faded.
fade_type: FadeType::Both,
color_start: RED,
color_end: RED,
..Default::default()
}
}), // .with_size(vec2(0.2, 5.0))
Transform::position(vec2(10.0, 0.0)),
));
}
fn update(_c: &mut EngineContext) {}