wrire up ammo and health in head_ui
This commit is contained in:
@@ -153,6 +153,7 @@ fn sync(
|
||||
new_state = Some(BackpackHead {
|
||||
head: head.0,
|
||||
health: hp.health(),
|
||||
ammo: 1.,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,29 @@ use bevy::prelude::*;
|
||||
|
||||
pub use backpack_ui::BackpackAction;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Reflect)]
|
||||
pub struct BackpackHead {
|
||||
pub head: usize,
|
||||
pub health: f32,
|
||||
pub ammo: f32,
|
||||
}
|
||||
|
||||
impl BackpackHead {
|
||||
pub fn new(head: usize) -> Self {
|
||||
Self {
|
||||
head,
|
||||
health: 1.0,
|
||||
ammo: 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn damage(&self) -> f32 {
|
||||
1. - self.health
|
||||
}
|
||||
|
||||
pub fn ammo_used(&self) -> f32 {
|
||||
1. - self.ammo
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
@@ -37,6 +50,7 @@ fn setup(mut commands: Commands) {
|
||||
.map(|i| BackpackHead {
|
||||
head: i,
|
||||
health: 1.,
|
||||
ammo: 1.,
|
||||
})
|
||||
.collect(),
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::{
|
||||
sounds::PlaySound,
|
||||
};
|
||||
use bevy::prelude::*;
|
||||
use bevy_ui_gradients::{AngularColorStop, BackgroundGradient, ConicGradient, Position};
|
||||
use bevy_ui_gradients::{AngularColorStop, BackgroundGradient, ConicGradient, Gradient, Position};
|
||||
use std::f32::consts::PI;
|
||||
|
||||
pub static HEAD_COUNT: usize = 18;
|
||||
@@ -35,9 +35,10 @@ pub struct HeadsImages {
|
||||
pub heads: Vec<Handle<Image>>,
|
||||
}
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
#[derive(Resource, Default, Reflect)]
|
||||
#[reflect(Resource)]
|
||||
pub struct ActiveHeads {
|
||||
heads: [Option<usize>; 5],
|
||||
heads: [Option<BackpackHead>; 5],
|
||||
current_slot: usize,
|
||||
}
|
||||
|
||||
@@ -46,8 +47,13 @@ pub struct HeadChanged(pub usize);
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
app.register_type::<HeadDamage>();
|
||||
app.register_type::<ActiveHeads>();
|
||||
|
||||
app.add_systems(OnEnter(GameState::Playing), setup);
|
||||
app.add_systems(Update, update.run_if(in_state(GameState::Playing)));
|
||||
app.add_systems(
|
||||
Update,
|
||||
(update, update_ammo, update_health).run_if(in_state(GameState::Playing)),
|
||||
);
|
||||
app.add_observer(on_select_active_head);
|
||||
app.add_observer(on_swap_backpack);
|
||||
}
|
||||
@@ -82,7 +88,13 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, assets: Res<UIA
|
||||
commands.insert_resource(HeadsImages { heads });
|
||||
|
||||
commands.insert_resource(ActiveHeads {
|
||||
heads: [Some(0), Some(3), Some(6), Some(8), Some(9)],
|
||||
heads: [
|
||||
Some(BackpackHead::new(0)),
|
||||
Some(BackpackHead::new(3)),
|
||||
Some(BackpackHead::new(6)),
|
||||
Some(BackpackHead::new(8)),
|
||||
Some(BackpackHead::new(9)),
|
||||
],
|
||||
current_slot: 0,
|
||||
});
|
||||
}
|
||||
@@ -117,6 +129,7 @@ fn spawn_head_ui(
|
||||
ImageNode::new(selector),
|
||||
HeadSelector(head_slot),
|
||||
));
|
||||
|
||||
parent.spawn((
|
||||
Node {
|
||||
position_type: PositionType::Absolute,
|
||||
@@ -125,12 +138,20 @@ fn spawn_head_ui(
|
||||
ImageNode::new(bg),
|
||||
));
|
||||
parent.spawn((
|
||||
Name::new("head-icon"),
|
||||
Node {
|
||||
position_type: PositionType::Absolute,
|
||||
// width: Val::Px(66.0),
|
||||
// height: Val::Px(66.0),
|
||||
..default()
|
||||
},
|
||||
BorderRadius::all(Val::Px(9999.)),
|
||||
BackgroundGradient::from(ConicGradient {
|
||||
stops: vec![
|
||||
AngularColorStop::new(Color::linear_rgba(0., 0., 0., 0.9), 0.),
|
||||
AngularColorStop::new(Color::linear_rgba(0., 0., 0., 0.9), PI * 1.5),
|
||||
AngularColorStop::new(Color::linear_rgba(0., 0., 0., 0.0), PI * 1.5),
|
||||
],
|
||||
position: Position::CENTER,
|
||||
}),
|
||||
ImageNode::default(),
|
||||
Visibility::Hidden,
|
||||
HeadImage(head_slot),
|
||||
@@ -140,16 +161,7 @@ fn spawn_head_ui(
|
||||
position_type: PositionType::Absolute,
|
||||
..default()
|
||||
},
|
||||
BorderRadius::all(Val::Px(9999.)),
|
||||
ImageNode::new(regular),
|
||||
BackgroundGradient::from(ConicGradient {
|
||||
stops: vec![
|
||||
AngularColorStop::new(Color::linear_rgba(0., 0., 0., 0.9), 0.),
|
||||
AngularColorStop::new(Color::linear_rgba(0., 0., 0., 0.9), PI * 1.5),
|
||||
AngularColorStop::new(Color::linear_rgba(0., 0., 0., 0.0), PI * 1.5),
|
||||
],
|
||||
position: Position::CENTER,
|
||||
}),
|
||||
));
|
||||
parent
|
||||
.spawn((Node {
|
||||
@@ -187,7 +199,7 @@ fn update(
|
||||
for (HeadImage(head), mut vis, mut image) in head_image.iter_mut() {
|
||||
if let Some(head) = res.heads[*head] {
|
||||
*vis = Visibility::Visible;
|
||||
image.image = heads_images.heads[head].clone();
|
||||
image.image = heads_images.heads[head.head].clone();
|
||||
} else {
|
||||
*vis = Visibility::Hidden;
|
||||
}
|
||||
@@ -202,6 +214,31 @@ fn update(
|
||||
}
|
||||
}
|
||||
|
||||
fn update_ammo(res: Res<ActiveHeads>, mut gradients: Query<(&mut BackgroundGradient, &HeadImage)>) {
|
||||
if res.is_changed() {
|
||||
for (mut gradient, HeadImage(head)) in gradients.iter_mut() {
|
||||
if let Some(head) = res.heads[*head] {
|
||||
let ammo_used = head.ammo_used();
|
||||
let Gradient::Conic(gradient) = &mut gradient.0[0] else {
|
||||
continue;
|
||||
};
|
||||
let angle = PI * 2. * ammo_used;
|
||||
gradient.stops[1].angle = Some(angle);
|
||||
gradient.stops[2].angle = Some(angle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_health(res: Res<ActiveHeads>, mut query: Query<(&mut Node, &HeadDamage)>) {
|
||||
if res.is_changed() {
|
||||
for (mut node, HeadDamage(head)) in query.iter_mut() {
|
||||
node.height =
|
||||
Val::Percent(res.heads[*head].map(|head| head.damage()).unwrap_or(0.) * 100.);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn on_select_active_head(
|
||||
trigger: Trigger<SelectActiveHead>,
|
||||
mut commands: Commands,
|
||||
@@ -217,7 +254,7 @@ fn on_select_active_head(
|
||||
}
|
||||
|
||||
commands.trigger(PlaySound::Selection);
|
||||
commands.trigger(HeadChanged(res.heads[res.current_slot].unwrap()));
|
||||
commands.trigger(HeadChanged(res.heads[res.current_slot].unwrap().head));
|
||||
}
|
||||
|
||||
fn on_swap_backpack(
|
||||
@@ -233,16 +270,13 @@ fn on_swap_backpack(
|
||||
let current_active_slot = res.current_slot;
|
||||
|
||||
let current_active_head = res.heads[current_active_slot];
|
||||
res.heads[current_active_slot] = Some(head.head);
|
||||
res.heads[current_active_slot] = Some(*head);
|
||||
|
||||
if let Some(old_active) = current_active_head {
|
||||
backpack.heads[backpack_slot] = BackpackHead {
|
||||
head: old_active,
|
||||
health: 1.,
|
||||
};
|
||||
backpack.heads[backpack_slot] = old_active;
|
||||
} else {
|
||||
backpack.heads.remove(backpack_slot);
|
||||
}
|
||||
|
||||
commands.trigger(HeadChanged(res.heads[res.current_slot].unwrap()));
|
||||
commands.trigger(HeadChanged(res.heads[res.current_slot].unwrap().head));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user