Skip to content
Snippets Groups Projects
systems.rs 3.36 KiB
Newer Older
Louis's avatar
Louis committed
use bevy::prelude::*;
use bevy::render::texture::ImageSampler;
Louis's avatar
Louis committed
use iyes_loopless::state::NextState;
Louis's avatar
v2  
Louis committed
use micro_musicbox::music_box::MusicBox;
Louis's avatar
Louis committed

use crate::assets::AssetHandles;
use crate::splash_screen::components::{
	SplashAnimation, SplashAnimationBundle, SplashAnimationTimer, SplashAnimationType,
};
use crate::system::flow::AppState;
Louis's avatar
v2  
Louis committed
use crate::system::load_config::virtual_size;
Louis's avatar
Louis committed
use crate::system::utilities::f32_min;

const C_TRANS: Color = Color::rgba(1.0, 1.0, 1.0, 0.0);
const C_WHITE: Color = Color::rgba(1.0, 1.0, 1.0, 1.0);

fn interpolate_colours(from: Color, to: Color, percent: f32) -> Color {
	let diff_r = to.r() - from.r();
	let diff_g = to.g() - from.g();
	let diff_b = to.b() - from.b();
	let diff_a = to.a() - from.a();

	Color::rgba(
		from.r() + diff_r * percent,
		from.g() + diff_g * percent,
		from.b() + diff_b * percent,
		from.a() + diff_a * percent,
	)
}

pub fn setup_splash_screen(
	mut commands: Commands,
	mut image_assets: ResMut<Assets<Image>>,
	handles: Res<AssetHandles>,
	mut music_box: MusicBox<AssetHandles>,
) {
Louis's avatar
v2  
Louis committed
	let (window_width, window_height) = virtual_size();
Louis's avatar
Louis committed

	let handle = match handles.images.get("splash") {
		Some(handle) => handle,
		None => {
			log::error!("No splash image was found; Skipping");
			commands.insert_resource(NextState(AppState::Menu));
			return;
		}
	};
	let image_data = image_assets
		.get_mut(handle)
		.expect("An image was stored without the handle being persisted");

	commands.insert_resource(ClearColor(Color::hex("001122").unwrap()));

Louis's avatar
v2  
Louis committed
	let scale_factor = match window_width > window_height {
		true => window_height / image_data.texture_descriptor.size.height as f32,
		false => window_width / image_data.texture_descriptor.size.width as f32,
Louis's avatar
Louis committed
	};

	image_data.sampler_descriptor = ImageSampler::linear();
Louis's avatar
v2  
Louis committed
	music_box.play_sfx("splash_sting");
Louis's avatar
Louis committed

	commands
		.spawn_bundle(SpriteBundle {
			texture: handle.clone_weak(),
			sprite: Sprite {
				color: C_TRANS,
				..Default::default()
			},
			transform: Transform {
				scale: [scale_factor, scale_factor, 1.0].into(),
				..Default::default()
			},
			..Default::default()
		})
		.insert_bundle(SplashAnimationBundle::from_animation(
			SplashAnimation::wait(
				1.0,
				Some(Box::new(SplashAnimation::fade(
					C_TRANS,
					C_WHITE,
					1.0,
					Some(Box::new(SplashAnimation::wait(
						1.0,
						Some(Box::new(SplashAnimation::fade(
							C_WHITE,
							C_TRANS,
							0.75,
							Some(Box::new(SplashAnimation::wait(0.75, None))),
						))),
					))),
				))),
			),
		));
}

pub fn tick_splash_system(
	mut commands: Commands,
	time: Res<Time>,
	mut query: Query<(&mut Sprite, &mut SplashAnimation, &mut SplashAnimationTimer)>,
) {
	let tick = time.delta_seconds();
	for (mut sprite, mut anims, mut timer) in query.iter_mut() {
		timer.0 += tick;

		match anims.anim {
			SplashAnimationType::FadeColour { from, to } => {
				let percent = f32_min(1.0, timer.0 / anims.duration);
				sprite.color = interpolate_colours(from, to, percent);
			}
			SplashAnimationType::Wait => {}
		}

		if timer.0 >= anims.duration {
			timer.0 = 0.0;
			match &anims.then {
				Some(anim) => {
					*anims = *anim.clone();
				}
				None => {
					commands.insert_resource(NextState(AppState::Menu));
				}
			}
		}
	}
}

pub fn remove_splash_entities(mut commands: Commands, query: Query<Entity, With<SplashAnimation>>) {
	for entity in query.iter() {
		commands.entity(entity).despawn_recursive();
	}
}