diff --git a/src/level_ui.rs b/src/level_ui.rs index f72b232..ae51d23 100644 --- a/src/level_ui.rs +++ b/src/level_ui.rs @@ -1,13 +1,14 @@ use bevy::prelude::*; -use crate::{storyteller::LevelTimer, GameStuff}; +use crate::{storyteller::LevelTimer, GameStuff, player::Stamina, GameSet}; pub struct LevelUiPlugin; impl Plugin for LevelUiPlugin { fn build(&self, app: &mut App) { app.add_event::() - .add_systems(Update, create_level_ui_system); + .add_systems(Update, create_level_ui_system) + .add_systems(Update, show_stamina.in_set(GameSet::Playing)); } } @@ -17,9 +18,13 @@ pub struct CreateLevelUi; #[derive(Component)] pub struct LevelUi; + #[derive(Component)] pub struct TaskText; +#[derive(Component)] +pub struct StaminaState; + fn create_level_ui_system( mut commands: Commands, _asset_server: Res, @@ -34,53 +39,123 @@ fn create_level_ui_system( //Spawn top info bar commands + .spawn(NodeBundle { + style: Style { + width: Val::Percent(100.0), + justify_content: JustifyContent::Center, + align_items: AlignItems::Center, + + top: Val::Px(0.0), + left: Val::Px(0.0), + ..default() + }, + ..default() + }).with_children(|parent| { + parent.spawn(( + NodeBundle { + style: Style { + width: Val::Percent(80.0), + flex_direction: FlexDirection::Column, + justify_content: JustifyContent::Center, + align_items: AlignItems::Center, + min_height: Val::Px(150.0), + ..default() + }, + background_color: BackgroundColor(Color::rgba(0.0, 0.0, 0.0, 0.5)), + ..default() + }, + LevelUi, + GameStuff, + )) + .with_children(|parent| { + parent.spawn(( + TextBundle::from_section("", text_style.clone()), + LevelUi, + LevelTimer, + )); + + parent.spawn(( + TextBundle::from_section( + "", + text_style.clone() + ), + LevelUi, + TaskText + )); + + spawn_bar(parent); + }); + }); + + ev_create_level_ui.clear(); +} + +fn spawn_bar(parent: &mut ChildBuilder) { + parent .spawn(NodeBundle { style: Style { - width: Val::Percent(100.0), - height: Val::Px(100.0), - justify_content: JustifyContent::Center, + height: Val::Px(10.0), + width: Val::Px(200.0), align_items: AlignItems::Center, - align_self: AlignSelf::Stretch, - top: Val::Px(0.0), - left: Val::Px(0.0), - ..default() + justify_content: JustifyContent::Center, + flex_direction: FlexDirection::Row, + ..Default::default() }, - ..default() + ..Default::default() }) .with_children(|parent| { + + parent.spawn(TextBundle::from_section("Stamina", TextStyle::default())); + parent - .spawn(( - NodeBundle { - style: Style { - width: Val::Percent(50.0), - height: Val::Px(100.0), - flex_direction: FlexDirection::Column, - justify_content: JustifyContent::Center, - align_items: AlignItems::Center, - - align_self: AlignSelf::Stretch, - ..default() - }, - background_color: BackgroundColor(Color::rgba(0.0, 0.0, 0.0, 0.5)), - ..default() + .spawn(NodeBundle { + style: Style { + width: Val::Px(100.), + height: Val::Px(10.), + padding: UiRect::all(Val::Px(1.)), + align_items: AlignItems::Stretch, + top: Val::Px(2.0), + left: Val::Px(6.0), + ..Default::default() }, - LevelUi, - GameStuff, - )) + background_color: Color::BLACK.into(), + ..Default::default() + }) .with_children(|parent| { parent.spawn(( - TextBundle::from_section("", text_style.clone()), - LevelUi, - LevelTimer, - )); - - parent.spawn(( - TextBundle::from_section("", text_style.clone()), - LevelUi, - TaskText, + NodeBundle { + style: Style { + width : Val::Percent(50.0), + ..Default::default() + }, + background_color: Color::GREEN.into(), + ..Default::default() + }, + StaminaState, )); }); }); - - ev_create_level_ui.clear(); } + +fn show_stamina( + mut query: Query<(&mut Style, &mut BackgroundColor), With>, + staminas : Query<&Stamina> +) { + let Ok(stamina) = staminas.get_single() else { + warn!("Stamina not found"); + return; + }; + + let Ok((mut style, mut background_color)) = query.get_single_mut() else { + warn!("Stamina ui not found"); + return; + }; + + style.width = Val::Percent(stamina.value * 100.0); + + if stamina.blocked { + background_color.0 = Color::ORANGE_RED; + } else { + background_color.0 = Color::GREEN; + } +} \ No newline at end of file diff --git a/src/player.rs b/src/player.rs index 095c493..23cb575 100644 --- a/src/player.rs +++ b/src/player.rs @@ -9,7 +9,7 @@ use crate::{ get_sprite_rotation, physics::Velocity, sprite_material::{create_plane_mesh, SpriteExtension, SpriteMaterial}, - GameStuff, + GameStuff, GameSet, }; const DOG_PATH: &str = "test/dog.png"; @@ -17,6 +17,10 @@ const DOG_PATH: &str = "test/dog.png"; pub const DOG_SPEED: f32 = 45.0 * 1000.0 / 3600.0; // Sheepdog accepts 35 km/h in reality (but fastest dog can do 67 km/h o.0) pub const DOG_ACCELERATION: f32 = DOG_SPEED * 4.0; +pub const RUN_K: f32 = 1.5; +pub const STAMINA_INCREASE: f32 = 1.0 / 2.5; +pub const STAMINA_DECREASE: f32 = 1.0 / 5.0 + STAMINA_INCREASE; + pub struct PlayerPlugin; #[derive(Default, Hash, PartialEq, Eq, Debug, States, Clone)] @@ -31,7 +35,7 @@ impl Plugin for PlayerPlugin { app.add_event::() .add_event::() .add_state::() - .add_systems(Update, spawn_player_by_event) + .add_systems(Update, spawn_player_by_event.in_set(GameSet::Playing)) .add_systems( Update, player_movemnt_by_wasd.run_if(in_state(MovementStyle::WASD)), @@ -40,11 +44,17 @@ impl Plugin for PlayerPlugin { Update, player_movemnt_by_mouse.run_if(in_state(MovementStyle::Mouse)), ) - .add_systems(Update, (change_movement_style, bark)) - .add_systems(Update, (set_cam_distance, camera_movement)); + .add_systems(Update, (change_movement_style, bark).in_set(GameSet::Playing)) + .add_systems(Update, (set_cam_distance, camera_movement, stamina_increse).in_set(GameSet::Playing)); } } +#[derive(Component)] +pub struct Stamina { + pub value: f32, + pub blocked: bool +} + fn change_movement_style( mut next_state: ResMut>, current_state: Res>, @@ -59,6 +69,19 @@ fn change_movement_style( } } +fn stamina_increse( + mut stamina_query: Query<&mut Stamina>, + time: Res