Game Dev Diary

Day 5: An enemy approaches #

Today we continue watching Shiffman to figure out how to get the enemy circle to chase us!

We continue with 1.5: Unit Vectors and 1.6 Acceleration Vectors and then we sit down to finish up our enemy_movement system

Let’s look back at where we stopped off:

fn enemy_movement(
    mut query1: Query<&mut Transform, With<Enemy>>,
    query2: Query<&Transform, With<Balloon>>,
) {
    if let Ok(balloon) = query2.get_single() {
        for mut transform in query1.iter_mut() {
            transform.translation.x -= 1.0
        }
    }
}

First thing I explain that this is where Components really get interesting! We want to create a Component for our data. We mainly have two choices, we can either create a Velocity component that is independent of another Acceleration Component or we can put them both in one place. She chooses the easier route and picks the name Movement which is actually quite fitting! We create a simple Movement component with a velocity vector and an accel.

#[derive(Component)]
struct Movement {
    velocity: Vec3,
    accel: Vec3,
}

After this we move back to the system and I show A the ability to query multiple components that relate together at the same time, we update query1:

mut query1: Query<(&mut Transform, &mut Movement), (With<Enemy>, Without<Balloon>)>,

And update the loop over query1:

for (mut enemy, mut movement) in query1.iter_mut() {

And here I leave A to pilot for a bit on her own, to try to figure out how to achieve what Shiffman achieved in his last video.

She remembers how to access data from a struct as it’s what she does to access translation from from a Transform. However, she struggles a little to remember the formulas Shiffman explained. Should have written them down instead of being like me and rewatching the whole video again when I wanna remember any part of it… after a little bit of scrubbing through the last video and rewatching parts of it she got here:

movement.accel = balloon.translation - enemy.translation;
movement.velocity = movement.velocity + movement.accel;
enemy.translation = movement.velocity + enemy.translation;

But for whatever reason the enemy seems to move blink around as if it merged with sonic and grew a teleportation organ! It’s so blinky that we both look away because it makes us feel nauseous lol. What could be the cause?

Of course that’s exactly what Shiffman added a limit on the velocity for in his video, and we can do that too! Though one of the main reasons ours is much more blinky than his was is because Bevy runs our systems A LOT, but that’s a story for another day.

We open the Bevy Vec3 docs and go through them a bit and eventually we get to clamps, and we don’t really want to clamp the minimum so we can just use clamp_length_max:

movement.accel = balloon.translation - enemy.translation;
movement.velocity = movement.velocity + movement.accel;
movement.velocity = movement.velocity.clamp_length_max(0.69);
enemy.translation = movement.velocity + enemy.translation;

And fixes the issue! Our enemy now moves at a sane speed towards us relentlessly!

A video of two circles, one pink and one red where the pink is moving and stopping based on user input while the red one is chasing it relentlessly at a fixed velocity

And see you tomorrow! You’re beautiful 💜