diff --git a/game_core/src/entities/mod.rs b/game_core/src/entities/mod.rs index 13037dbe39af29500d714cea5a78c818e1367c67..89dfaa7f89d9e5af74214bd9c2585387419ea181 100644 --- a/game_core/src/entities/mod.rs +++ b/game_core/src/entities/mod.rs @@ -1,2 +1,16 @@ pub mod lifecycle; pub mod spawner; +pub mod timing; + +mod __plugin { + use bevy::app::{PluginGroup, PluginGroupBuilder}; + + pub struct EntitiesPluginGroup; + impl PluginGroup for EntitiesPluginGroup { + fn build(&mut self, group: &mut PluginGroupBuilder) { + group.add(super::timing::TimingPlugin); + } + } +} + +pub use __plugin::EntitiesPluginGroup; diff --git a/game_core/src/entities/timing.rs b/game_core/src/entities/timing.rs new file mode 100644 index 0000000000000000000000000000000000000000..e6c35869ce39ec564a6877eb11b658c58da1982f --- /dev/null +++ b/game_core/src/entities/timing.rs @@ -0,0 +1,95 @@ +use std::time::Duration; + +use bevy::prelude::*; +use iyes_loopless::prelude::{AppLooplessStateExt, ConditionSet}; + +use crate::system::flow::AppState; + +#[derive(Debug)] +pub struct GlobalTimer { + internal: Duration, +} + +impl Default for GlobalTimer { + fn default() -> Self { + GlobalTimer { + internal: Duration::ZERO, + } + } +} + +impl GlobalTimer { + const GOAL: Duration = Duration::from_secs(10); + pub fn tick(&mut self, dt: Duration) { + self.internal += dt; + } + pub fn is_triggered(&self) -> bool { + self.internal >= Self::GOAL + } + pub fn settle(&mut self) { + while self.internal >= Self::GOAL { + self.internal -= Self::GOAL + } + } + pub fn percent_complete(&self) -> f32 { + self.internal.as_secs_f32() / Self::GOAL.as_secs_f32() + } +} + +pub fn tick_global_timer(time: Res<Time>, mut timer: ResMut<GlobalTimer>) { + timer.settle(); + timer.tick(time.delta()); +} + +#[derive(Copy, Clone, Default, Component)] +pub struct GlobalTimerUi; +pub fn spawn_global_timer_ui(mut commands: Commands, timer: Res<GlobalTimer>) { + commands + .spawn_bundle(NodeBundle { + style: Style { + size: Size::new(Val::Auto, Val::Px(25.0)), + position_type: PositionType::Absolute, + position: UiRect::new( + Val::Px(0.0), + Val::Percent((1.0 - timer.percent_complete()) * 100.0), + Val::Auto, + Val::Px(0.0), + ), + ..Default::default() + }, + color: Color::ALICE_BLUE.into(), + ..Default::default() + }) + .insert(GlobalTimerUi); +} + +pub fn update_global_timer_ui( + timer: Res<GlobalTimer>, + mut query: Query<&mut Style, With<GlobalTimerUi>>, +) { + for mut style in &mut query { + style.position.right = Val::Percent((1.0 - timer.percent_complete()) * 100.0); + } +} + +pub fn remove_global_timer_ui(mut commands: Commands, query: Query<Entity, With<GlobalTimerUi>>) { + for entity in &query { + commands.entity(entity).despawn_recursive(); + } +} + +pub struct TimingPlugin; +impl Plugin for TimingPlugin { + fn build(&self, app: &mut App) { + app.init_resource::<GlobalTimer>() + .add_system_to_stage(CoreStage::First, tick_global_timer) + .add_enter_system(AppState::InGame, spawn_global_timer_ui) + .add_system_set( + ConditionSet::new() + .run_in_state(AppState::InGame) + .with_system(update_global_timer_ui) + .into(), + ) + .add_exit_system(AppState::InGame, remove_global_timer_ui); + } +} diff --git a/game_core/src/main.rs b/game_core/src/main.rs index 9e165a9060d5f313726a791cae039629f1bfe09d..4823b6c706c61a0263cd61189cb5973d49c3997a 100644 --- a/game_core/src/main.rs +++ b/game_core/src/main.rs @@ -22,5 +22,6 @@ fn main() { .add_plugin(game_core::debug::DebugPlugin) .add_plugin(game_core::world::WorldPlugin) .add_plugin(game_core::control::ControlPlugin) + .add_plugins(game_core::entities::EntitiesPluginGroup) .run(); } diff --git a/game_core/src/system/resources.rs b/game_core/src/system/resources.rs index cab2bb41f4b06c203ba2eafed356374142e0d811..b684f08f0a08df34993c50af2237a907c8b2192d 100644 --- a/game_core/src/system/resources.rs +++ b/game_core/src/system/resources.rs @@ -11,8 +11,8 @@ impl Plugin for DefaultResourcesPlugin { let (width, height) = initial_size(); app.insert_resource(WindowDescriptor { - width, - height, + width: width * 2.0, + height: height * 2.0, resizable: true, title: String::from("Ludum Dare 51"), present_mode: PresentMode::AutoNoVsync,