|
|
|
@ -1,8 +1,8 @@
|
|
|
|
// Bevy basically forces "complex types" with Querys
|
|
|
|
// Bevy basically forces "complex types" with Querys
|
|
|
|
#![allow(clippy::type_complexity)]
|
|
|
|
#![allow(clippy::type_complexity)]
|
|
|
|
|
|
|
|
|
|
|
|
use bevy::audio::PlaybackMode;
|
|
|
|
|
|
|
|
use bevy::image::{ImageLoaderSettings, ImageSampler};
|
|
|
|
use bevy::image::{ImageLoaderSettings, ImageSampler};
|
|
|
|
|
|
|
|
use bevy::platform::time::Instant;
|
|
|
|
use bevy::render::view::ColorGrading;
|
|
|
|
use bevy::render::view::ColorGrading;
|
|
|
|
use games::physics2d::*;
|
|
|
|
use games::physics2d::*;
|
|
|
|
use games::*;
|
|
|
|
use games::*;
|
|
|
|
@ -15,6 +15,8 @@ fn main() {
|
|
|
|
title: "flappy bird (with rewind)".into(),
|
|
|
|
title: "flappy bird (with rewind)".into(),
|
|
|
|
name: "flappy".into(),
|
|
|
|
name: "flappy".into(),
|
|
|
|
game_type: GameType::Two,
|
|
|
|
game_type: GameType::Two,
|
|
|
|
|
|
|
|
target_resolution: (360.0, 640.0).into(),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Physics2dPlugin,
|
|
|
|
Physics2dPlugin,
|
|
|
|
))
|
|
|
|
))
|
|
|
|
@ -27,6 +29,7 @@ fn main() {
|
|
|
|
.init_resource::<RewindFrames>()
|
|
|
|
.init_resource::<RewindFrames>()
|
|
|
|
.init_resource::<Flaps>()
|
|
|
|
.init_resource::<Flaps>()
|
|
|
|
.init_resource::<Deaths>()
|
|
|
|
.init_resource::<Deaths>()
|
|
|
|
|
|
|
|
.init_resource::<LongestRun>()
|
|
|
|
.init_state::<PlayerState>()
|
|
|
|
.init_state::<PlayerState>()
|
|
|
|
.add_systems(
|
|
|
|
.add_systems(
|
|
|
|
Startup,
|
|
|
|
Startup,
|
|
|
|
@ -40,9 +43,12 @@ fn main() {
|
|
|
|
tweak_camera.after(create_camera_2d),
|
|
|
|
tweak_camera.after(create_camera_2d),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.add_systems(OnEnter(PlayerState::Alive), alive_bird)
|
|
|
|
.add_systems(
|
|
|
|
.add_systems(OnEnter(PlayerState::Alive), reset_button::<FlapButton>)
|
|
|
|
OnEnter(PlayerState::Alive),
|
|
|
|
.add_systems(OnEnter(PlayerState::Rewind), (start_rewinding, alive_bird))
|
|
|
|
(alive_bird, start_run, reset_button::<FlapButton>),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.add_systems(OnExit(PlayerState::Alive), end_run)
|
|
|
|
|
|
|
|
.add_systems(OnEnter(PlayerState::Rewind), alive_bird)
|
|
|
|
.add_systems(OnEnter(PlayerState::Pause), pause_bird)
|
|
|
|
.add_systems(OnEnter(PlayerState::Pause), pause_bird)
|
|
|
|
.add_systems(OnEnter(PlayerState::Stasis), pause_bird)
|
|
|
|
.add_systems(OnEnter(PlayerState::Stasis), pause_bird)
|
|
|
|
.add_systems(OnExit(PlayerState::Stasis), reset_button::<RewindButton>)
|
|
|
|
.add_systems(OnExit(PlayerState::Stasis), reset_button::<RewindButton>)
|
|
|
|
@ -85,8 +91,9 @@ fn main() {
|
|
|
|
// Stats that get synced to the UI
|
|
|
|
// Stats that get synced to the UI
|
|
|
|
(
|
|
|
|
(
|
|
|
|
sync_resource_to_ui::<Score>.run_if(resource_changed::<Score>),
|
|
|
|
sync_resource_to_ui::<Score>.run_if(resource_changed::<Score>),
|
|
|
|
sync_resource_to_ui::<Flaps>.run_if(resource_changed::<Flaps>),
|
|
|
|
sync_resource_to_ui::<LongestRun>.run_if(resource_changed::<LongestRun>),
|
|
|
|
sync_resource_to_ui::<Deaths>.run_if(resource_changed::<Deaths>),
|
|
|
|
sync_resource_to_ui::<Deaths>.run_if(resource_changed::<Deaths>),
|
|
|
|
|
|
|
|
sync_resource_to_ui::<Flaps>.run_if(resource_changed::<Flaps>),
|
|
|
|
sync_resource_to_ui::<RewindFrames>.run_if(resource_changed::<RewindFrames>),
|
|
|
|
sync_resource_to_ui::<RewindFrames>.run_if(resource_changed::<RewindFrames>),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
(update_tooltip, debug_trail).run_if(in_state(DebuggingState::On)),
|
|
|
|
(update_tooltip, debug_trail).run_if(in_state(DebuggingState::On)),
|
|
|
|
@ -101,6 +108,7 @@ fn main() {
|
|
|
|
.add_observer(flap)
|
|
|
|
.add_observer(flap)
|
|
|
|
.add_observer(populate_batch)
|
|
|
|
.add_observer(populate_batch)
|
|
|
|
.add_observer(populate_pipe)
|
|
|
|
.add_observer(populate_pipe)
|
|
|
|
|
|
|
|
.add_observer(move_pipe)
|
|
|
|
.add_observer(populate_ground)
|
|
|
|
.add_observer(populate_ground)
|
|
|
|
.add_observer(populate_ceiling)
|
|
|
|
.add_observer(populate_ceiling)
|
|
|
|
.add_observer(populate_hitbox)
|
|
|
|
.add_observer(populate_hitbox)
|
|
|
|
@ -110,7 +118,7 @@ fn main() {
|
|
|
|
fn tweak_camera(camera: Single<(Entity, &mut Camera)>, mut commands: Commands) {
|
|
|
|
fn tweak_camera(camera: Single<(Entity, &mut Camera)>, mut commands: Commands) {
|
|
|
|
debug!("Tweaking camera");
|
|
|
|
debug!("Tweaking camera");
|
|
|
|
let (e, mut c) = camera.into_inner();
|
|
|
|
let (e, mut c) = camera.into_inner();
|
|
|
|
c.clear_color = ClearColorConfig::Custom(DEEP_SKY_BLUE.into());
|
|
|
|
c.clear_color = ClearColorConfig::Custom(SKY_BLUE.into());
|
|
|
|
commands.entity(e).insert(ColorGrading { ..default() });
|
|
|
|
commands.entity(e).insert(ColorGrading { ..default() });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -200,11 +208,11 @@ impl Tape {
|
|
|
|
fn init_bird(mut commands: Commands, bird_assets: Res<BirdAssets>) {
|
|
|
|
fn init_bird(mut commands: Commands, bird_assets: Res<BirdAssets>) {
|
|
|
|
let name = Name::new("bird");
|
|
|
|
let name = Name::new("bird");
|
|
|
|
|
|
|
|
|
|
|
|
let t = Transform::from_xyz(0.0, 0.0, 0.0).with_scale(Vec3::splat(50.0));
|
|
|
|
let t = Transform::from_xyz(0.0, 0.0, 0.0).with_scale(Vec3::new(62.5, 50.0, 50.0));
|
|
|
|
|
|
|
|
|
|
|
|
let physics = (
|
|
|
|
let physics = (
|
|
|
|
RigidBody::Static,
|
|
|
|
RigidBody::Static,
|
|
|
|
Collider::rectangle(1.0, 1.2),
|
|
|
|
Collider::rectangle(1.0, 1.0),
|
|
|
|
Mass(10.0),
|
|
|
|
Mass(10.0),
|
|
|
|
ExternalImpulse::default().with_persistence(false),
|
|
|
|
ExternalImpulse::default().with_persistence(false),
|
|
|
|
MaxLinearSpeed(500.0),
|
|
|
|
MaxLinearSpeed(500.0),
|
|
|
|
@ -317,8 +325,8 @@ fn populate_ground(
|
|
|
|
ground_assets.mesh.clone(),
|
|
|
|
ground_assets.mesh.clone(),
|
|
|
|
Name::new("ground"),
|
|
|
|
Name::new("ground"),
|
|
|
|
RigidBody::Static,
|
|
|
|
RigidBody::Static,
|
|
|
|
Collider::rectangle(1.0, 1.0),
|
|
|
|
Collider::rectangle(1.0, 0.75),
|
|
|
|
Transform::from_xyz(100.0 * (*idx) as f32, -300.0, -1.0).with_scale(Vec3::splat(100.0)),
|
|
|
|
Transform::from_xyz(100.0 * (*idx) as f32, -275.0, -1.0).with_scale(Vec3::splat(100.0)),
|
|
|
|
));
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -335,23 +343,53 @@ fn populate_ceiling(
|
|
|
|
ceiling_assets.mesh.clone(),
|
|
|
|
ceiling_assets.mesh.clone(),
|
|
|
|
Name::new("ceiling"),
|
|
|
|
Name::new("ceiling"),
|
|
|
|
RigidBody::Static,
|
|
|
|
RigidBody::Static,
|
|
|
|
Collider::rectangle(1.0, 1.0),
|
|
|
|
Collider::rectangle(1.0, 0.75),
|
|
|
|
Transform::from_xyz(100.0 * (*idx) as f32, 300.0, -3.0).with_scale(Vec3::splat(100.0)),
|
|
|
|
Transform::from_xyz(100.0 * (*idx) as f32, 300.0, -3.0).with_scale(Vec3::splat(100.0)),
|
|
|
|
));
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn move_pipe(
|
|
|
|
|
|
|
|
trigger: Trigger<OnInsert, Batch>,
|
|
|
|
|
|
|
|
mut pipes: Query<(&Batch, &Pipe, &mut Transform)>,
|
|
|
|
|
|
|
|
rand: Res<Rand>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
if let Ok((Batch(id), pipe, mut pipe_t)) = pipes.get_mut(trigger.target()) {
|
|
|
|
|
|
|
|
*pipe_t =
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let offset = {
|
|
|
|
|
|
|
|
let val = rand.0.hash_one(id);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let option = val % 3;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match option {
|
|
|
|
|
|
|
|
0 => 100.0,
|
|
|
|
|
|
|
|
1 => 0.0,
|
|
|
|
|
|
|
|
2 => -100.0,
|
|
|
|
|
|
|
|
_ => panic!("Can only pick 1 of 3 pipe offsets"),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match pipe {
|
|
|
|
|
|
|
|
Pipe::Top => Transform::from_xyz(0.0, 300.0 + offset, -2.0)
|
|
|
|
|
|
|
|
.with_scale(Vec3::splat(100.0)),
|
|
|
|
|
|
|
|
Pipe::Bottom => Transform::from_xyz(0.0, -300.0 + offset, -2.0)
|
|
|
|
|
|
|
|
.with_scale(Vec3::splat(100.0)),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Based on if this is a Top or Bottom pipe the placement changes
|
|
|
|
/// Based on if this is a Top or Bottom pipe the placement changes
|
|
|
|
/// Otherwise this just spawns in the center of the batch.
|
|
|
|
/// Otherwise this just spawns in the center of the batch.
|
|
|
|
fn populate_pipe(
|
|
|
|
fn populate_pipe(
|
|
|
|
trigger: Trigger<OnAdd, Pipe>,
|
|
|
|
trigger: Trigger<OnAdd, Pipe>,
|
|
|
|
pipes: Query<(&Pipe, &Batch)>,
|
|
|
|
pipes: Query<(&Batch, &Pipe)>,
|
|
|
|
pipe_assets: Res<PipeAssets>,
|
|
|
|
pipe_assets: Res<PipeAssets>,
|
|
|
|
mut commands: Commands,
|
|
|
|
mut commands: Commands,
|
|
|
|
rand: Res<Rand>,
|
|
|
|
rand: Res<Rand>,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
let pipe_t = {
|
|
|
|
let pipe_t = {
|
|
|
|
let (pipe, Batch(id)) = pipes.get(trigger.target()).unwrap();
|
|
|
|
let (Batch(id), pipe) = pipes.get(trigger.target()).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
let offset = {
|
|
|
|
let offset = {
|
|
|
|
let val = rand.0.hash_one(id);
|
|
|
|
let val = rand.0.hash_one(id);
|
|
|
|
|
|
|
|
|
|
|
|
@ -374,6 +412,7 @@ fn populate_pipe(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
commands.entity(trigger.target()).insert((
|
|
|
|
commands.entity(trigger.target()).insert((
|
|
|
|
pipe_t,
|
|
|
|
pipe_t,
|
|
|
|
pipe_assets.material.clone(),
|
|
|
|
pipe_assets.material.clone(),
|
|
|
|
@ -440,14 +479,14 @@ fn init_assets(
|
|
|
|
|
|
|
|
|
|
|
|
ground_assets.material = MeshMaterial2d(materials.add(ColorMaterial {
|
|
|
|
ground_assets.material = MeshMaterial2d(materials.add(ColorMaterial {
|
|
|
|
texture: Some(server.load("flappy/ground.png")),
|
|
|
|
texture: Some(server.load("flappy/ground.png")),
|
|
|
|
color: Srgba::new(0.9, 0.9, 0.9, 1.0).into(),
|
|
|
|
color: GREEN.into(),
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
}));
|
|
|
|
}));
|
|
|
|
ground_assets.mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0)));
|
|
|
|
ground_assets.mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0)));
|
|
|
|
|
|
|
|
|
|
|
|
ceiling_assets.material = MeshMaterial2d(materials.add(ColorMaterial {
|
|
|
|
ceiling_assets.material = MeshMaterial2d(materials.add(ColorMaterial {
|
|
|
|
texture: Some(server.load("flappy/ceiling.png")),
|
|
|
|
texture: Some(server.load("flappy/ceiling.png")),
|
|
|
|
color: Srgba::new(0.9, 0.9, 0.9, 1.0).into(),
|
|
|
|
color: FIRE_BRICK.into(),
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
}));
|
|
|
|
}));
|
|
|
|
ceiling_assets.mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 0.777)));
|
|
|
|
ceiling_assets.mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 0.777)));
|
|
|
|
@ -461,18 +500,9 @@ fn init_assets(
|
|
|
|
bird_assets.mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.2)));
|
|
|
|
bird_assets.mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.2)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Component)]
|
|
|
|
|
|
|
|
struct FlapSfx;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Component)]
|
|
|
|
#[derive(Component)]
|
|
|
|
struct FlapButton;
|
|
|
|
struct FlapButton;
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Component)]
|
|
|
|
|
|
|
|
struct BonkSfx;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Component)]
|
|
|
|
|
|
|
|
struct RewindSfx;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Component)]
|
|
|
|
#[derive(Component)]
|
|
|
|
struct RewindButton;
|
|
|
|
struct RewindButton;
|
|
|
|
|
|
|
|
|
|
|
|
@ -485,35 +515,50 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
BorderRadius::all(Val::Px(5.0)),
|
|
|
|
|
|
|
|
BackgroundColor(Color::WHITE),
|
|
|
|
|
|
|
|
BorderColor(BLACK.into()),
|
|
|
|
PlayerState::Stasis,
|
|
|
|
PlayerState::Stasis,
|
|
|
|
))
|
|
|
|
))
|
|
|
|
.with_children(|parent| {
|
|
|
|
.with_children(|parent| {
|
|
|
|
parent.spawn((
|
|
|
|
parent.spawn((
|
|
|
|
Text::new("Game Over...?"),
|
|
|
|
Text::new("Game Over...?"),
|
|
|
|
|
|
|
|
TextColor(BLACK.into()),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
));
|
|
|
|
));
|
|
|
|
parent.spawn((
|
|
|
|
parent.spawn((
|
|
|
|
SyncResource::<Score>::default(),
|
|
|
|
SyncResource::<Score>::default(),
|
|
|
|
Text::default(),
|
|
|
|
Text::default(),
|
|
|
|
|
|
|
|
TextColor(BLACK.into()),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
));
|
|
|
|
));
|
|
|
|
parent.spawn((
|
|
|
|
parent.spawn((
|
|
|
|
SyncResource::<Flaps>::default(),
|
|
|
|
SyncResource::<LongestRun>::default(),
|
|
|
|
Text::default(),
|
|
|
|
Text::default(),
|
|
|
|
|
|
|
|
TextColor(BLACK.into()),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
));
|
|
|
|
));
|
|
|
|
parent.spawn((
|
|
|
|
parent.spawn((
|
|
|
|
SyncResource::<RewindFrames>::default(),
|
|
|
|
SyncResource::<Deaths>::default(),
|
|
|
|
Text::default(),
|
|
|
|
Text::default(),
|
|
|
|
|
|
|
|
TextColor(BLACK.into()),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
));
|
|
|
|
));
|
|
|
|
parent.spawn((
|
|
|
|
parent.spawn((
|
|
|
|
SyncResource::<Deaths>::default(),
|
|
|
|
SyncResource::<Flaps>::default(),
|
|
|
|
|
|
|
|
Text::default(),
|
|
|
|
|
|
|
|
TextColor(BLACK.into()),
|
|
|
|
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
parent.spawn((
|
|
|
|
|
|
|
|
SyncResource::<RewindFrames>::default(),
|
|
|
|
Text::default(),
|
|
|
|
Text::default(),
|
|
|
|
|
|
|
|
TextColor(BLACK.into()),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
));
|
|
|
|
));
|
|
|
|
parent.spawn((
|
|
|
|
parent.spawn((
|
|
|
|
Text::new("Press R to Rewind"),
|
|
|
|
Text::new("Press R to Rewind"),
|
|
|
|
|
|
|
|
TextColor(BLACK.into()),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
));
|
|
|
|
));
|
|
|
|
parent
|
|
|
|
parent
|
|
|
|
@ -523,14 +568,6 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},))
|
|
|
|
},))
|
|
|
|
.with_children(|parent| {
|
|
|
|
.with_children(|parent| {
|
|
|
|
fn quit_game(
|
|
|
|
|
|
|
|
_trigger: Trigger<Pointer<Click>>,
|
|
|
|
|
|
|
|
mut exit: EventWriter<AppExit>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
warn!("Quitting game");
|
|
|
|
|
|
|
|
exit.write(AppExit::Success);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn show_credits(
|
|
|
|
fn show_credits(
|
|
|
|
_trigger: Trigger<Pointer<Click>>,
|
|
|
|
_trigger: Trigger<Pointer<Click>>,
|
|
|
|
mut state: ResMut<NextState<PlayerState>>,
|
|
|
|
mut state: ResMut<NextState<PlayerState>>,
|
|
|
|
@ -541,13 +578,33 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
|
|
|
|
parent
|
|
|
|
parent
|
|
|
|
.spawn((
|
|
|
|
.spawn((
|
|
|
|
Button,
|
|
|
|
Button,
|
|
|
|
|
|
|
|
BorderRadius::all(Val::Px(5.0)),
|
|
|
|
|
|
|
|
BorderColor(BLACK.into()),
|
|
|
|
Node { ..default() },
|
|
|
|
Node { ..default() },
|
|
|
|
children![Text::new("Credits")],
|
|
|
|
children![(TextColor(BLACK.into()), Text::new("Credits")),],
|
|
|
|
))
|
|
|
|
))
|
|
|
|
.observe(show_credits);
|
|
|
|
.observe(show_credits);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
fn quit_game(
|
|
|
|
|
|
|
|
_trigger: Trigger<Pointer<Click>>,
|
|
|
|
|
|
|
|
mut exit: EventWriter<AppExit>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
warn!("Quitting game");
|
|
|
|
|
|
|
|
exit.write(AppExit::Success);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
parent
|
|
|
|
parent
|
|
|
|
.spawn((Button, Node { ..default() }, children![Text::new("Quit"),]))
|
|
|
|
.spawn((
|
|
|
|
|
|
|
|
BorderRadius::all(Val::Px(5.0)),
|
|
|
|
|
|
|
|
BorderColor(BLACK.into()),
|
|
|
|
|
|
|
|
Button,
|
|
|
|
|
|
|
|
Node { ..default() },
|
|
|
|
|
|
|
|
children![(Text::new("Quit"), TextColor(BLACK.into()))],
|
|
|
|
|
|
|
|
))
|
|
|
|
.observe(quit_game);
|
|
|
|
.observe(quit_game);
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
@ -565,9 +622,13 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
BorderRadius::all(Val::Px(5.0)),
|
|
|
|
|
|
|
|
BackgroundColor(WHITE.into()),
|
|
|
|
|
|
|
|
BorderColor(BLACK.into()),
|
|
|
|
PlayerState::Credits,
|
|
|
|
PlayerState::Credits,
|
|
|
|
children![(
|
|
|
|
children![(
|
|
|
|
Text::new(credits_str),
|
|
|
|
Text::new(credits_str),
|
|
|
|
|
|
|
|
TextColor(BLACK.into()),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center)
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center)
|
|
|
|
)],
|
|
|
|
)],
|
|
|
|
))
|
|
|
|
))
|
|
|
|
@ -577,25 +638,56 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
|
|
|
|
align_self: AlignSelf::Center,
|
|
|
|
align_self: AlignSelf::Center,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
BorderRadius::all(Val::Px(5.0)),
|
|
|
|
|
|
|
|
BorderColor(BLACK.into()),
|
|
|
|
Button,
|
|
|
|
Button,
|
|
|
|
children![Text::new("Close")],
|
|
|
|
children![(Text::new("Close"), TextColor(BLACK.into()))],
|
|
|
|
));
|
|
|
|
));
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.observe(hide_credits);
|
|
|
|
.observe(hide_credits);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let logo =
|
|
|
|
|
|
|
|
server.load_with_settings("flappy/logo.png", |settings: &mut ImageLoaderSettings| {
|
|
|
|
|
|
|
|
// Need to use nearest filtering to avoid bleeding between the slices with tiling
|
|
|
|
|
|
|
|
settings.sampler = ImageSampler::nearest();
|
|
|
|
|
|
|
|
});
|
|
|
|
commands.spawn((
|
|
|
|
commands.spawn((
|
|
|
|
Node {
|
|
|
|
Node {
|
|
|
|
align_self: AlignSelf::Center,
|
|
|
|
align_self: AlignSelf::Center,
|
|
|
|
justify_self: JustifySelf::Center,
|
|
|
|
justify_self: JustifySelf::Center,
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
|
|
|
|
align_items: AlignItems::Center,
|
|
|
|
|
|
|
|
justify_items: JustifyItems::Center,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
BackgroundColor(Color::NONE),
|
|
|
|
PlayerState::Pause,
|
|
|
|
PlayerState::Pause,
|
|
|
|
Text::new("PAUSED"),
|
|
|
|
children![
|
|
|
|
|
|
|
|
(
|
|
|
|
|
|
|
|
ImageNode {
|
|
|
|
|
|
|
|
image: logo,
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
Node {
|
|
|
|
|
|
|
|
width: Val::Px(256.0),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
(
|
|
|
|
|
|
|
|
Node {
|
|
|
|
|
|
|
|
margin: UiRect::all(Val::Px(5.0)),
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
BorderRadius::all(Val::Px(5.0)),
|
|
|
|
|
|
|
|
BorderColor(BLACK.into()),
|
|
|
|
|
|
|
|
Text::new("(paused)"),
|
|
|
|
|
|
|
|
TextColor(BLACK.into()),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
],
|
|
|
|
));
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
commands
|
|
|
|
commands
|
|
|
|
.spawn(Node {
|
|
|
|
.spawn((Node {
|
|
|
|
align_self: AlignSelf::End,
|
|
|
|
align_self: AlignSelf::End,
|
|
|
|
justify_self: JustifySelf::Center,
|
|
|
|
justify_self: JustifySelf::Center,
|
|
|
|
flex_direction: FlexDirection::Row,
|
|
|
|
flex_direction: FlexDirection::Row,
|
|
|
|
@ -603,7 +695,7 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
width: Val::Percent(100.0),
|
|
|
|
min_height: Val::Percent(10.0),
|
|
|
|
min_height: Val::Percent(10.0),
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
})
|
|
|
|
},))
|
|
|
|
.with_children(|parent| {
|
|
|
|
.with_children(|parent| {
|
|
|
|
let rewind_image = server.load_with_settings(
|
|
|
|
let rewind_image = server.load_with_settings(
|
|
|
|
"flappy/rewind.png",
|
|
|
|
"flappy/rewind.png",
|
|
|
|
@ -621,8 +713,10 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
|
|
|
|
justify_content: JustifyContent::Center,
|
|
|
|
justify_content: JustifyContent::Center,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
BorderRadius::all(Val::Px(5.0)),
|
|
|
|
|
|
|
|
BorderColor(BLACK.into()),
|
|
|
|
|
|
|
|
BackgroundColor(Color::WHITE.with_alpha(0.9)),
|
|
|
|
Button,
|
|
|
|
Button,
|
|
|
|
BackgroundColor::default(),
|
|
|
|
|
|
|
|
RewindButton,
|
|
|
|
RewindButton,
|
|
|
|
children![
|
|
|
|
children![
|
|
|
|
(
|
|
|
|
(
|
|
|
|
@ -637,8 +731,9 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
),
|
|
|
|
),
|
|
|
|
(
|
|
|
|
(
|
|
|
|
Text::new("Rewind! (R)"),
|
|
|
|
Text::new("Rewind!\n(Hold R)"),
|
|
|
|
TextFont::from_font_size(30.0),
|
|
|
|
TextColor(BLACK.into()),
|
|
|
|
|
|
|
|
TextFont::from_font_size(20.0),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center)
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center)
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
],
|
|
|
|
@ -661,12 +756,16 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
|
|
|
|
justify_content: JustifyContent::Center,
|
|
|
|
justify_content: JustifyContent::Center,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
BorderRadius::all(Val::Px(5.0)),
|
|
|
|
|
|
|
|
BorderColor(BLACK.into()),
|
|
|
|
|
|
|
|
BackgroundColor(Color::WHITE.with_alpha(0.9)),
|
|
|
|
Button,
|
|
|
|
Button,
|
|
|
|
FlapButton,
|
|
|
|
FlapButton,
|
|
|
|
children![
|
|
|
|
children![
|
|
|
|
(
|
|
|
|
(
|
|
|
|
Text::new("Flap! (Spacebar)"),
|
|
|
|
Text::new("Flap!\n(Spacebar)"),
|
|
|
|
TextFont::from_font_size(30.0),
|
|
|
|
TextColor(BLACK.into()),
|
|
|
|
|
|
|
|
TextFont::from_font_size(20.0),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center)
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center)
|
|
|
|
),
|
|
|
|
),
|
|
|
|
(
|
|
|
|
(
|
|
|
|
@ -691,10 +790,13 @@ fn init_ui(mut commands: Commands, server: Res<AssetServer>) {
|
|
|
|
justify_self: JustifySelf::Center,
|
|
|
|
justify_self: JustifySelf::Center,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
BackgroundColor(WHITE.into()),
|
|
|
|
BorderRadius::all(Val::Px(5.0)),
|
|
|
|
|
|
|
|
BackgroundColor(Color::WHITE),
|
|
|
|
|
|
|
|
BorderColor(BLACK.into()),
|
|
|
|
children![(
|
|
|
|
children![(
|
|
|
|
SyncResource::<Score>::default(),
|
|
|
|
SyncResource::<Score>::default(),
|
|
|
|
Text::default(),
|
|
|
|
Text::default(),
|
|
|
|
|
|
|
|
TextColor(BLACK.into()),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
TextLayout::new_with_justify(JustifyText::Center),
|
|
|
|
)],
|
|
|
|
)],
|
|
|
|
));
|
|
|
|
));
|
|
|
|
@ -709,36 +811,36 @@ fn init_background(
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let material = MeshMaterial2d(materials.add(ColorMaterial {
|
|
|
|
let material = MeshMaterial2d(materials.add(ColorMaterial {
|
|
|
|
texture: Some(server.load("flappy/background-city.png")),
|
|
|
|
texture: Some(server.load("flappy/background-city.png")),
|
|
|
|
color: Srgba::new(0.3, 0.3, 0.3, 1.0).into(),
|
|
|
|
color: LIGHT_GREY.with_alpha(0.8).into(),
|
|
|
|
alpha_mode: AlphaMode2d::Blend,
|
|
|
|
alpha_mode: AlphaMode2d::Blend,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
}));
|
|
|
|
}));
|
|
|
|
let mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0)));
|
|
|
|
let mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0)));
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let t = Transform::from_xyz(-325.0, 0.0, -32.0).with_scale(Vec3::splat(650.0));
|
|
|
|
let t = Transform::from_xyz(-325.0, 0.0, -32.0).with_scale(Vec3::splat(650.0));
|
|
|
|
commands.spawn((ParallaxDepth(4.0), mesh.clone(), material.clone(), t));
|
|
|
|
commands.spawn((ParallaxDepth(24.0), mesh.clone(), material.clone(), t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let t = Transform::from_xyz(325.0, 0.0, -32.0).with_scale(Vec3::splat(650.0));
|
|
|
|
let t = Transform::from_xyz(325.0, 0.0, -32.0).with_scale(Vec3::splat(650.0));
|
|
|
|
commands.spawn((ParallaxDepth(4.0), mesh.clone(), material.clone(), t));
|
|
|
|
commands.spawn((ParallaxDepth(24.0), mesh.clone(), material.clone(), t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let material = MeshMaterial2d(materials.add(ColorMaterial {
|
|
|
|
let material = MeshMaterial2d(materials.add(ColorMaterial {
|
|
|
|
texture: Some(server.load("flappy/background-clouds.png")),
|
|
|
|
texture: Some(server.load("flappy/background-clouds.png")),
|
|
|
|
color: Srgba::new(0.2, 0.2, 0.2, 1.0).into(),
|
|
|
|
color: WHITE_SMOKE.with_alpha(0.8).into(),
|
|
|
|
alpha_mode: AlphaMode2d::Blend,
|
|
|
|
alpha_mode: AlphaMode2d::Blend,
|
|
|
|
..default()
|
|
|
|
..default()
|
|
|
|
}));
|
|
|
|
}));
|
|
|
|
let mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0)));
|
|
|
|
let mesh = Mesh2d(meshes.add(Rectangle::new(1.0, 1.0)));
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let t = Transform::from_xyz(-325.0, 0.0, -64.0).with_scale(Vec3::splat(650.0));
|
|
|
|
let t = Transform::from_xyz(-325.0, 0.0, -64.0).with_scale(Vec3::splat(650.0));
|
|
|
|
commands.spawn((ParallaxDepth(8.0), mesh.clone(), material.clone(), t));
|
|
|
|
commands.spawn((ParallaxDepth(32.0), mesh.clone(), material.clone(), t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let t = Transform::from_xyz(325.0, 0.0, -64.0).with_scale(Vec3::splat(650.0));
|
|
|
|
let t = Transform::from_xyz(325.0, 0.0, -64.0).with_scale(Vec3::splat(650.0));
|
|
|
|
commands.spawn((ParallaxDepth(8.0), mesh.clone(), material.clone(), t));
|
|
|
|
commands.spawn((ParallaxDepth(32.0), mesh.clone(), material.clone(), t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -783,8 +885,6 @@ fn flap(
|
|
|
|
trigger: Trigger<Flap>,
|
|
|
|
trigger: Trigger<Flap>,
|
|
|
|
mut bird: Query<&mut ExternalImpulse, With<Bird>>,
|
|
|
|
mut bird: Query<&mut ExternalImpulse, With<Bird>>,
|
|
|
|
mut flaps: ResMut<Flaps>,
|
|
|
|
mut flaps: ResMut<Flaps>,
|
|
|
|
server: ResMut<AssetServer>,
|
|
|
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
debug!("real flap for {:?}", trigger.target());
|
|
|
|
debug!("real flap for {:?}", trigger.target());
|
|
|
|
// Increment flap stat
|
|
|
|
// Increment flap stat
|
|
|
|
@ -793,16 +893,6 @@ fn flap(
|
|
|
|
// Flap birds wings
|
|
|
|
// Flap birds wings
|
|
|
|
if let Ok(mut f) = bird.get_mut(trigger.target()) {
|
|
|
|
if let Ok(mut f) = bird.get_mut(trigger.target()) {
|
|
|
|
f.apply_impulse(Vec2::Y * 5000.0 + Vec2::X * 1000.0);
|
|
|
|
f.apply_impulse(Vec2::Y * 5000.0 + Vec2::X * 1000.0);
|
|
|
|
|
|
|
|
|
|
|
|
// Play flap sfx
|
|
|
|
|
|
|
|
commands.spawn((
|
|
|
|
|
|
|
|
AudioPlayer::new(server.load("flappy/bonk.ogg")),
|
|
|
|
|
|
|
|
PlaybackSettings {
|
|
|
|
|
|
|
|
mode: PlaybackMode::Despawn,
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
BonkSfx,
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -914,8 +1004,6 @@ fn detect_dead(
|
|
|
|
bird: Single<&ColliderAabb, With<Bird>>,
|
|
|
|
bird: Single<&ColliderAabb, With<Bird>>,
|
|
|
|
obstacles: Query<&ColliderAabb, Or<(With<Ground>, With<Pipe>, With<Ceiling>)>>,
|
|
|
|
obstacles: Query<&ColliderAabb, Or<(With<Ground>, With<Pipe>, With<Ceiling>)>>,
|
|
|
|
mut next: ResMut<NextState<PlayerState>>,
|
|
|
|
mut next: ResMut<NextState<PlayerState>>,
|
|
|
|
server: ResMut<AssetServer>,
|
|
|
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
#[cfg(debug_assertions)]
|
|
|
|
#[cfg(debug_assertions)]
|
|
|
|
debug_assert!(
|
|
|
|
debug_assert!(
|
|
|
|
@ -925,16 +1013,6 @@ fn detect_dead(
|
|
|
|
|
|
|
|
|
|
|
|
if obstacles.iter().any(|obstacle| bird.intersects(obstacle)) {
|
|
|
|
if obstacles.iter().any(|obstacle| bird.intersects(obstacle)) {
|
|
|
|
next.set(PlayerState::Stasis);
|
|
|
|
next.set(PlayerState::Stasis);
|
|
|
|
|
|
|
|
|
|
|
|
// Play bonk sfx
|
|
|
|
|
|
|
|
commands.spawn((
|
|
|
|
|
|
|
|
AudioPlayer::new(server.load("flappy/flap.ogg")),
|
|
|
|
|
|
|
|
PlaybackSettings {
|
|
|
|
|
|
|
|
mode: PlaybackMode::Despawn,
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
FlapSfx,
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -994,6 +1072,61 @@ impl Display for Flaps {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Track the longest run a player has done
|
|
|
|
|
|
|
|
/// Store the latest run and upsert latest run to the longest run if it is longer
|
|
|
|
|
|
|
|
#[derive(Resource, Default)]
|
|
|
|
|
|
|
|
struct LongestRun {
|
|
|
|
|
|
|
|
/// Longest run start
|
|
|
|
|
|
|
|
start: Option<Instant>,
|
|
|
|
|
|
|
|
/// Longest run end
|
|
|
|
|
|
|
|
end: Option<Instant>,
|
|
|
|
|
|
|
|
/// Latest run start
|
|
|
|
|
|
|
|
latest_start: Option<Instant>,
|
|
|
|
|
|
|
|
/// Latest run start
|
|
|
|
|
|
|
|
latest_end: Option<Instant>,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Display for LongestRun {
|
|
|
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
|
|
|
|
|
|
match (self.start, self.end) {
|
|
|
|
|
|
|
|
(Some(a), Some(b)) => {
|
|
|
|
|
|
|
|
if b > a {
|
|
|
|
|
|
|
|
writeln!(f, "Longest Run: {:.2?}", b - a)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
writeln!(f, "Longest Run: ???")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
_ => writeln!(f, "Longest Run: ???"),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn start_run(mut longest_run: ResMut<LongestRun>) {
|
|
|
|
|
|
|
|
longest_run.latest_start = Some(Instant::now());
|
|
|
|
|
|
|
|
longest_run.latest_end = None;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn end_run(mut longest_run: ResMut<LongestRun>) {
|
|
|
|
|
|
|
|
longest_run.latest_end = Some(Instant::now());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match (longest_run.start, longest_run.end) {
|
|
|
|
|
|
|
|
// Longest run hasn't been set yet, so set it to the latest run
|
|
|
|
|
|
|
|
(None, None) => {
|
|
|
|
|
|
|
|
longest_run.start = longest_run.latest_start;
|
|
|
|
|
|
|
|
longest_run.end = longest_run.latest_end;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Longest run was previously set
|
|
|
|
|
|
|
|
(Some(start), Some(end)) => {
|
|
|
|
|
|
|
|
// Check if latest run is longer than current longest run
|
|
|
|
|
|
|
|
if longest_run.latest_end.unwrap() - longest_run.latest_start.unwrap() > end - start {
|
|
|
|
|
|
|
|
longest_run.start = longest_run.latest_start;
|
|
|
|
|
|
|
|
longest_run.end = longest_run.latest_end;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
_ => panic!("What?"),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Track number of times player died
|
|
|
|
// Track number of times player died
|
|
|
|
#[derive(Resource, Default)]
|
|
|
|
#[derive(Resource, Default)]
|
|
|
|
struct Deaths(usize);
|
|
|
|
struct Deaths(usize);
|
|
|
|
@ -1140,24 +1273,16 @@ fn debug_trail(
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn start_rewinding(server: ResMut<AssetServer>, mut commands: Commands) {
|
|
|
|
|
|
|
|
commands.spawn((
|
|
|
|
|
|
|
|
AudioPlayer::new(server.load("flappy/rewind-start.ogg")),
|
|
|
|
|
|
|
|
PlaybackSettings {
|
|
|
|
|
|
|
|
mode: PlaybackMode::Despawn,
|
|
|
|
|
|
|
|
..default()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
RewindSfx,
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn shimmer_button<T: Component>(mut bg: Single<&mut BackgroundColor, With<T>>, time: Res<Time>) {
|
|
|
|
fn shimmer_button<T: Component>(mut bg: Single<&mut BackgroundColor, With<T>>, time: Res<Time>) {
|
|
|
|
let t = time.elapsed_secs();
|
|
|
|
let t = time.elapsed_secs();
|
|
|
|
let period = 3.0;
|
|
|
|
let lightness = 0.5;
|
|
|
|
let r = (((t / period) % 1.0) * std::f32::consts::PI).cos();
|
|
|
|
let chroma = 0.5;
|
|
|
|
let g = ((((t / period) + 0.3) % 1.0) * std::f32::consts::PI).cos();
|
|
|
|
let hue = (t * 60.0) % 360.0;
|
|
|
|
let b = ((((t / period) + 0.6) % 1.0) * std::f32::consts::PI).cos();
|
|
|
|
bg.0 = Oklcha {
|
|
|
|
bg.0 = Srgba::rgb(r, g, b).into();
|
|
|
|
lightness, chroma, hue,
|
|
|
|
|
|
|
|
alpha: bg.0.alpha(),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.into();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn reset_button<T: Component>(mut bg: Single<&mut BackgroundColor, With<T>>) {
|
|
|
|
fn reset_button<T: Component>(mut bg: Single<&mut BackgroundColor, With<T>>) {
|
|
|
|
|