Particle explosions
We don’t want the squares to just disappear when they are hit by a bullet. So now we’ll make use of the Macroquad particle system to generate explosions. With the particle system you can easily create and draw many small particles on the screen based on a base configuration. In our case the particles will start from the center of the square and move outwards in all directions. In a later chapter we will add a graphical image to the particles to make it look even more like a real explosion.
Implementation
Add the particle crate
The code for Macroquads particle system is in a separate crate. Start by
adding it to the Cargo.toml
file, either by changing the file by hand, or by
running the following command:
cargo add macroquad-particles
The following line will be added to the Cargo.toml
file under the heading
[dependencies]
.
[package]
name = "my-game"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
macroquad = { version = "0.4" }
macroquad-particles = "0.2.2"
Version 0.2.2 of macroquad-particles doesn’t support the latest version of
Macroquad. If you get an error when compiling you can try using both
macroquad
and macroquad-particles
crates
directly from git
by adding the following section to the Cargo.toml
file.
[patch.crates-io]
macroquad = { git = "https://github.com/not-fl3/macroquad" }
macroquad-particles = { git = "https://github.com/not-fl3/macroquad" }
Import crate
At the top of main.rs
we need to import the things we use from the
macroquad_particles
module.
use macroquad_particles::{self as particles, ColorCurve, Emitter, EmitterConfig};
Particle configuration
We’ll use the same configuration for all the explosions, and will only change
the size based on the sizes of the squares. Create a function that returns an
EmitterConfig
that can be used to create an Emitter
. The Emitter
is a
point from where particles can be generated.
fn particle_explosion() -> particles::EmitterConfig {
particles::EmitterConfig {
local_coords: false,
one_shot: true,
emitting: true,
lifetime: 0.6,
lifetime_randomness: 0.3,
explosiveness: 0.65,
initial_direction_spread: 2.0 * std::f32::consts::PI,
initial_velocity: 300.0,
initial_velocity_randomness: 0.8,
size: 3.0,
size_randomness: 0.3,
colors_curve: ColorCurve {
start: RED,
mid: ORANGE,
end: RED,
},
..Default::default()
}
}
There are a lot of different things to configure in an Emitter
. The fields of
EmitterConfig
are described in the documentation of the module macroquad-particles
.
Vector of explosions
We need another vector to keep track of all the explosions. It includes a
tuple with an Emitter
and the coordinate it should be drawn at.
let mut explosions: Vec<(Emitter, Vec2)> = vec![];
When we start a new game, we need to clear the vector of explosions.
if is_key_pressed(KeyCode::Space) {
squares.clear();
bullets.clear();
explosions.clear();
circle.x = screen_width() / 2.0;
circle.y = screen_height() / 2.0;
score = 0;
game_state = GameState::Playing;
}
Create an explosion
When a square is hit by a bullet, we’ll create a new Emitter
based on
the configuration from particle_explosion()
, with the addition that the
number of particles is based on the size of the square. The coordinates where
the particles are generated should be the same as the coordinates of
the square.
for square in squares.iter_mut() {
for bullet in bullets.iter_mut() {
if bullet.collides_with(square) {
bullet.collided = true;
square.collided = true;
score += square.size.round() as u32;
high_score = high_score.max(score);
explosions.push((
Emitter::new(EmitterConfig {
amount: square.size.round() as u32 * 2,
..particle_explosion()
}),
vec2(square.x, square.y),
));
}
}
}
Removing explosions
When the emitter has finished drawing all the particles, we need to remove
them from the explosions
vector so that we stop trying to draw it. Add the
following code below the code that removes squares and bullets.
explosions.retain(|(explosion, _)| explosion.config.emitting);
Drawing explosions
After drawing all the squares, we can loop through the explosions
vector and
draw them. We only need to send in the coordinates where the particles will be
generated, then the emitter will randomize and move all the particles by
itself.
for (explosion, coords) in explosions.iter_mut() {
explosion.draw(*coords);
}
It’s time to try the game to see if there are particle explosions when the squares get hit by bullets.