119 lines
3.3 KiB
Rust
119 lines
3.3 KiB
Rust
use std::time::Duration;
|
|
|
|
use bevy::{prelude::*, utils::Instant};
|
|
use bevy_asset_loader::asset_collection::AssetCollection;
|
|
use keyframe::functions::*;
|
|
|
|
use crate::AppState;
|
|
|
|
const FADE_IN_TIME: f32 = 2.5;
|
|
const ZOOM_OUT_TIME: f32 = 2.0;
|
|
const FULL_FADE_FINISHED: f32 = 4.0;
|
|
const FADE_OUT_TIME: f32 = 1.0;
|
|
const QUIT_TIME: f32 = 0.5;
|
|
const LOGO_FINISHED_SCALE: f32 = 0.2;
|
|
|
|
pub struct LogoPlugin;
|
|
|
|
#[derive(AssetCollection, Resource)]
|
|
pub struct LogoAssets {
|
|
#[asset(path = "logo.ktx2")]
|
|
logo_texture: Handle<Image>,
|
|
}
|
|
|
|
#[derive(Resource)]
|
|
struct LogoData {
|
|
logo_entity: Entity,
|
|
camera_entity: Entity,
|
|
}
|
|
|
|
impl Plugin for LogoPlugin {
|
|
fn build(&self, app: &mut App) {
|
|
app.add_systems(OnEnter(AppState::Logo), load_logo)
|
|
.add_systems(Update, fade_in_logo.run_if(in_state(AppState::Logo)))
|
|
.add_systems(OnExit(AppState::Logo), cleanup_logo);
|
|
}
|
|
}
|
|
|
|
#[derive(Component)]
|
|
struct LogoTimer(Instant, Instant);
|
|
|
|
impl LogoTimer {
|
|
fn elapsed_secs(&self) -> f32 {
|
|
self.0.elapsed().as_secs_f32()
|
|
}
|
|
|
|
fn finished(&self) -> bool {
|
|
Instant::now() > self.1
|
|
}
|
|
}
|
|
|
|
fn load_logo(mut commands: Commands, assets: Res<LogoAssets>) {
|
|
let now = Instant::now();
|
|
commands.insert_resource(ClearColor(Color::BLACK));
|
|
let sprite_entity = commands
|
|
.spawn((
|
|
SpriteBundle {
|
|
texture: assets.logo_texture.clone(),
|
|
sprite: Sprite {
|
|
color: Color::rgba(1.0, 1.0, 1.0, 0.0),
|
|
..Default::default()
|
|
},
|
|
transform: Transform::from_scale(Vec3::ONE),
|
|
..Default::default()
|
|
},
|
|
LogoTimer(
|
|
now,
|
|
now + Duration::from_secs_f32(QUIT_TIME + FULL_FADE_FINISHED + FADE_OUT_TIME),
|
|
),
|
|
))
|
|
.id();
|
|
let camera_entity = commands.spawn(Camera2dBundle::default()).id();
|
|
commands.insert_resource(LogoData {
|
|
logo_entity: sprite_entity,
|
|
camera_entity,
|
|
});
|
|
}
|
|
|
|
fn fade_in_logo(
|
|
mut query: Query<(&mut Sprite, &mut Transform, &LogoTimer)>,
|
|
mut next_state: ResMut<NextState<AppState>>,
|
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
|
) {
|
|
let (mut sprite, mut transform, timer) = query.single_mut();
|
|
let elapsed = timer.elapsed_secs();
|
|
|
|
if timer.finished() || keyboard_input.get_pressed().len() > 0 {
|
|
next_state.set(AppState::LoadingMenu);
|
|
} else if elapsed > FULL_FADE_FINISHED {
|
|
sprite.color.set_a(keyframe::ease_with_scaled_time(
|
|
EaseInCubic,
|
|
FULL_FADE_FINISHED,
|
|
0.0,
|
|
elapsed,
|
|
FADE_OUT_TIME + FULL_FADE_FINISHED,
|
|
));
|
|
} else {
|
|
sprite.color.set_a(keyframe::ease_with_scaled_time(
|
|
Linear,
|
|
0.0,
|
|
1.0,
|
|
elapsed,
|
|
FADE_IN_TIME,
|
|
));
|
|
transform.scale = Vec3::splat(keyframe::ease_with_scaled_time(
|
|
EaseOutQuint,
|
|
2.0,
|
|
LOGO_FINISHED_SCALE,
|
|
elapsed,
|
|
ZOOM_OUT_TIME,
|
|
));
|
|
}
|
|
}
|
|
|
|
fn cleanup_logo(mut commands: Commands, logo_data: Res<LogoData>) {
|
|
commands.entity(logo_data.logo_entity).despawn_recursive();
|
|
commands.entity(logo_data.camera_entity).despawn_recursive();
|
|
commands.remove_resource::<LogoData>();
|
|
commands.remove_resource::<LogoAssets>();
|
|
}
|