Log in to access Rust Adventure videos!

Lesson Details

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.