That's it, the game works, we have high scores, and we can start a new game.
On top of that, it would be nice if the tiles slid into place instead of just "appearing" at their next location.
To do that we can use a plugin called bevy_easings
. We need to add it to our Cargo.toml
, which I'll do with cargo-edit.
cargo add bevy_easings
Then we can bring everything into scope
use bevy_easings::*;
and add the plugin to our app builder.
.add_plugin(EasingsPlugin)
Then we can get right to editing the render_tiles
system. We'll need commands
access and the tile Entity
as well. We no longer need mutable access to Transform
because we'll be using bevy_easings
to handle that for us. Now that we've learned about filters we can move Changed<Position>
into the filter position in our query so that we only operate on tiles that have changed Position
(before, we were manually checking that for each tile).
fn render_tiles(
mut commands: Commands,
tiles: Query<
(Entity, &Transform, &Position),
Changed<Position>,
>,
query_board: Query<&Board>,
) {
We iterate over the queried tiles and change the part where we're setting the transform
to declaring our new x
and y
variables.
Then we need to get the EntityCommands
like we did when we used despawn_recursive
and we can use that to insert a new component.
When we brought bevy_easings::*
into scope, it added a function for us to Transform
components called ease_to
. ease_to
creates a new component that the bevy_easings
plugin systems can handle to ease our tiles across the screen. ease_to
takes three arguments: the final Transform
position, an easing function and an easing type.
The easing function defines how we interpolate between the original position and the final position of the tile. It's how we pick each of the x and y positions along the way.
EasingType
gives us a way to define how many times the loop should run. The variants are Once
, Loop
, and PingPong
. In our case we want EasingType::Once
with a duration of 100ms.
for (entity, transform, pos) in tiles.iter() {
let x = board.cell_position_to_physical(pos.x);
let y = board.cell_position_to_physical(pos.y);
commands.entity(entity).insert(transform.ease_to(
Transform::from_xyz(
x,
y,
transform.translation.z,
),
EaseFunction::QuadraticInOut,
EasingType::Once {
duration: std::time::Duration::from_millis(
100,
),
},
));
and now when we run our game, any tile that already exists on the board will get animated into it's new location when a board shift happens.