Cleanup and Polish
And that’s Flappy Bird!
Let’s finish off the application.
Turn the Gizmos off if you haven’t already in startup.
let (config, _) = config_store
.config_mut::<DefaultGizmoConfigGroup>();
config.enabled = false;
And we can make the gap invisible by setting Visibility::Hidden on it.
(
Visibility::Hidden,
Sprite {
color: Color::WHITE,
custom_size: Some(Vec2::new(
10.0, GAP_SIZE,
)),
..default()
},
Transform::from_xyz(
0.0,
gap_y_position,
1.0,
),
PointsGate,
),
Moving the Pipes Vertically
The pipes in Flappy Bird are supposed to be in different positions. This can be accomplished more effectively using noise, but we’ll start off with just a sin wave.
Add the Time resource to spawn_pipes.
fn spawn_pipes(
mut commands: Commands,
asset_server: Res<AssetServer>,
time: Res<Time>,
) { ... }
and use it to produce a sine wave. I multiply it here by an arbitrary number so that the output doesn’t look exactly periodic like a sine wave. The .sin function returns a value between -1 and 1, so multiplying that by one quarter of our CANVAS_SIZE height means it will move up and down a total of half the size of the canvas.
let gap_y_position = (time.elapsed_secs() * 4.2309875)
.sin()
* CANVAS_SIZE.y
/ 4.;
Pointing the Bird
Our bird doesn’t really move much either. We can add a little life by having it point in the direction of the arc it is following. Our pretend horizontal speed is PIPE_SPEED and our vertical speed is the velocity value.
Make PIPE_SPEED pub so we can use it in main.rs.
pub const PIPE_SPEED: f32 = 200.0;
Then we’ll use that value in a new enforce_bird_direction system. This system takes advantage of the fact that the angle of a 2d vector is just… that vector. So since our x and y speeds are already relative to our bird, we consider the bird to be the velocity vector’s local Vec2::ZERO. calculated_velocity - Vec2::ZERO is calculated_velocity. So we take advantage of glam’s Vec2::to_angle function (which uses atan2 under the hood), and make that a rotation around the Z axis, which is the one coming out of our screen.
fn enforce_bird_direction(
mut player: Single<
(&mut Transform, &Velocity),
With<Player>,
>,
) {
let calculated_velocity =
Vec2::new(PIPE_SPEED, player.1.0);
player.0.rotation = Quat::from_rotation_z(
calculated_velocity.to_angle(),
);
}
Since the system is only visual, and not gameplay related, we can put it in the Update schedule.
.add_systems(
Update,
(
controls,
score_update
.run_if(resource_changed::<Score>),
enforce_bird_direction,
),
)